diff options
Diffstat (limited to 'source4/smb_server/smb')
-rw-r--r-- | source4/smb_server/smb/nttrans.c | 15 | ||||
-rw-r--r-- | source4/smb_server/smb/receive.c | 4 | ||||
-rw-r--r-- | source4/smb_server/smb/reply.c | 229 | ||||
-rw-r--r-- | source4/smb_server/smb/request.c | 92 | ||||
-rw-r--r-- | source4/smb_server/smb/service.c | 14 | ||||
-rw-r--r-- | source4/smb_server/smb/trans2.c | 18 |
6 files changed, 272 insertions, 100 deletions
diff --git a/source4/smb_server/smb/nttrans.c b/source4/smb_server/smb/nttrans.c index c5b950ec5b..3bc0ab69b2 100644 --- a/source4/smb_server/smb/nttrans.c +++ b/source4/smb_server/smb/nttrans.c @@ -75,7 +75,7 @@ static NTSTATUS nttrans_create_send(struct nttrans_op *op) params = op->trans->out.params.data; SSVAL(params, 0, io->ntcreatex.out.oplock_level); - SSVAL(params, 2, io->ntcreatex.out.file.fnum); + smbsrv_push_fnum(params, 2, io->ntcreatex.out.file.ntvfs); SIVAL(params, 4, io->ntcreatex.out.create_action); SIVAL(params, 8, 0); /* ea error offset */ push_nttime(params, 12, io->ntcreatex.out.create_time); @@ -230,12 +230,13 @@ static NTSTATUS nttrans_query_sec_desc(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(io); io->query_secdesc.level = RAW_FILEINFO_SEC_DESC; - io->query_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0); + io->query_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->query_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); op->op_info = io; op->send_fn = nttrans_query_sec_desc_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->query_secdesc.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, io); } @@ -259,7 +260,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(io); io->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; - io->set_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0); + io->set_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->set_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); io->set_secdesc.in.sd = talloc(io, struct security_descriptor); @@ -270,6 +271,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); NT_STATUS_NOT_OK_RETURN(status); + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->set_secdesc.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, io); } @@ -304,6 +306,7 @@ static NTSTATUS nttrans_ioctl_send(struct nttrans_op *op) return NT_STATUS_OK; } + /* parse NTTRANS_IOCTL request */ @@ -323,7 +326,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, nt->ntioctl.level = RAW_IOCTL_NTIOCTL; nt->ntioctl.in.function = IVAL(trans->in.setup, 0); - nt->ntioctl.in.file.fnum = SVAL(trans->in.setup, 4); + 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; @@ -332,6 +335,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, 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); } @@ -408,13 +412,14 @@ static NTSTATUS nttrans_notify_change(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(info); info->in.completion_filter = IVAL(trans->in.setup, 0); - info->in.file.fnum = SVAL(trans->in.setup, 4); + info->in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4); info->in.recursive = SVAL(trans->in.setup, 6); info->in.buffer_size = trans->in.max_param; op->op_info = info; op->send_fn = nttrans_notify_change_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->in.file.ntvfs); return ntvfs_notify(req->ntvfs, info); } diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c index ee728e0ec5..a47d0a5442 100644 --- a/source4/smb_server/smb/receive.c +++ b/source4/smb_server/smb/receive.c @@ -31,7 +31,7 @@ /* send an oplock break request to a client */ -NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level) +NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level) { struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon); struct smbsrv_request *req; @@ -51,7 +51,7 @@ NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - SSVAL(req->out.vwv, VWV(2), fnum); + smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs); SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE); SCVAL(req->out.vwv, VWV(3)+1, level); SIVAL(req->out.vwv, VWV(4), 0); diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c index 768fba1319..9abb35ad86 100644 --- a/source4/smb_server/smb/reply.c +++ b/source4/smb_server/smb/reply.c @@ -3,6 +3,7 @@ Main SMB reply routines Copyright (C) Andrew Tridgell 1992-2003 Copyright (C) James J Myers 2003 <myersjj@samba.org> + Copyright (C) Stefan Metzmacher 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +21,7 @@ */ /* This file handles most of the reply_ calls that the server - makes to handle specific protocols + makes to handle specific SMB commands */ #include "includes.h" @@ -204,10 +205,11 @@ void smbsrv_reply_ioctl(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->ioctl.level = RAW_IOCTL_IOCTL; - io->ioctl.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->ioctl.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->ioctl.in.request = IVAL(req->in.vwv, VWV(1)); - /* call backend */ + SMBSRV_CHECK_FILE_HANDLE_ERROR(io->ioctl.in.file.ntvfs, + NT_STATUS_DOS(ERRSRV, ERRerror)); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io)); } @@ -353,7 +355,7 @@ static void reply_open_send(struct ntvfs_request *ntvfs) /* construct reply */ smbsrv_setup_reply(req, 7, 0); - SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs); SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib); srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time); SIVAL(req->out.vwv, VWV(4), oi->openold.out.size); @@ -408,7 +410,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(2), oi->openx.out.file.ntvfs); SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib); srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time); SIVAL(req->out.vwv, VWV(6), oi->openx.out.size); @@ -423,7 +425,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs) SMBSRV_VWV_RESERVED(17, 2); } - req->chained_fnum = oi->openx.out.file.fnum; + req->chained_fnum = SVAL(req->out.vwv, VWV(2)); smbsrv_chain_reply(req); } @@ -475,7 +477,7 @@ static void reply_mknew_send(struct ntvfs_request *ntvfs) /* build the reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->mknew.out.file.ntvfs); smbsrv_send_reply(req); } @@ -524,7 +526,7 @@ static void reply_ctemp_send(struct ntvfs_request *ntvfs) /* build the reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->ctemp.out.file.ntvfs); /* the returned filename is relative to the directory */ req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII); @@ -599,12 +601,16 @@ void smbsrv_reply_readbraw(struct smbsrv_request *req) goto failed; } - io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io.readbraw.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1)); io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3)); io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4)); io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5)); + if (!io.readbraw.in.file.ntvfs) { + goto failed; + } + /* the 64 bit variant */ if (req->in.wct == 10) { uint32_t offset_high = IVAL(req->in.vwv, VWV(8)); @@ -695,17 +701,18 @@ void smbsrv_reply_lockread(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->lockread.level = RAW_READ_LOCKREAD; - io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->lockread.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->lockread.in.count = SVAL(req->in.vwv, VWV(1)); io->lockread.in.offset = IVAL(req->in.vwv, VWV(2)); io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4)); - + /* setup the reply packet assuming the maximum possible read */ smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count); /* tell the backend where to put the data */ io->lockread.out.data = req->out.data + 3; + SMBSRV_CHECK_FILE_HANDLE(io->lockread.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -749,17 +756,18 @@ void smbsrv_reply_read(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->read.level = RAW_READ_READ; - io->read.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->read.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->read.in.count = SVAL(req->in.vwv, VWV(1)); io->read.in.offset = IVAL(req->in.vwv, VWV(2)); io->read.in.remaining = SVAL(req->in.vwv, VWV(4)); - + /* setup the reply packet assuming the maximum possible read */ smbsrv_setup_reply(req, 5, 3 + io->read.in.count); /* tell the backend where to put the data */ io->read.out.data = req->out.data + 3; + SMBSRV_CHECK_FILE_HANDLE(io->read.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -812,7 +820,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->readx.level = RAW_READ_READX; - io->readx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + io->readx.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); io->readx.in.offset = IVAL(req->in.vwv, VWV(3)); io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5)); io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6)); @@ -847,6 +855,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req) io->readx.out.data = req->out.data; } + SMBSRV_CHECK_FILE_HANDLE(io->readx.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -890,7 +899,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->writeunlock.level = RAW_WRITE_WRITEUNLOCK; - io->writeunlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->writeunlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1)); io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2)); io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4)); @@ -908,6 +917,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->writeunlock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -943,7 +953,7 @@ void smbsrv_reply_write(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->write.level = RAW_WRITE_WRITE; - io->write.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->write.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->write.in.count = SVAL(req->in.vwv, VWV(1)); io->write.in.offset = IVAL(req->in.vwv, VWV(2)); io->write.in.remaining = SVAL(req->in.vwv, VWV(4)); @@ -961,6 +971,7 @@ void smbsrv_reply_write(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->write.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1003,7 +1014,7 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->writex.level = RAW_WRITE_WRITEX; - io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + io->writex.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); io->writex.in.offset = IVAL(req->in.vwv, VWV(3)); io->writex.in.wmode = SVAL(req->in.vwv, VWV(7)); io->writex.in.remaining = SVAL(req->in.vwv, VWV(8)); @@ -1021,8 +1032,9 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req) if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; - } + } + SMBSRV_CHECK_FILE_HANDLE(io->writex.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1056,10 +1068,11 @@ void smbsrv_reply_lseek(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_seek); SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->lseek.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->lseek.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->lseek.in.mode = SVAL(req->in.vwv, VWV(1)); io->lseek.in.offset = IVALS(req->in.vwv, VWV(2)); + SMBSRV_CHECK_FILE_HANDLE(io->lseek.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io)); } @@ -1076,46 +1089,18 @@ void smbsrv_reply_flush(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_flush); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - fnum = req_fnum(req, req->in.vwv, VWV(0)); - + fnum = SVAL(req->in.vwv, VWV(0)); if (fnum == 0xFFFF) { io->flush_all.level = RAW_FLUSH_ALL; } else { io->flush.level = RAW_FLUSH_FLUSH; - io->flush.in.file.fnum = fnum; + io->flush.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + SMBSRV_CHECK_FILE_HANDLE(io->flush.in.file.ntvfs); } SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io)); } - -/**************************************************************************** - Reply to a exit. This closes all files open by a smbpid -****************************************************************************/ -void smbsrv_reply_exit(struct smbsrv_request *req) -{ - NTSTATUS status; - struct smbsrv_tcon *tcon; - SMBSRV_CHECK_WCT(req, 0); - - for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { - req->tcon = tcon; - SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); - status = ntvfs_exit(req->ntvfs); - talloc_free(req->ntvfs); - req->ntvfs = NULL; - req->tcon = NULL; - if (!NT_STATUS_IS_OK(status)) { - smbsrv_send_error(req, status); - return; - } - } - - smbsrv_setup_reply(req, 0, 0); - smbsrv_send_reply(req); -} - - /**************************************************************************** Reply to a close @@ -1131,9 +1116,10 @@ void smbsrv_reply_close(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->close.level = RAW_CLOSE_CLOSE; - io->close.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->close.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1)); + SMBSRV_CHECK_FILE_HANDLE(io->close.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io)); } @@ -1171,12 +1157,12 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_write); SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->writeclose.level = RAW_WRITE_WRITECLOSE; - io->writeclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); - io->writeclose.in.count = SVAL(req->in.vwv, VWV(1)); - io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2)); - io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4)); - io->writeclose.in.data = req->in.data + 1; + io->writeclose.level = RAW_WRITE_WRITECLOSE; + io->writeclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + io->writeclose.in.count = SVAL(req->in.vwv, VWV(1)); + io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2)); + io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4)); + io->writeclose.in.data = req->in.data + 1; /* make sure they gave us the data they promised */ if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) { @@ -1184,6 +1170,7 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->writeclose.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1200,10 +1187,11 @@ void smbsrv_reply_lock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->lock.level = RAW_LOCK_LOCK; - lck->lock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + lck->lock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); lck->lock.in.count = IVAL(req->in.vwv, VWV(1)); lck->lock.in.offset = IVAL(req->in.vwv, VWV(3)); + SMBSRV_CHECK_FILE_HANDLE(lck->lock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1221,10 +1209,11 @@ void smbsrv_reply_unlock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->unlock.level = RAW_LOCK_UNLOCK; - lck->unlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + lck->unlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); lck->unlock.in.count = IVAL(req->in.vwv, VWV(1)); lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3)); + SMBSRV_CHECK_FILE_HANDLE(lck->unlock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1234,14 +1223,27 @@ void smbsrv_reply_unlock(struct smbsrv_request *req) ****************************************************************************/ void smbsrv_reply_tdis(struct smbsrv_request *req) { + struct smbsrv_handle *h, *nh; + SMBSRV_CHECK_WCT(req, 0); + /* + * TODO: cancel all pending requests on this tcon + */ + + /* + * close all handles on this tcon + */ + for (h=req->tcon->handles.list; h; h=nh) { + nh = h->next; + talloc_free(h); + } + + /* finaly destroy the tcon */ talloc_free(req->tcon); req->tcon = NULL; - /* construct reply */ smbsrv_setup_reply(req, 0, 0); - smbsrv_send_reply(req); } @@ -1292,7 +1294,7 @@ static void reply_printopen_send(struct ntvfs_request *ntvfs) /* construct reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs); smbsrv_send_reply(req); } @@ -1330,9 +1332,10 @@ void smbsrv_reply_printclose(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_close); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->splclose.level = RAW_CLOSE_SPLCLOSE; - io->splclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->splclose.level = RAW_CLOSE_SPLCLOSE; + io->splclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + SMBSRV_CHECK_FILE_HANDLE(io->splclose.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io)); } @@ -1414,16 +1417,15 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_write); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->splwrite.level = RAW_WRITE_SPLWRITE; - if (req->in.data_size < 3) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } - io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); - io->splwrite.in.count = SVAL(req->in.data, 1); - io->splwrite.in.data = req->in.data + 3; + io->splwrite.level = RAW_WRITE_SPLWRITE; + io->splwrite.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + io->splwrite.in.count = SVAL(req->in.data, 1); + io->splwrite.in.data = req->in.data + 3; /* make sure they gave us the data they promised */ if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) { @@ -1431,6 +1433,7 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->splwrite.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1621,7 +1624,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->lockx.level = RAW_LOCK_LOCKX; - lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + lck->lockx.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3)); lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4)); lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6)); @@ -1676,6 +1679,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req) p += lck_size; } + SMBSRV_CHECK_FILE_HANDLE(lck->lockx.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1702,11 +1706,12 @@ void smbsrv_reply_setattrE(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); info->setattre.level = RAW_SFILEINFO_SETATTRE; - info->setattre.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + 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)); } @@ -1765,9 +1770,10 @@ void smbsrv_reply_getattrE(struct smbsrv_request *req) 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.fnum = req_fnum(req, req->in.vwv, VWV(0)); + 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)); } @@ -1988,26 +1994,81 @@ void smbsrv_reply_sesssetup(struct smbsrv_request *req) } /**************************************************************************** + 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; - NTSTATUS status; - /* in user level security we are supposed to close any files - open by this user on all open tree connects */ + 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); - status = ntvfs_logoff(req->ntvfs); + ntvfs_logoff(req->ntvfs); talloc_free(req->ntvfs); req->ntvfs = NULL; req->tcon = NULL; - if (!NT_STATUS_IS_OK(status)) { - smbsrv_send_error(req, status); - return; - } } talloc_free(req->session); @@ -2018,7 +2079,7 @@ void smbsrv_reply_ulogoffX(struct smbsrv_request *req) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - + smbsrv_chain_reply(req); } @@ -2067,7 +2128,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs) SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level); /* the rest of the parameters are not aligned! */ - SSVAL(req->out.vwv, 5, io->ntcreatex.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, 5, io->ntcreatex.out.file.ntvfs); SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action); push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time); push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time); @@ -2080,7 +2141,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs) SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state); SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory); - req->chained_fnum = io->ntcreatex.out.file.fnum; + req->chained_fnum = SVAL(req->out.vwv, 5); smbsrv_chain_reply(req); } diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c index 21f89f40f9..2896a44d29 100644 --- a/source4/smb_server/smb/request.c +++ b/source4/smb_server/smb/request.c @@ -636,10 +636,100 @@ BOOL req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count /* pull an open file handle from a packet, taking account of the chained_fnum */ -uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) +static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) { if (req->chained_fnum != -1) { return req->chained_fnum; } return SVAL(base, offset); } + +struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) +{ + struct smbsrv_handle *handle; + uint16_t fnum = req_fnum(req, base, offset); + + handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time); + if (!handle) { + return NULL; + } + + return handle->ntvfs; +} + +void smbsrv_push_fnum(uint8_t *base, uint_t offset, struct ntvfs_handle *ntvfs) +{ + struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_handle); + SSVAL(base, offset, handle->hid); +} + +NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h) +{ + struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_request); + struct smbsrv_handle *handle; + struct ntvfs_handle *h; + + handle = smbsrv_handle_new(req); + if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES; + + h = talloc_zero(handle, struct ntvfs_handle); + if (!h) goto nomem; + + /* + * note: we don't set handle->ntvfs yet, + * this will be done by smbsrv_handle_make_valid() + * this makes sure the handle is invalid for clients + * until the ntvfs subsystem has made it valid + */ + h->ctx = ntvfs->ctx; + h->session_info = ntvfs->session_info; + h->smbpid = ntvfs->smbpid; + + h->frontend_data.private_data = handle; + + *_h = h; + return NT_STATUS_OK; +nomem: + talloc_free(handle); + return NT_STATUS_NO_MEMORY; +} + +NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h) +{ + struct smbsrv_tcon *tcon = talloc_get_type(private_data, struct smbsrv_tcon); + struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data, + struct smbsrv_handle); + /* this tells the frontend that the handle is valid */ + handle->ntvfs = h; + /* this moves the smbsrv_request to the smbsrv_tcon memory context */ + talloc_steal(tcon, handle); + return NT_STATUS_OK; +} + +void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h) +{ + struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data, + struct smbsrv_handle); + talloc_free(handle); +} + +struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key) +{ + struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_request); + + if (key->length != 2) return NULL; + + return smbsrv_pull_fnum(req, key->data, 0); +} + +DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx) +{ + uint8_t key[2]; + + smbsrv_push_fnum(key, 0, handle); + + return data_blob_talloc(mem_ctx, key, sizeof(key)); +} diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c index 13ef268a98..7c703c8920 100644 --- a/source4/smb_server/smb/service.c +++ b/source4/smb_server/smb/service.c @@ -110,7 +110,19 @@ static NTSTATUS make_connection_snum(struct smbsrv_request *req, status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("make_connection: NTVFS failed to set the oplock handler!\n")); + DEBUG(0,("make_connection: NTVFS failed to set the addr callbacks!\n")); + goto failed; + } + + status = ntvfs_set_handle_callbacks(tcon->ntvfs, + smbsrv_handle_create_new, + smbsrv_handle_make_valid, + smbsrv_handle_destroy, + smbsrv_handle_search_by_wire_key, + smbsrv_handle_get_wire_key, + tcon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("make_connection: NTVFS failed to set the handle callbacks!\n")); goto failed; } diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c index 1145a08426..69fa65010c 100644 --- a/source4/smb_server/smb/trans2.c +++ b/source4/smb_server/smb/trans2.c @@ -447,7 +447,7 @@ static NTSTATUS trans2_open_send(struct trans_op *op) trans2_setup_reply(trans, 30, 0, 0); - SSVAL(trans->out.params.data, VWV(0), io->t2open.out.file.fnum); + smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs); SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib); srv_push_dos_date3(req->smb_conn, trans->out.params.data, VWV(2), io->t2open.out.write_time); @@ -847,7 +847,8 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op struct smb_trans2 *trans = op->trans; union smb_fileinfo *st; NTSTATUS status; - uint16_t level, fnum; + uint16_t level; + struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { @@ -857,10 +858,10 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op st = talloc(op, union smb_fileinfo); NT_STATUS_HAVE_NO_MEMORY(st); - fnum = SVAL(trans->in.params.data, 0); + h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); - st->generic.in.file.fnum = fnum; + st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_fileinfo_level)level; if (st->generic.level >= RAW_FILEINFO_GENERIC) { @@ -877,6 +878,7 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op op->op_info = st; op->send_fn = trans2_fileinfo_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, st); } @@ -985,7 +987,8 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * struct smb_trans2 *trans = op->trans; union smb_setfileinfo *st; NTSTATUS status; - uint16_t level, fnum; + uint16_t level; + struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { @@ -995,10 +998,10 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * st = talloc(op, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(st); - fnum = SVAL(trans->in.params.data, 0); + h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); - st->generic.in.file.fnum = fnum; + st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_setfileinfo_level)level; if (st->generic.level >= RAW_SFILEINFO_GENERIC) { @@ -1011,6 +1014,7 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * op->op_info = st; op->send_fn = trans2_simple_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, st); } |