/* finish a smbcli_transport_connect() */ NTSTATUS smbcli_transport_connect_recv(struct smbcli_request *req) { NTSTATUS status; if (!smbcli_request_receive(req)) { smbcli_request_destroy(req); return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } switch (CVAL(req->in.buffer,0)) { case 0x82: status = NT_STATUS_OK; break; case 0x83: status = map_session_refused_error(CVAL(req->in.buffer,4)); break; case 0x84: DEBUG(1,("Warning: session retarget not supported\n")); status = NT_STATUS_NOT_SUPPORTED; break; default: status = NT_STATUS_UNEXPECTED_IO_ERROR; break; } smbcli_request_destroy(req); return status; }
/**************************************************************************** Old style search next. ****************************************************************************/ static NTSTATUS smb_raw_search_close_old(struct smbcli_tree *tree, union smb_search_close *io) { struct smbcli_request *req; uint8_t var_block[21]; req = smbcli_request_setup(tree, SMBfclose, 2, 0); if (!req) { return NT_STATUS_NO_MEMORY; } SSVAL(req->out.vwv, VWV(0), io->fclose.in.max_count); SSVAL(req->out.vwv, VWV(1), io->fclose.in.search_attrib); smbcli_req_append_ascii4(req, "", STR_TERMINATE); SCVAL(var_block, 0, io->fclose.in.id.reserved); memcpy(&var_block[1], io->fclose.in.id.name, 11); SCVAL(var_block, 12, io->fclose.in.id.handle); SIVAL(var_block, 13, io->fclose.in.id.server_cookie); SIVAL(var_block, 17, io->fclose.in.id.client_cookie); smbcli_req_append_var_block(req, var_block, 21); if (!smbcli_request_send(req) || !smbcli_request_receive(req)) { return smbcli_request_destroy(req); } return smbcli_request_destroy(req); }
/**************************************************************************** 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); }
/* scan for valid base SMB requests */ bool torture_smb_scan(struct torture_context *torture) { static struct smbcli_state *cli; int op; struct smbcli_request *req; NTSTATUS status; for (op=0x0;op<=0xFF;op++) { if (op == SMBreadbraw) continue; if (!torture_open_connection(&cli, torture, 0)) { return false; } req = smbcli_request_setup(cli->tree, op, 0, 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); break; } usleep(10000); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); torture_close_connection(cli); continue; } sleep(1); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); } else { printf("op=0x%x no reply\n", op); smbcli_request_destroy(req); continue; /* don't attempt close! */ } torture_close_connection(cli); } printf("smb scan finished\n"); return true; }
/**************************************************************************** Close a file - async send ****************************************************************************/ _PUBLIC_ struct smbcli_request *smb_raw_close_send(struct smbcli_tree *tree, union smb_close *parms) { struct smbcli_request *req = NULL; switch (parms->generic.level) { case RAW_CLOSE_CLOSE: SETUP_REQUEST(SMBclose, 3, 0); SSVAL(req->out.vwv, VWV(0), parms->close.in.file.fnum); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(1), parms->close.in.write_time); break; case RAW_CLOSE_SPLCLOSE: SETUP_REQUEST(SMBsplclose, 3, 0); SSVAL(req->out.vwv, VWV(0), parms->splclose.in.file.fnum); SIVAL(req->out.vwv, VWV(1), 0); /* reserved */ break; case RAW_CLOSE_SMB2: case RAW_CLOSE_GENERIC: return NULL; } if (!req) return NULL; if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
static struct smbcli_request *smb_raw_openX_name_blob_send(struct smbcli_tree *tree, union smb_open *parms, const DATA_BLOB *pname_blob) { struct smbcli_request *req = NULL; if (parms->generic.level != RAW_OPEN_OPENX) { return NULL; } SETUP_REQUEST(SMBopenX, 15, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->openx.in.flags); SSVAL(req->out.vwv, VWV(3), parms->openx.in.open_mode); SSVAL(req->out.vwv, VWV(4), parms->openx.in.search_attrs); SSVAL(req->out.vwv, VWV(5), parms->openx.in.file_attrs); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(6), parms->openx.in.write_time); SSVAL(req->out.vwv, VWV(8), parms->openx.in.open_func); SIVAL(req->out.vwv, VWV(9), parms->openx.in.size); SIVAL(req->out.vwv, VWV(11),parms->openx.in.timeout); SIVAL(req->out.vwv, VWV(13),0); /* reserved */ smbcli_req_append_blob(req, pname_blob); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Rename a file - async interface ****************************************************************************/ struct smbcli_request *smb_raw_rename_send(struct smbcli_tree *tree, union smb_rename *parms) { struct smbcli_request *req = NULL; struct smb_nttrans nt; TALLOC_CTX *mem_ctx; switch (parms->generic.level) { case RAW_RENAME_RENAME: SETUP_REQUEST(SMBmv, 1, 0); SSVAL(req->out.vwv, VWV(0), parms->rename.in.attrib); smbcli_req_append_ascii4(req, parms->rename.in.pattern1, STR_TERMINATE); smbcli_req_append_ascii4(req, parms->rename.in.pattern2, STR_TERMINATE); break; case RAW_RENAME_NTRENAME: SETUP_REQUEST(SMBntrename, 4, 0); SSVAL(req->out.vwv, VWV(0), parms->ntrename.in.attrib); SSVAL(req->out.vwv, VWV(1), parms->ntrename.in.flags); SIVAL(req->out.vwv, VWV(2), parms->ntrename.in.cluster_size); smbcli_req_append_ascii4(req, parms->ntrename.in.old_name, STR_TERMINATE); smbcli_req_append_ascii4(req, parms->ntrename.in.new_name, STR_TERMINATE); break; case RAW_RENAME_NTTRANS: mem_ctx = talloc_new(tree); nt.in.max_setup = 0; nt.in.max_param = 0; nt.in.max_data = 0; nt.in.setup_count = 0; nt.in.setup = NULL; nt.in.function = NT_TRANSACT_RENAME; nt.in.params = data_blob_talloc(mem_ctx, NULL, 4); nt.in.data = data_blob(NULL, 0); SSVAL(nt.in.params.data, VWV(0), parms->nttrans.in.file.fnum); SSVAL(nt.in.params.data, VWV(1), parms->nttrans.in.flags); smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params, parms->nttrans.in.new_name, STR_TERMINATE); req = smb_raw_nttrans_send(tree, &nt); talloc_free(mem_ctx); return req; } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Old style search next. ****************************************************************************/ static NTSTATUS smb_raw_search_next_old(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_search_next *io, void *private_data, smbcli_search_callback callback) { struct smbcli_request *req; uint8_t var_block[21]; uint8_t op = SMBsearch; if (io->generic.level == RAW_SEARCH_FFIRST) { op = SMBffirst; } req = smbcli_request_setup(tree, op, 2, 0); if (!req) { return NT_STATUS_NO_MEMORY; } SSVAL(req->out.vwv, VWV(0), io->search_next.in.max_count); SSVAL(req->out.vwv, VWV(1), io->search_next.in.search_attrib); smbcli_req_append_ascii4(req, "", STR_TERMINATE); SCVAL(var_block, 0, io->search_next.in.id.reserved); memcpy(&var_block[1], io->search_next.in.id.name, 11); SCVAL(var_block, 12, io->search_next.in.id.handle); SIVAL(var_block, 13, io->search_next.in.id.server_cookie); SIVAL(var_block, 17, io->search_next.in.id.client_cookie); smbcli_req_append_var_block(req, var_block, 21); if (!smbcli_request_send(req) || !smbcli_request_receive(req)) { return smbcli_request_destroy(req); } if (NT_STATUS_IS_OK(req->status)) { io->search_next.out.count = SVAL(req->in.vwv, VWV(0)); smb_raw_search_backend(req, mem_ctx, io->search_next.out.count, private_data, callback); } return smbcli_request_destroy(req); }
/**************************************************************************** Send a exit (async send) *****************************************************************************/ struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session) { struct smbcli_request *req; SETUP_REQUEST_SESSION(SMBexit, 0, 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Query FS Info - SMBdskattr call (async send) ****************************************************************************/ static struct smbcli_request *smb_raw_dskattr_send(struct smbcli_tree *tree, union smb_fsinfo *fsinfo) { struct smbcli_request *req; req = smbcli_request_setup(tree, SMBdskattr, 0, 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Old style search first. ****************************************************************************/ static NTSTATUS smb_raw_search_first_old(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_search_first *io, void *private_data, smbcli_search_callback callback) { struct smbcli_request *req; uint8_t op = SMBsearch; if (io->generic.level == RAW_SEARCH_FFIRST) { op = SMBffirst; } else if (io->generic.level == RAW_SEARCH_FUNIQUE) { op = SMBfunique; } req = smbcli_request_setup(tree, op, 2, 0); if (!req) { return NT_STATUS_NO_MEMORY; } SSVAL(req->out.vwv, VWV(0), io->search_first.in.max_count); SSVAL(req->out.vwv, VWV(1), io->search_first.in.search_attrib); smbcli_req_append_ascii4(req, io->search_first.in.pattern, STR_TERMINATE); smbcli_req_append_var_block(req, NULL, 0); if (!smbcli_request_send(req) || !smbcli_request_receive(req)) { return smbcli_request_destroy(req); } if (NT_STATUS_IS_OK(req->status)) { io->search_first.out.count = SVAL(req->in.vwv, VWV(0)); smb_raw_search_backend(req, mem_ctx, io->search_first.out.count, private_data, callback); } return smbcli_request_destroy(req); }
/* send a session request */ struct smbcli_request *smbcli_transport_connect_send(struct smbcli_transport *transport, struct nbt_name *calling, struct nbt_name *called) { uint8_t *p; struct smbcli_request *req; DATA_BLOB calling_blob, called_blob; TALLOC_CTX *tmp_ctx = talloc_new(transport); NTSTATUS status; status = nbt_name_dup(transport, called, &transport->called); if (!NT_STATUS_IS_OK(status)) goto failed; status = nbt_name_to_blob(tmp_ctx, &calling_blob, calling); if (!NT_STATUS_IS_OK(status)) goto failed; status = nbt_name_to_blob(tmp_ctx, &called_blob, called); if (!NT_STATUS_IS_OK(status)) goto failed; /* allocate output buffer */ req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + calling_blob.length + called_blob.length); if (req == NULL) goto failed; /* put in the destination name */ p = req->out.buffer + NBT_HDR_SIZE; memcpy(p, called_blob.data, called_blob.length); p += called_blob.length; memcpy(p, calling_blob.data, calling_blob.length); p += calling_blob.length; _smb_setlen(req->out.buffer, PTR_DIFF(p, req->out.buffer) - NBT_HDR_SIZE); SCVAL(req->out.buffer,0,0x81); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); goto failed; } talloc_free(tmp_ctx); return req; failed: talloc_free(tmp_ctx); return NULL; }
/**************************************************************************** Remove a directory - async interface ****************************************************************************/ struct smbcli_request *smb_raw_rmdir_send(struct smbcli_tree *tree, struct smb_rmdir *parms) { struct smbcli_request *req; SETUP_REQUEST(SMBrmdir, 0, 0); smbcli_req_append_ascii4(req, parms->in.path, STR_TERMINATE); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Delete a file - async interface ****************************************************************************/ struct smbcli_request *smb_raw_unlink_send(struct smbcli_tree *tree, union smb_unlink *parms) { struct smbcli_request *req; SETUP_REQUEST(SMBunlink, 1, 0); SSVAL(req->out.vwv, VWV(0), parms->unlink.in.attrib); smbcli_req_append_ascii4(req, parms->unlink.in.pattern, STR_TERMINATE); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** Send a ulogoff (async send) *****************************************************************************/ struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session) { struct smbcli_request *req; SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/* disconnect from a share */ static NTSTATUS cvfs_disconnect(struct ntvfs_module_context *ntvfs) { struct cvfs_private *p = ntvfs->private_data; struct async_info *a, *an; /* first cleanup pending requests */ for (a=p->pending; a; a = an) { an = a->next; smbcli_request_destroy(a->c_req); talloc_free(a); } talloc_free(p); ntvfs->private_data = NULL; return NT_STATUS_OK; }
/**************************************************************************** Query FS Info - SMBdskattr call (async recv) ****************************************************************************/ static NTSTATUS smb_raw_dskattr_recv(struct smbcli_request *req, union smb_fsinfo *fsinfo) { if (!smbcli_request_receive(req) || smbcli_request_is_error(req)) { goto failed; } SMBCLI_CHECK_WCT(req, 5); fsinfo->dskattr.out.units_total = SVAL(req->in.vwv, VWV(0)); fsinfo->dskattr.out.blocks_per_unit = SVAL(req->in.vwv, VWV(1)); fsinfo->dskattr.out.block_size = SVAL(req->in.vwv, VWV(2)); fsinfo->dskattr.out.units_free = SVAL(req->in.vwv, VWV(3)); failed: return smbcli_request_destroy(req); }
/* put a request into the send queue */ void smbcli_transport_send(struct smbcli_request *req) { DATA_BLOB blob; NTSTATUS status; /* check if the transport is dead */ if (req->transport->socket->sock == NULL) { req->state = SMBCLI_REQUEST_ERROR; req->status = NT_STATUS_NET_WRITE_FAULT; return; } blob = data_blob_const(req->out.buffer, req->out.size); status = packet_send(req->transport->packet, blob); if (!NT_STATUS_IS_OK(status)) { req->state = SMBCLI_REQUEST_ERROR; req->status = status; return; } packet_queue_run(req->transport->packet); if (req->transport->socket->sock == NULL) { req->state = SMBCLI_REQUEST_ERROR; req->status = NT_STATUS_NET_WRITE_FAULT; return; } if (req->one_way_request) { req->state = SMBCLI_REQUEST_DONE; smbcli_request_destroy(req); return; } req->state = SMBCLI_REQUEST_RECV; DLIST_ADD(req->transport->pending_recv, req); /* add a timeout */ if (req->transport->options.request_timeout) { event_add_timed(req->transport->socket->event.ctx, req, timeval_current_ofs(req->transport->options.request_timeout, 0), smbcli_timeout_handler, req); } talloc_set_destructor(req, smbcli_request_destructor); }
/**************************************************************************** Send an SMBecho (async send) *****************************************************************************/ _PUBLIC_ struct smbcli_request *smb_raw_echo_send(struct smbcli_transport *transport, struct smb_echo *p) { struct smbcli_request *req; req = smbcli_request_setup_transport(transport, SMBecho, 1, p->in.size); if (!req) return NULL; SSVAL(req->out.vwv, VWV(0), p->in.repeat_count); memcpy(req->out.data, p->in.data, p->in.size); ZERO_STRUCT(p->out); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/* Send a negprot command. */ struct smbcli_request *smb_raw_negotiate_send(struct smbcli_transport *transport, bool unicode, int maxprotocol) { struct smbcli_request *req; int i; uint16_t flags2 = 0; req = smbcli_request_setup_transport(transport, SMBnegprot, 0, 0); if (!req) { return NULL; } flags2 |= FLAGS2_32_BIT_ERROR_CODES; if (unicode) { flags2 |= FLAGS2_UNICODE_STRINGS; } flags2 |= FLAGS2_EXTENDED_ATTRIBUTES; flags2 |= FLAGS2_LONG_PATH_COMPONENTS; flags2 |= FLAGS2_IS_LONG_NAME; if (transport->options.use_spnego) { flags2 |= FLAGS2_EXTENDED_SECURITY; } SSVAL(req->out.hdr,HDR_FLG2, flags2); /* setup the protocol strings */ for (i=0; i < ARRAY_SIZE(prots) && prots[i].prot <= maxprotocol; i++) { smbcli_req_append_bytes(req, (const uint8_t *)"\2", 1); smbcli_req_append_string(req, prots[i].name, STR_TERMINATE | STR_ASCII); } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/* Implements trans2findclose2 */ NTSTATUS smb_raw_search_close(struct smbcli_tree *tree, union smb_search_close *io) { struct smbcli_request *req; if (io->generic.level == RAW_FINDCLOSE_FCLOSE) { return smb_raw_search_close_old(tree, io); } req = smbcli_request_setup(tree, SMBfindclose, 1, 0); if (!req) { return NT_STATUS_NO_MEMORY; } SSVAL(req->out.vwv, VWV(0), io->findclose.in.handle); if (smbcli_request_send(req)) { (void) smbcli_request_receive(req); } return smbcli_request_destroy(req); }
/**************************************************************************** raw write interface (async recv) ****************************************************************************/ NTSTATUS smb_raw_write_recv(struct smbcli_request *req, union smb_write *parms) { if (!smbcli_request_receive(req) || !NT_STATUS_IS_OK(req->status)) { goto failed; } switch (parms->generic.level) { case RAW_WRITE_WRITEUNLOCK: SMBCLI_CHECK_WCT(req, 1); parms->writeunlock.out.nwritten = SVAL(req->in.vwv, VWV(0)); break; case RAW_WRITE_WRITE: SMBCLI_CHECK_WCT(req, 1); parms->write.out.nwritten = SVAL(req->in.vwv, VWV(0)); break; case RAW_WRITE_WRITECLOSE: SMBCLI_CHECK_WCT(req, 1); parms->writeclose.out.nwritten = SVAL(req->in.vwv, VWV(0)); break; case RAW_WRITE_WRITEX: SMBCLI_CHECK_WCT(req, 6); parms->writex.out.nwritten = SVAL(req->in.vwv, VWV(2)); parms->writex.out.nwritten += (CVAL(req->in.vwv, VWV(4)) << 16); parms->writex.out.remaining = SVAL(req->in.vwv, VWV(3)); break; case RAW_WRITE_SPLWRITE: break; case RAW_WRITE_SMB2: req->status = NT_STATUS_INTERNAL_ERROR; break; } failed: return smbcli_request_destroy(req); }
/**************************************************************************** Perform a session setup (async recv) ****************************************************************************/ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, union smb_sesssetup *parms) { uint16_t len; uint8_t *p; if (!smbcli_request_receive(req)) { return smbcli_request_destroy(req); } if (!NT_STATUS_IS_OK(req->status) && !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) { return smbcli_request_destroy(req); } switch (parms->old.level) { case RAW_SESSSETUP_OLD: SMBCLI_CHECK_WCT(req, 3); ZERO_STRUCT(parms->old.out); parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID); parms->old.out.action = SVAL(req->in.vwv, VWV(2)); p = req->in.data; if (p) { p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE); } break; case RAW_SESSSETUP_NT1: SMBCLI_CHECK_WCT(req, 3); ZERO_STRUCT(parms->nt1.out); parms->nt1.out.vuid = SVAL(req->in.hdr, HDR_UID); parms->nt1.out.action = SVAL(req->in.vwv, VWV(2)); p = req->in.data; if (p) { p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE); if (p < (req->in.data + req->in.data_size)) { p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE); } } break; case RAW_SESSSETUP_SPNEGO: SMBCLI_CHECK_WCT(req, 4); ZERO_STRUCT(parms->spnego.out); parms->spnego.out.vuid = SVAL(req->in.hdr, HDR_UID); parms->spnego.out.action = SVAL(req->in.vwv, VWV(2)); len = SVAL(req->in.vwv, VWV(3)); p = req->in.data; if (!p) { break; } parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len); p += parms->spnego.out.secblob.length; p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); break; case RAW_SESSSETUP_SMB2: req->status = NT_STATUS_INTERNAL_ERROR; break; } failed: return smbcli_request_destroy(req); }
/* wait for a reply to be received for a packet that just returns an error code and nothing more */ _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req) { (void) smbcli_request_receive(req); return smbcli_request_destroy(req); }
/**************************************************************************** low level read operation (async send) ****************************************************************************/ _PUBLIC_ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_read *parms) { bool bigoffset = false; struct smbcli_request *req = NULL; switch (parms->generic.level) { case RAW_READ_READBRAW: if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { bigoffset = true; } SETUP_REQUEST(SMBreadbraw, bigoffset? 10:8, 0); SSVAL(req->out.vwv, VWV(0), parms->readbraw.in.file.fnum); SIVAL(req->out.vwv, VWV(1), parms->readbraw.in.offset); SSVAL(req->out.vwv, VWV(3), parms->readbraw.in.maxcnt); SSVAL(req->out.vwv, VWV(4), parms->readbraw.in.mincnt); SIVAL(req->out.vwv, VWV(5), parms->readbraw.in.timeout); SSVAL(req->out.vwv, VWV(7), 0); /* reserved */ if (bigoffset) { SIVAL(req->out.vwv, VWV(8),parms->readbraw.in.offset>>32); } break; case RAW_READ_LOCKREAD: SETUP_REQUEST(SMBlockread, 5, 0); SSVAL(req->out.vwv, VWV(0), parms->lockread.in.file.fnum); SSVAL(req->out.vwv, VWV(1), parms->lockread.in.count); SIVAL(req->out.vwv, VWV(2), parms->lockread.in.offset); SSVAL(req->out.vwv, VWV(4), parms->lockread.in.remaining); break; case RAW_READ_READ: SETUP_REQUEST(SMBread, 5, 0); SSVAL(req->out.vwv, VWV(0), parms->read.in.file.fnum); SSVAL(req->out.vwv, VWV(1), parms->read.in.count); SIVAL(req->out.vwv, VWV(2), parms->read.in.offset); SSVAL(req->out.vwv, VWV(4), parms->read.in.remaining); break; case RAW_READ_READX: if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { bigoffset = true; } SETUP_REQUEST(SMBreadX, bigoffset ? 12 : 10, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->readx.in.file.fnum); SIVAL(req->out.vwv, VWV(3), parms->readx.in.offset); SSVAL(req->out.vwv, VWV(5), parms->readx.in.maxcnt & 0xFFFF); SSVAL(req->out.vwv, VWV(6), parms->readx.in.mincnt); SIVAL(req->out.vwv, VWV(7), parms->readx.in.maxcnt >> 16); SSVAL(req->out.vwv, VWV(9), parms->readx.in.remaining); /* * TODO: give an error when the offset is 64 bit * and the server doesn't support it */ if (bigoffset) { SIVAL(req->out.vwv, VWV(10),parms->readx.in.offset>>32); } if (parms->readx.in.read_for_execute) { uint16_t flags2 = SVAL(req->out.hdr, HDR_FLG2); flags2 |= FLAGS2_READ_PERMIT_EXECUTE; SSVAL(req->out.hdr, HDR_FLG2, flags2); } break; case RAW_READ_SMB2: return NULL; } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } /* the transport layer needs to know that a readbraw is pending and handle receives a little differently */ if (parms->generic.level == RAW_READ_READBRAW) { tree->session->transport->readbraw_pending = 1; } return req; }
/**************************************************************************** Open a file - async send ****************************************************************************/ _PUBLIC_ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_open *parms) { int len; struct smbcli_request *req = NULL; bool bigoffset = false; switch (parms->generic.level) { case RAW_OPEN_T2OPEN: return smb_raw_t2open_send(tree, parms); case RAW_OPEN_OPEN: SETUP_REQUEST(SMBopen, 2, 0); SSVAL(req->out.vwv, VWV(0), parms->openold.in.open_mode); SSVAL(req->out.vwv, VWV(1), parms->openold.in.search_attrs); smbcli_req_append_ascii4(req, parms->openold.in.fname, STR_TERMINATE); break; case RAW_OPEN_OPENX: SETUP_REQUEST(SMBopenX, 15, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->openx.in.flags); SSVAL(req->out.vwv, VWV(3), parms->openx.in.open_mode); SSVAL(req->out.vwv, VWV(4), parms->openx.in.search_attrs); SSVAL(req->out.vwv, VWV(5), parms->openx.in.file_attrs); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(6), parms->openx.in.write_time); SSVAL(req->out.vwv, VWV(8), parms->openx.in.open_func); SIVAL(req->out.vwv, VWV(9), parms->openx.in.size); SIVAL(req->out.vwv, VWV(11),parms->openx.in.timeout); SIVAL(req->out.vwv, VWV(13),0); /* reserved */ smbcli_req_append_string(req, parms->openx.in.fname, STR_TERMINATE); break; case RAW_OPEN_MKNEW: SETUP_REQUEST(SMBmknew, 3, 0); SSVAL(req->out.vwv, VWV(0), parms->mknew.in.attrib); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(1), parms->mknew.in.write_time); smbcli_req_append_ascii4(req, parms->mknew.in.fname, STR_TERMINATE); break; case RAW_OPEN_CREATE: SETUP_REQUEST(SMBcreate, 3, 0); SSVAL(req->out.vwv, VWV(0), parms->create.in.attrib); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(1), parms->create.in.write_time); smbcli_req_append_ascii4(req, parms->create.in.fname, STR_TERMINATE); break; case RAW_OPEN_CTEMP: SETUP_REQUEST(SMBctemp, 3, 0); SSVAL(req->out.vwv, VWV(0), parms->ctemp.in.attrib); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(1), parms->ctemp.in.write_time); smbcli_req_append_ascii4(req, parms->ctemp.in.directory, STR_TERMINATE); break; case RAW_OPEN_SPLOPEN: SETUP_REQUEST(SMBsplopen, 2, 0); SSVAL(req->out.vwv, VWV(0), parms->splopen.in.setup_length); SSVAL(req->out.vwv, VWV(1), parms->splopen.in.mode); break; case RAW_OPEN_NTCREATEX: SETUP_REQUEST(SMBntcreateX, 24, 0); SSVAL(req->out.vwv, VWV(0),SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1),0); SCVAL(req->out.vwv, VWV(2),0); /* padding */ SIVAL(req->out.vwv, 7, parms->ntcreatex.in.flags); SIVAL(req->out.vwv, 11, parms->ntcreatex.in.root_fid.fnum); SIVAL(req->out.vwv, 15, parms->ntcreatex.in.access_mask); SBVAL(req->out.vwv, 19, parms->ntcreatex.in.alloc_size); SIVAL(req->out.vwv, 27, parms->ntcreatex.in.file_attr); SIVAL(req->out.vwv, 31, parms->ntcreatex.in.share_access); SIVAL(req->out.vwv, 35, parms->ntcreatex.in.open_disposition); SIVAL(req->out.vwv, 39, parms->ntcreatex.in.create_options); SIVAL(req->out.vwv, 43, parms->ntcreatex.in.impersonation); SCVAL(req->out.vwv, 47, parms->ntcreatex.in.security_flags); smbcli_req_append_string_len(req, parms->ntcreatex.in.fname, STR_TERMINATE, &len); SSVAL(req->out.vwv, 5, len); break; case RAW_OPEN_NTTRANS_CREATE: return smb_raw_nttrans_create_send(tree, parms); case RAW_OPEN_OPENX_READX: SETUP_REQUEST(SMBopenX, 15, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->openxreadx.in.flags); SSVAL(req->out.vwv, VWV(3), parms->openxreadx.in.open_mode); SSVAL(req->out.vwv, VWV(4), parms->openxreadx.in.search_attrs); SSVAL(req->out.vwv, VWV(5), parms->openxreadx.in.file_attrs); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(6), parms->openxreadx.in.write_time); SSVAL(req->out.vwv, VWV(8), parms->openxreadx.in.open_func); SIVAL(req->out.vwv, VWV(9), parms->openxreadx.in.size); SIVAL(req->out.vwv, VWV(11),parms->openxreadx.in.timeout); SIVAL(req->out.vwv, VWV(13),0); smbcli_req_append_string(req, parms->openxreadx.in.fname, STR_TERMINATE); if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { bigoffset = true; } smbcli_chained_request_setup(req, SMBreadX, bigoffset ? 12 : 10, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), 0); SIVAL(req->out.vwv, VWV(3), parms->openxreadx.in.offset); SSVAL(req->out.vwv, VWV(5), parms->openxreadx.in.maxcnt & 0xFFFF); SSVAL(req->out.vwv, VWV(6), parms->openxreadx.in.mincnt); SIVAL(req->out.vwv, VWV(7), parms->openxreadx.in.maxcnt >> 16); SSVAL(req->out.vwv, VWV(9), parms->openxreadx.in.remaining); if (bigoffset) { SIVAL(req->out.vwv, VWV(10),parms->openxreadx.in.offset>>32); } break; case RAW_OPEN_NTCREATEX_READX: SETUP_REQUEST(SMBntcreateX, 24, 0); SSVAL(req->out.vwv, VWV(0),SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1),0); SCVAL(req->out.vwv, VWV(2),0); /* padding */ SIVAL(req->out.vwv, 7, parms->ntcreatexreadx.in.flags); SIVAL(req->out.vwv, 11, parms->ntcreatexreadx.in.root_fid.fnum); SIVAL(req->out.vwv, 15, parms->ntcreatexreadx.in.access_mask); SBVAL(req->out.vwv, 19, parms->ntcreatexreadx.in.alloc_size); SIVAL(req->out.vwv, 27, parms->ntcreatexreadx.in.file_attr); SIVAL(req->out.vwv, 31, parms->ntcreatexreadx.in.share_access); SIVAL(req->out.vwv, 35, parms->ntcreatexreadx.in.open_disposition); SIVAL(req->out.vwv, 39, parms->ntcreatexreadx.in.create_options); SIVAL(req->out.vwv, 43, parms->ntcreatexreadx.in.impersonation); SCVAL(req->out.vwv, 47, parms->ntcreatexreadx.in.security_flags); smbcli_req_append_string_len(req, parms->ntcreatexreadx.in.fname, STR_TERMINATE, &len); SSVAL(req->out.vwv, 5, len); if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { bigoffset = true; } smbcli_chained_request_setup(req, SMBreadX, bigoffset ? 12 : 10, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), 0); SIVAL(req->out.vwv, VWV(3), parms->ntcreatexreadx.in.offset); SSVAL(req->out.vwv, VWV(5), parms->ntcreatexreadx.in.maxcnt & 0xFFFF); SSVAL(req->out.vwv, VWV(6), parms->ntcreatexreadx.in.mincnt); SIVAL(req->out.vwv, VWV(7), parms->ntcreatexreadx.in.maxcnt >> 16); SSVAL(req->out.vwv, VWV(9), parms->ntcreatexreadx.in.remaining); if (bigoffset) { SIVAL(req->out.vwv, VWV(10),parms->ntcreatexreadx.in.offset>>32); } break; case RAW_OPEN_SMB2: return NULL; } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return 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); }
/* Send a negprot command. */ NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req) { struct smbcli_transport *transport = req->transport; int protocol; if (!smbcli_request_receive(req) || smbcli_request_is_error(req)) { return smbcli_request_destroy(req); } SMBCLI_CHECK_MIN_WCT(req, 1); protocol = SVALS(req->in.vwv, VWV(0)); if (protocol >= ARRAY_SIZE(prots) || protocol < 0) { req->status = NT_STATUS_UNSUCCESSFUL; return smbcli_request_destroy(req); } transport->negotiate.protocol = prots[protocol].prot; if (transport->negotiate.protocol >= PROTOCOL_NT1) { NTTIME ntt; /* NT protocol */ SMBCLI_CHECK_WCT(req, 17); transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1)); transport->negotiate.max_mux = SVAL(req->in.vwv,VWV(1)+1); transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1); transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(7)+1); transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1); /* this time arrives in real GMT */ ntt = smbcli_pull_nttime(req->in.vwv, VWV(11)+1); transport->negotiate.server_time = nt_time_to_unix(ntt); transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60; transport->negotiate.key_len = CVAL(req->in.vwv,VWV(16)+1); if (transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) { if (req->in.data_size < 16) { goto failed; } transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16); transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16); } else { if (req->in.data_size < (transport->negotiate.key_len)) { goto failed; } transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len); smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain, req->in.data+transport->negotiate.key_len, req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN); /* here comes the server name */ } if (transport->negotiate.capabilities & CAP_RAW_MODE) { transport->negotiate.readbraw_supported = true; transport->negotiate.writebraw_supported = true; } if (transport->negotiate.capabilities & CAP_LOCK_AND_READ) transport->negotiate.lockread_supported = true; } else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) { SMBCLI_CHECK_WCT(req, 13); transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1)); transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2)); transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(6)); transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60; /* this time is converted to GMT by raw_pull_dos_date */ transport->negotiate.server_time = raw_pull_dos_date(transport, req->in.vwv+VWV(8)); if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) { transport->negotiate.readbraw_supported = 1; } if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) { transport->negotiate.writebraw_supported = 1; } transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, req->in.data_size); } else { /* the old core protocol */ transport->negotiate.sec_mode = 0; transport->negotiate.server_time = time(NULL); transport->negotiate.max_xmit = transport->options.max_xmit; transport->negotiate.server_zone = get_time_zone(transport->negotiate.server_time); } /* a way to force ascii SMB */ if (!transport->options.unicode) { transport->negotiate.capabilities &= ~CAP_UNICODE; } if (!transport->options.ntstatus_support) { transport->negotiate.capabilities &= ~CAP_STATUS32; } if (!transport->options.use_level2_oplocks) { transport->negotiate.capabilities &= ~CAP_LEVEL_II_OPLOCKS; } failed: return smbcli_request_destroy(req); }
/**************************************************************************** Perform a session setup (async send) ****************************************************************************/ struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, union smb_sesssetup *parms) { struct smbcli_request *req = NULL; switch (parms->old.level) { case RAW_SESSSETUP_OLD: SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize); SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max); SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num); SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey); SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length); SIVAL(req->out.vwv,VWV(8), 0); /* reserved */ smbcli_req_append_blob(req, &parms->old.in.password); smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE); smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER); smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE); smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE); break; case RAW_SESSSETUP_NT1: SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize); SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max); SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num); SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey); SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length); SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length); SIVAL(req->out.vwv, VWV(9), 0); /* reserved */ SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities); smbcli_req_append_blob(req, &parms->nt1.in.password1); smbcli_req_append_blob(req, &parms->nt1.in.password2); smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE); smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER); smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE); smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE); break; case RAW_SESSSETUP_SPNEGO: SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize); SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max); SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num); SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey); SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length); SIVAL(req->out.vwv, VWV(8), 0); /* reserved */ SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities); smbcli_req_append_blob(req, &parms->spnego.in.secblob); smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE); smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE); smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE); break; case RAW_SESSSETUP_SMB2: return NULL; } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }
/**************************************************************************** raw write interface (async send) ****************************************************************************/ _PUBLIC_ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_write *parms) { bool bigoffset = false; struct smbcli_request *req = NULL; switch (parms->generic.level) { case RAW_WRITE_WRITEUNLOCK: SETUP_REQUEST(SMBwriteunlock, 5, 3 + parms->writeunlock.in.count); SSVAL(req->out.vwv, VWV(0), parms->writeunlock.in.file.fnum); SSVAL(req->out.vwv, VWV(1), parms->writeunlock.in.count); SIVAL(req->out.vwv, VWV(2), parms->writeunlock.in.offset); SSVAL(req->out.vwv, VWV(4), parms->writeunlock.in.remaining); SCVAL(req->out.data, 0, SMB_DATA_BLOCK); SSVAL(req->out.data, 1, parms->writeunlock.in.count); if (parms->writeunlock.in.count > 0) { memcpy(req->out.data+3, parms->writeunlock.in.data, parms->writeunlock.in.count); } break; case RAW_WRITE_WRITE: SETUP_REQUEST(SMBwrite, 5, 3 + parms->write.in.count); SSVAL(req->out.vwv, VWV(0), parms->write.in.file.fnum); SSVAL(req->out.vwv, VWV(1), parms->write.in.count); SIVAL(req->out.vwv, VWV(2), parms->write.in.offset); SSVAL(req->out.vwv, VWV(4), parms->write.in.remaining); SCVAL(req->out.data, 0, SMB_DATA_BLOCK); SSVAL(req->out.data, 1, parms->write.in.count); if (parms->write.in.count > 0) { memcpy(req->out.data+3, parms->write.in.data, parms->write.in.count); } break; case RAW_WRITE_WRITECLOSE: SETUP_REQUEST(SMBwriteclose, 6, 1 + parms->writeclose.in.count); SSVAL(req->out.vwv, VWV(0), parms->writeclose.in.file.fnum); SSVAL(req->out.vwv, VWV(1), parms->writeclose.in.count); SIVAL(req->out.vwv, VWV(2), parms->writeclose.in.offset); raw_push_dos_date3(tree->session->transport, req->out.vwv, VWV(4), parms->writeclose.in.mtime); SCVAL(req->out.data, 0, 0); if (parms->writeclose.in.count > 0) { memcpy(req->out.data+1, parms->writeclose.in.data, parms->writeclose.in.count); } break; case RAW_WRITE_WRITEX: if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { bigoffset = true; } SETUP_REQUEST(SMBwriteX, bigoffset ? 14 : 12, parms->writex.in.count); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), parms->writex.in.file.fnum); SIVAL(req->out.vwv, VWV(3), parms->writex.in.offset); SIVAL(req->out.vwv, VWV(5), 0); /* reserved */ SSVAL(req->out.vwv, VWV(7), parms->writex.in.wmode); SSVAL(req->out.vwv, VWV(8), parms->writex.in.remaining); SSVAL(req->out.vwv, VWV(9), parms->writex.in.count>>16); SSVAL(req->out.vwv, VWV(10), parms->writex.in.count); SSVAL(req->out.vwv, VWV(11), PTR_DIFF(req->out.data, req->out.hdr)); if (bigoffset) { SIVAL(req->out.vwv,VWV(12),parms->writex.in.offset>>32); } if (parms->writex.in.count > 0) { memcpy(req->out.data, parms->writex.in.data, parms->writex.in.count); } break; case RAW_WRITE_SPLWRITE: SETUP_REQUEST(SMBsplwr, 1, parms->splwrite.in.count); SSVAL(req->out.vwv, VWV(0), parms->splwrite.in.file.fnum); if (parms->splwrite.in.count > 0) { memcpy(req->out.data, parms->splwrite.in.data, parms->splwrite.in.count); } break; case RAW_WRITE_SMB2: return NULL; } if (!smbcli_request_send(req)) { smbcli_request_destroy(req); return NULL; } return req; }