📄 nttrans.c
字号:
/* parse NTTRANS_IOCTL request */static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_ioctl *nt; /* should have at least 4 setup words */ if (trans->in.setup_count != 4) { return NT_STATUS_INVALID_PARAMETER; } nt = talloc(op, union smb_ioctl); NT_STATUS_HAVE_NO_MEMORY(nt); nt->ntioctl.level = RAW_IOCTL_NTIOCTL; nt->ntioctl.in.function = IVAL(trans->in.setup, 0); nt->ntioctl.in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4); nt->ntioctl.in.fsctl = CVAL(trans->in.setup, 6); nt->ntioctl.in.filter = CVAL(trans->in.setup, 7); nt->ntioctl.in.max_data = trans->in.max_data; nt->ntioctl.in.blob = trans->in.data; op->op_info = nt; op->send_fn = nttrans_ioctl_send; SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(nt->ntioctl.in.file.ntvfs); return ntvfs_ioctl(req->ntvfs, nt);}/* send NTTRANS_NOTIFY_CHANGE reply */static NTSTATUS nttrans_notify_change_send(struct nttrans_op *op){ union smb_notify *info = talloc_get_type(op->op_info, union smb_notify); size_t size = 0; int i; NTSTATUS status; uint8_t *p;#define MAX_BYTES_PER_CHAR 3 /* work out how big the reply buffer could be */ for (i=0;i<info->nttrans.out.num_changes;i++) { size += 12 + 3 + (1+strlen(info->nttrans.out.changes[i].name.s)) * MAX_BYTES_PER_CHAR; } status = nttrans_setup_reply(op, op->trans, size, 0, 0); NT_STATUS_NOT_OK_RETURN(status); p = op->trans->out.params.data; /* construct the changes buffer */ for (i=0;i<info->nttrans.out.num_changes;i++) { uint32_t ofs; ssize_t len; SIVAL(p, 4, info->nttrans.out.changes[i].action); len = push_string(lp_iconv_convenience(global_loadparm), p + 12, info->nttrans.out.changes[i].name.s, op->trans->out.params.length - (p+12 - op->trans->out.params.data), STR_UNICODE); SIVAL(p, 8, len); ofs = len + 12; if (ofs & 3) { int pad = 4 - (ofs & 3); memset(p+ofs, 0, pad); ofs += pad; } if (i == info->nttrans.out.num_changes-1) { SIVAL(p, 0, 0); } else { SIVAL(p, 0, ofs); } p += ofs; } op->trans->out.params.length = p - op->trans->out.params.data; return NT_STATUS_OK;}/* parse NTTRANS_NOTIFY_CHANGE request */static NTSTATUS nttrans_notify_change(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_notify *info; /* should have at least 4 setup words */ if (trans->in.setup_count != 4) { return NT_STATUS_INVALID_PARAMETER; } info = talloc(op, union smb_notify); NT_STATUS_HAVE_NO_MEMORY(info); info->nttrans.level = RAW_NOTIFY_NTTRANS; info->nttrans.in.completion_filter = IVAL(trans->in.setup, 0); info->nttrans.in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4); info->nttrans.in.recursive = SVAL(trans->in.setup, 6); info->nttrans.in.buffer_size = trans->in.max_param; op->op_info = info; op->send_fn = nttrans_notify_change_send; SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->nttrans.in.file.ntvfs); return ntvfs_notify(req->ntvfs, info);}/* backend for nttrans requests*/static NTSTATUS nttrans_backend(struct smbsrv_request *req, struct nttrans_op *op){ /* the nttrans command is in function */ switch (op->trans->in.function) { case NT_TRANSACT_CREATE: return nttrans_create(req, op); case NT_TRANSACT_IOCTL: return nttrans_ioctl(req, op); case NT_TRANSACT_RENAME: return nttrans_rename(req, op); case NT_TRANSACT_QUERY_SECURITY_DESC: return nttrans_query_sec_desc(req, op); case NT_TRANSACT_SET_SECURITY_DESC: return nttrans_set_sec_desc(req, op); case NT_TRANSACT_NOTIFY_CHANGE: return nttrans_notify_change(req, op); } /* an unknown nttrans command */ return NT_STATUS_DOS(ERRSRV, ERRerror);}static void reply_nttrans_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; uint32_t params_left, data_left; uint8_t *params, *data; struct smb_nttrans *trans; struct nttrans_op *op; SMBSRV_CHECK_ASYNC_STATUS(op, struct nttrans_op); trans = op->trans; /* if this function needs work to form the nttrans reply buffer, then call that now */ if (op->send_fn != NULL) { NTSTATUS status; status = op->send_fn(op); if (!NT_STATUS_IS_OK(status)) { smbsrv_send_error(req, status); return; } } smbsrv_setup_reply(req, 18 + trans->out.setup_count, 0); /* note that we don't check the max_setup count (matching w2k3 behaviour) */ if (trans->out.params.length > trans->in.max_param) { smbsrv_setup_error(req, NT_STATUS_BUFFER_TOO_SMALL); trans->out.params.length = trans->in.max_param; } if (trans->out.data.length > trans->in.max_data) { smbsrv_setup_error(req, NT_STATUS_BUFFER_TOO_SMALL); trans->out.data.length = trans->in.max_data; } params_left = trans->out.params.length; data_left = trans->out.data.length; params = trans->out.params.data; data = trans->out.data.data; /* we need to divide up the reply into chunks that fit into the negotiated buffer size */ do { uint32_t this_data, this_param, max_bytes; uint_t align1 = 1, align2 = (params_left ? 2 : 0); struct smbsrv_request *this_req; max_bytes = req_max_data(req) - (align1 + align2); this_param = params_left; if (this_param > max_bytes) { this_param = max_bytes; } max_bytes -= this_param; this_data = data_left; if (this_data > max_bytes) { this_data = max_bytes; } /* don't destroy unless this is the last chunk */ if (params_left - this_param != 0 || data_left - this_data != 0) { this_req = smbsrv_setup_secondary_request(req); } else { this_req = req; } req_grow_data(this_req, this_param + this_data + (align1 + align2)); SSVAL(this_req->out.vwv, 0, 0); /* reserved */ SCVAL(this_req->out.vwv, 2, 0); /* reserved */ SIVAL(this_req->out.vwv, 3, trans->out.params.length); SIVAL(this_req->out.vwv, 7, trans->out.data.length); SIVAL(this_req->out.vwv, 11, this_param); SIVAL(this_req->out.vwv, 15, align1 + PTR_DIFF(this_req->out.data, this_req->out.hdr)); SIVAL(this_req->out.vwv, 19, PTR_DIFF(params, trans->out.params.data)); SIVAL(this_req->out.vwv, 23, this_data); SIVAL(this_req->out.vwv, 27, align1 + align2 + PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr)); SIVAL(this_req->out.vwv, 31, PTR_DIFF(data, trans->out.data.data)); SCVAL(this_req->out.vwv, 35, trans->out.setup_count); memcpy((char *)(this_req->out.vwv) + VWV(18), trans->out.setup, sizeof(uint16_t) * trans->out.setup_count); memset(this_req->out.data, 0, align1); if (this_param != 0) { memcpy(this_req->out.data + align1, params, this_param); } memset(this_req->out.data+this_param+align1, 0, align2); if (this_data != 0) { memcpy(this_req->out.data+this_param+align1+align2, data, this_data); } params_left -= this_param; data_left -= this_data; params += this_param; data += this_data; smbsrv_send_reply(this_req); } while (params_left != 0 || data_left != 0);}/**************************************************************************** Reply to an SMBnttrans request****************************************************************************/void smbsrv_reply_nttrans(struct smbsrv_request *req){ struct nttrans_op *op; struct smb_nttrans *trans; uint32_t param_ofs, data_ofs; uint32_t param_count, data_count; uint32_t param_total, data_total; /* parse request */ if (req->in.wct < 19) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } SMBSRV_TALLOC_IO_PTR(op, struct nttrans_op); SMBSRV_SETUP_NTVFS_REQUEST(reply_nttrans_send, NTVFS_ASYNC_STATE_MAY_ASYNC); trans = talloc(op, struct smb_nttrans); if (trans == NULL) { smbsrv_send_error(req, NT_STATUS_NO_MEMORY); return; } op->trans = trans; op->op_info = NULL; op->send_fn = NULL; trans->in.max_setup = CVAL(req->in.vwv, 0); param_total = IVAL(req->in.vwv, 3); data_total = IVAL(req->in.vwv, 7); trans->in.max_param = IVAL(req->in.vwv, 11); trans->in.max_data = IVAL(req->in.vwv, 15); param_count = IVAL(req->in.vwv, 19); param_ofs = IVAL(req->in.vwv, 23); data_count = IVAL(req->in.vwv, 27); data_ofs = IVAL(req->in.vwv, 31); trans->in.setup_count= CVAL(req->in.vwv, 35); trans->in.function = SVAL(req->in.vwv, 36); if (req->in.wct != 19 + trans->in.setup_count) { smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror)); return; } /* parse out the setup words */ trans->in.setup = talloc_array(req, uint8_t, trans->in.setup_count*2); if (!trans->in.setup) { smbsrv_send_error(req, NT_STATUS_NO_MEMORY); return; } memcpy(trans->in.setup, (char *)(req->in.vwv) + VWV(19), sizeof(uint16_t) * trans->in.setup_count); if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &trans->in.params) || !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &trans->in.data)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } /* is it a partial request? if so, then send a 'send more' message */ if (param_total > param_count || data_total > data_count) { DEBUG(0,("REWRITE: not handling partial nttrans requests!\n")); smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } ZERO_STRUCT(trans->out); SMBSRV_CALL_NTVFS_BACKEND(nttrans_backend(req, op));}/**************************************************************************** Reply to an SMBnttranss request****************************************************************************/void smbsrv_reply_nttranss(struct smbsrv_request *req){ smbsrv_send_error(req, NT_STATUS_FOOBAR);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -