summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-08-07 09:44:31 +0200
committerStefan Metzmacher <metze@samba.org>2012-08-09 08:21:35 +0200
commitf15d9a66701eaf580a0b641cf3f0dec185d6dd48 (patch)
treee60699404d0d3a983bd8a22558b3ab7603985fa3
parenta117fd6d11aef5360a1af1fc6da542829da8b7b0 (diff)
downloadsamba-f15d9a66701eaf580a0b641cf3f0dec185d6dd48.tar.gz
s3:smb2_server: do central file_id check if the operation requires it
Note that it's fine to call file_fsp_smb2() twice, the 2nd call just returns smb2req->compat_chain_fsp without a 2nd lookup. metze
-rw-r--r--source3/smbd/smb2_server.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 52425474aa0..61c1bfffae3 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -38,6 +38,8 @@ static const struct smbd_smb2_dispatch_table {
bool need_session;
bool need_tcon;
bool as_root;
+ uint16_t fileid_ofs;
+ bool allow_invalid_fileid;
} smbd_smb2_table[] = {
#define _OP(o) .opcode = o, .name = #o
{
@@ -74,26 +76,33 @@ static const struct smbd_smb2_dispatch_table {
_OP(SMB2_OP_CLOSE),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
},{
_OP(SMB2_OP_FLUSH),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
},{
_OP(SMB2_OP_READ),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x10,
},{
_OP(SMB2_OP_WRITE),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x10,
},{
_OP(SMB2_OP_LOCK),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
},{
_OP(SMB2_OP_IOCTL),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
+ .allow_invalid_fileid = true,
},{
_OP(SMB2_OP_CANCEL),
.as_root = true,
@@ -104,22 +113,32 @@ static const struct smbd_smb2_dispatch_table {
_OP(SMB2_OP_FIND),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
},{
_OP(SMB2_OP_NOTIFY),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x08,
},{
_OP(SMB2_OP_GETINFO),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x18,
},{
_OP(SMB2_OP_SETINFO),
.need_session = true,
.need_tcon = true,
+ .fileid_ofs = 0x10,
},{
_OP(SMB2_OP_BREAK),
.need_session = true,
.need_tcon = true,
+ /*
+ * we do not set
+ * .fileid_ofs here
+ * as LEASE breaks does not
+ * have a file id
+ */
}
};
@@ -1827,7 +1846,44 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
}
}
+ if (call->fileid_ofs != 0) {
+ size_t needed = call->fileid_ofs + 16;
+ const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
+ size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
+ uint64_t file_id_persistent;
+ uint64_t file_id_volatile;
+ struct files_struct *fsp;
+
+ SMB_ASSERT(call->need_tcon);
+
+ if (needed > body_size) {
+ return smbd_smb2_request_error(req,
+ NT_STATUS_INVALID_PARAMETER);
+ }
+
+ file_id_persistent = BVAL(body, call->fileid_ofs + 0);
+ file_id_volatile = BVAL(body, call->fileid_ofs + 8);
+
+ fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
+ if (fsp == NULL) {
+ if (!call->allow_invalid_fileid) {
+ return smbd_smb2_request_error(req,
+ NT_STATUS_FILE_CLOSED);
+ }
+
+ if (file_id_persistent != UINT64_MAX) {
+ return smbd_smb2_request_error(req,
+ NT_STATUS_FILE_CLOSED);
+ }
+ if (file_id_volatile != UINT64_MAX) {
+ return smbd_smb2_request_error(req,
+ NT_STATUS_FILE_CLOSED);
+ }
+ }
+ }
+
if (call->as_root) {
+ SMB_ASSERT(call->fileid_ofs == 0);
/* This call needs to be run as root */
change_to_root_user();
} else {