📄 reply.c
字号:
} else { lck->lockx.in.locks[i].offset = IVAL(p, 2); lck->lockx.in.locks[i].count = IVAL(p, 6); } if (ofs_high != 0 || count_high != 0) { lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32; lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32; } p += lck_size; } SMBSRV_CHECK_FILE_HANDLE(lck->lockx.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));}/**************************************************************************** Reply to a SMBreadbmpx (read block multiplex) request.****************************************************************************/void smbsrv_reply_readbmpx(struct smbsrv_request *req){ /* tell the client to not use a multiplexed read - its too broken to use */ smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));}/**************************************************************************** Reply to a SMBsetattrE.****************************************************************************/void smbsrv_reply_setattrE(struct smbsrv_request *req){ union smb_setfileinfo *info; /* parse request */ SMBSRV_CHECK_WCT(req, 7); SMBSRV_TALLOC_IO_PTR(info, union smb_setfileinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); info->setattre.level = RAW_SFILEINFO_SETATTRE; info->setattre.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1)); info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3)); info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5)); SMBSRV_CHECK_FILE_HANDLE(info->setattre.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info));}/**************************************************************************** Reply to a SMBwritebmpx (write block multiplex primary) request.****************************************************************************/void smbsrv_reply_writebmpx(struct smbsrv_request *req){ smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));}/**************************************************************************** Reply to a SMBwritebs (write block multiplex secondary) request.****************************************************************************/void smbsrv_reply_writebs(struct smbsrv_request *req){ smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));}/**************************************************************************** Reply to a SMBgetattrE (async reply)****************************************************************************/static void reply_getattrE_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_fileinfo *info; SMBSRV_CHECK_ASYNC_STATUS(info, union smb_fileinfo); /* setup reply */ smbsrv_setup_reply(req, 11, 0); srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time); srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time); srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time); SIVAL(req->out.vwv, VWV(6), info->getattre.out.size); SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size); SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib); smbsrv_send_reply(req);}/**************************************************************************** Reply to a SMBgetattrE.****************************************************************************/void smbsrv_reply_getattrE(struct smbsrv_request *req){ union smb_fileinfo *info; /* parse request */ SMBSRV_CHECK_WCT(req, 1); SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC); info->getattr.level = RAW_FILEINFO_GETATTRE; info->getattr.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); SMBSRV_CHECK_FILE_HANDLE(info->getattr.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info));}void smbsrv_reply_sesssetup_send(struct smbsrv_request *req, union smb_sesssetup *io, NTSTATUS status){ switch (io->old.level) { case RAW_SESSSETUP_OLD: if (!NT_STATUS_IS_OK(status)) { smbsrv_send_error(req, status); return; } /* construct reply */ smbsrv_setup_reply(req, 3, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), io->old.out.action); SSVAL(req->out.hdr, HDR_UID, io->old.out.vuid); smbsrv_chain_reply(req); return; case RAW_SESSSETUP_NT1: if (!NT_STATUS_IS_OK(status)) { smbsrv_send_error(req, status); return; } /* construct reply */ smbsrv_setup_reply(req, 3, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), io->nt1.out.action); SSVAL(req->out.hdr, HDR_UID, io->nt1.out.vuid); req_push_str(req, NULL, io->nt1.out.os, -1, STR_TERMINATE); req_push_str(req, NULL, io->nt1.out.lanman, -1, STR_TERMINATE); req_push_str(req, NULL, io->nt1.out.domain, -1, STR_TERMINATE); smbsrv_chain_reply(req); return; case RAW_SESSSETUP_SPNEGO: if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { smbsrv_send_error(req, status); return; } /* construct reply */ smbsrv_setup_reply(req, 4, io->spnego.out.secblob.length); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { smbsrv_setup_error(req, status); } SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), io->spnego.out.action); SSVAL(req->out.vwv, VWV(3), io->spnego.out.secblob.length); SSVAL(req->out.hdr, HDR_UID, io->spnego.out.vuid); memcpy(req->out.data, io->spnego.out.secblob.data, io->spnego.out.secblob.length); req_push_str(req, NULL, io->spnego.out.os, -1, STR_TERMINATE); req_push_str(req, NULL, io->spnego.out.lanman, -1, STR_TERMINATE); req_push_str(req, NULL, io->spnego.out.workgroup, -1, STR_TERMINATE); smbsrv_chain_reply(req); return; case RAW_SESSSETUP_SMB2: break; } smbsrv_send_error(req, NT_STATUS_INTERNAL_ERROR);}/****************************************************************************reply to an old style session setup command****************************************************************************/static void reply_sesssetup_old(struct smbsrv_request *req){ uint8_t *p; uint16_t passlen; union smb_sesssetup *io; SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup); io->old.level = RAW_SESSSETUP_OLD; /* parse request */ io->old.in.bufsize = SVAL(req->in.vwv, VWV(2)); io->old.in.mpx_max = SVAL(req->in.vwv, VWV(3)); io->old.in.vc_num = SVAL(req->in.vwv, VWV(4)); io->old.in.sesskey = IVAL(req->in.vwv, VWV(5)); passlen = SVAL(req->in.vwv, VWV(7)); /* check the request isn't malformed */ if (req_data_oob(&req->in.bufinfo, req->in.data, passlen)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p = req->in.data; if (!req_pull_blob(&req->in.bufinfo, p, passlen, &io->old.in.password)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p += passlen; p += req_pull_string(&req->in.bufinfo, &io->old.in.user, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->old.in.domain, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->old.in.os, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->old.in.lanman, p, -1, STR_TERMINATE); /* call the generic handler */ smbsrv_sesssetup_backend(req, io);}/****************************************************************************reply to an NT1 style session setup command****************************************************************************/static void reply_sesssetup_nt1(struct smbsrv_request *req){ uint8_t *p; uint16_t passlen1, passlen2; union smb_sesssetup *io; SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup); io->nt1.level = RAW_SESSSETUP_NT1; /* parse request */ io->nt1.in.bufsize = SVAL(req->in.vwv, VWV(2)); io->nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3)); io->nt1.in.vc_num = SVAL(req->in.vwv, VWV(4)); io->nt1.in.sesskey = IVAL(req->in.vwv, VWV(5)); passlen1 = SVAL(req->in.vwv, VWV(7)); passlen2 = SVAL(req->in.vwv, VWV(8)); io->nt1.in.capabilities = IVAL(req->in.vwv, VWV(11)); /* check the request isn't malformed */ if (req_data_oob(&req->in.bufinfo, req->in.data, passlen1) || req_data_oob(&req->in.bufinfo, req->in.data + passlen1, passlen2)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p = req->in.data; if (!req_pull_blob(&req->in.bufinfo, p, passlen1, &io->nt1.in.password1)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p += passlen1; if (!req_pull_blob(&req->in.bufinfo, p, passlen2, &io->nt1.in.password2)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p += passlen2; p += req_pull_string(&req->in.bufinfo, &io->nt1.in.user, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->nt1.in.domain, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->nt1.in.os, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->nt1.in.lanman, p, -1, STR_TERMINATE); /* call the generic handler */ smbsrv_sesssetup_backend(req, io);}/****************************************************************************reply to an SPNEGO style session setup command****************************************************************************/static void reply_sesssetup_spnego(struct smbsrv_request *req){ uint8_t *p; uint16_t blob_len; union smb_sesssetup *io; SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup); io->spnego.level = RAW_SESSSETUP_SPNEGO; /* parse request */ io->spnego.in.bufsize = SVAL(req->in.vwv, VWV(2)); io->spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3)); io->spnego.in.vc_num = SVAL(req->in.vwv, VWV(4)); io->spnego.in.sesskey = IVAL(req->in.vwv, VWV(5)); blob_len = SVAL(req->in.vwv, VWV(7)); io->spnego.in.capabilities = IVAL(req->in.vwv, VWV(10)); p = req->in.data; if (!req_pull_blob(&req->in.bufinfo, p, blob_len, &io->spnego.in.secblob)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } p += blob_len; p += req_pull_string(&req->in.bufinfo, &io->spnego.in.os, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->spnego.in.lanman, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &io->spnego.in.workgroup, p, -1, STR_TERMINATE); /* call the generic handler */ smbsrv_sesssetup_backend(req, io);}/****************************************************************************reply to a session setup command****************************************************************************/void smbsrv_reply_sesssetup(struct smbsrv_request *req){ switch (req->in.wct) { case 10: /* a pre-NT1 call */ reply_sesssetup_old(req); return; case 13: /* a NT1 call */ reply_sesssetup_nt1(req); return; case 12: /* a SPNEGO call */ reply_sesssetup_spnego(req); return; } /* unsupported variant */ smbsrv_send_error(req, NT_STATUS_FOOBAR);}/**************************************************************************** Reply to a exit. This closes all files open by a smbpid****************************************************************************/void smbsrv_reply_exit(struct smbsrv_request *req){ struct smbsrv_handle_session_item *i, *ni; struct smbsrv_handle *h; struct smbsrv_tcon *tcon; uint16_t smbpid; SMBSRV_CHECK_WCT(req, 0); smbpid = SVAL(req->in.hdr,HDR_PID); /* first destroy all handles, which have the same PID as the request */ for (i=req->session->handles; i; i=ni) { ni = i->next; h = i->handle; if (h->smbpid != smbpid) continue; talloc_free(h); } /* * then let the ntvfs backends proxy the call if they want to, * but we didn't check the return value of the backends, * as for the SMB client the call succeed */ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { req->tcon = tcon; SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); ntvfs_exit(req->ntvfs); talloc_free(req->ntvfs); req->ntvfs = NULL; req->tcon = NULL; } smbsrv_setup_reply(req, 0, 0); smbsrv_send_reply(req);}/**************************************************************************** Reply to a SMBulogoffX.****************************************************************************/void smbsrv_reply_ulogoffX(struct smbsrv_request *req){ struct smbsrv_handle_session_item *i, *ni; struct smbsrv_handle *h; struct smbsrv_tcon *tcon; SMBSRV_CHECK_WCT(req, 2); /* * TODO: cancel all pending requests */ /* destroy all handles */ for (i=req->session->handles; i; i=ni) { ni = i->next; h = i->handle; talloc_free(h); } /* * then let the ntvfs backends proxy the call if they want to, * but we didn't check the return value of the backends, * as for the SMB client the call succeed */ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { req->tcon = tcon; SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); ntvfs_logo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -