From 68ac90a6847b8dee49aee821358b0e56fcfeca68 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 26 Nov 2014 14:30:37 +0100 Subject: [PATCH 01/12] s3:vfs: add SMB_VFS_READDIR_ATTR() SMB_VFS_READDIR_ATTR is a last minute hook to fetch additional metadata for a directory entry when we're already marshalling the SMB reply buffer. This would be used, when there's a need to repurpose some fields in the the reply, like it's done with Apple's SMB2 extension "AAPL". Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit b65e37dc01d7afa007768f7cadfcf3b7c1007664) --- examples/VFS/skel_opaque.c | 9 +++++++++ examples/VFS/skel_transparent.c | 9 +++++++++ source3/include/smb.h | 1 + source3/include/vfs.h | 10 ++++++++++ source3/include/vfs_macros.h | 5 +++++ source3/lib/readdir_attr.h | 37 +++++++++++++++++++++++++++++++++++++ source3/modules/vfs_default.c | 9 +++++++++ source3/modules/vfs_full_audit.c | 18 ++++++++++++++++++ source3/modules/vfs_time_audit.c | 22 ++++++++++++++++++++++ source3/smbd/vfs.c | 9 +++++++++ 10 files changed, 129 insertions(+) create mode 100644 source3/lib/readdir_attr.h diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 47b46a4..6e15a06 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -633,6 +633,14 @@ static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle, return NT_STATUS_NOT_IMPLEMENTED; } +static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, TALLOC_CTX *mem_ctx, @@ -896,6 +904,7 @@ struct vfs_fn_pointers skel_opaque_fns = { .strict_unlock_fn = skel_strict_unlock, .translate_name_fn = skel_translate_name, .fsctl_fn = skel_fsctl, + .readdir_attr_fn = skel_readdir_attr, /* NT ACL operations. */ diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index fbb1323..b11e29c 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -759,6 +759,14 @@ static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle, in_len, _out_data, max_out_len, out_len); } +static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + return SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data); +} + static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, TALLOC_CTX *mem_ctx, @@ -1005,6 +1013,7 @@ struct vfs_fn_pointers skel_transparent_fns = { .strict_unlock_fn = skel_strict_unlock, .translate_name_fn = skel_translate_name, .fsctl_fn = skel_fsctl, + .readdir_attr_fn = skel_readdir_attr, /* NT ACL operations. */ diff --git a/source3/include/smb.h b/source3/include/smb.h index 7bace88..8af44b2 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -152,6 +152,7 @@ struct sys_notify_context { /* Include VFS stuff */ #include "smb_acls.h" +#include "lib/readdir_attr.h" #include "vfs.h" struct current_user { diff --git a/source3/include/vfs.h b/source3/include/vfs.h index e7dc079..b10e9a5 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -159,6 +159,7 @@ /* Bump to version 32 - Samba 4.2 will ship with that. */ /* Version 32 - Add "lease" to CREATE_FILE operation */ /* Version 32 - Add "lease" to struct files_struct */ +/* Version 32 - Add SMB_VFS_READDIR_ATTR() */ #define SMB_VFS_INTERFACE_VERSION 32 @@ -789,6 +790,11 @@ struct vfs_fn_pointers { TALLOC_CTX *mem_ctx, struct files_struct **fsp, DATA_BLOB *new_cookie); + + NTSTATUS (*readdir_attr_fn)(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **attr_data); }; /* @@ -1234,6 +1240,10 @@ NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct files_struct **fsp, DATA_BLOB *new_cookie); +NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **attr_data); NTSTATUS smb_register_vfs(int version, const char *name, const struct vfs_fn_pointers *fns); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index e2d494d..df676ad 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -565,4 +565,9 @@ (smb1req), (op), (old_cookie), \ (mem_ctx), (fsp), (new_cookie)) +#define SMB_VFS_READDIR_ATTR(conn, fname, mem_ctx, attr_data) \ + smb_vfs_call_readdir_attr((conn)->vfs_handles, (fname), (mem_ctx), (attr_data)) +#define SMB_VFS_NEXT_READDIR_ATTR(conn, fname, mem_ctx, attr_data) \ + smb_vfs_call_readdir_attr((handle)->next, (fname), (mem_ctx), (attr_data)) + #endif /* _VFS_MACROS_H */ diff --git a/source3/lib/readdir_attr.h b/source3/lib/readdir_attr.h new file mode 100644 index 0000000..d2a814d --- /dev/null +++ b/source3/lib/readdir_attr.h @@ -0,0 +1,37 @@ +/* + * Fetch filesystem metadata in readdir/marshall context + * + * Copyright (C) Ralph Boehme 2014 + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _READDIR_ATTR_H +#define _READDIR_ATTR_H + +enum readdir_attr_type {RDATTR_NONE, RDATTR_AAPL}; + +struct readdir_attr_data { + enum readdir_attr_type type; + union attr_data { + struct aapl { + uint64_t rfork_size; + char finder_info[16]; + uint32_t max_access; + mode_t unix_mode; + } aapl; + } attr_data; +}; + +#endif /* _READDIR_ATTR_H */ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 3a3943b..834c866 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -403,6 +403,14 @@ static struct dirent *vfswrap_readdir(vfs_handle_struct *handle, return result; } +static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **attr_data) +{ + return NT_STATUS_NOT_SUPPORTED; +} + static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset) { START_PROFILE(syscall_seekdir); @@ -2511,6 +2519,7 @@ static struct vfs_fn_pointers vfs_default_fns = { .opendir_fn = vfswrap_opendir, .fdopendir_fn = vfswrap_fdopendir, .readdir_fn = vfswrap_readdir, + .readdir_attr_fn = vfswrap_readdir_attr, .seekdir_fn = vfswrap_seekdir, .telldir_fn = vfswrap_telldir, .rewind_dir_fn = vfswrap_rewinddir, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index a51ab75..489a28c 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -171,6 +171,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_COPY_CHUNK_RECV, SMB_VFS_OP_GET_COMPRESSION, SMB_VFS_OP_SET_COMPRESSION, + SMB_VFS_OP_READDIR_ATTR, /* NT ACL operations. */ @@ -295,6 +296,7 @@ static struct { { SMB_VFS_OP_COPY_CHUNK_RECV, "copy_chunk_recv" }, { SMB_VFS_OP_GET_COMPRESSION, "get_compression" }, { SMB_VFS_OP_SET_COMPRESSION, "set_compression" }, + { SMB_VFS_OP_READDIR_ATTR, "readdir_attr" }, { SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" }, { SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" }, { SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" }, @@ -1834,6 +1836,21 @@ static NTSTATUS smb_full_audit_set_compression(vfs_handle_struct *handle, return result; } +static NTSTATUS smb_full_audit_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + NTSTATUS status; + + status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data); + + do_log(SMB_VFS_OP_READDIR_ATTR, NT_STATUS_IS_OK(status), handle, "%s", + smb_fname_str_do_log(fname)); + + return status; +} + static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, TALLOC_CTX *mem_ctx, @@ -2249,6 +2266,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .copy_chunk_recv_fn = smb_full_audit_copy_chunk_recv, .get_compression_fn = smb_full_audit_get_compression, .set_compression_fn = smb_full_audit_set_compression, + .readdir_attr_fn = smb_full_audit_readdir_attr, .fget_nt_acl_fn = smb_full_audit_fget_nt_acl, .get_nt_acl_fn = smb_full_audit_get_nt_acl, .fset_nt_acl_fn = smb_full_audit_fset_nt_acl, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 9dbbf8b..243238a 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -1802,6 +1802,27 @@ static NTSTATUS smb_time_audit_set_compression(vfs_handle_struct *handle, return result; } +static NTSTATUS smb_time_audit_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + NTSTATUS status; + struct timespec ts1,ts2; + double timediff; + + clock_gettime_mono(&ts1); + status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data); + clock_gettime_mono(&ts2); + timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; + + if (timediff > audit_timeout) { + smb_time_audit_log_smb_fname("readdir_attr", timediff, fname); + } + + return status; +} + static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, @@ -2423,6 +2444,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = { .copy_chunk_recv_fn = smb_time_audit_copy_chunk_recv, .get_compression_fn = smb_time_audit_get_compression, .set_compression_fn = smb_time_audit_set_compression, + .readdir_attr_fn = smb_time_audit_readdir_attr, .fget_nt_acl_fn = smb_time_audit_fget_nt_acl, .get_nt_acl_fn = smb_time_audit_get_nt_acl, .fset_nt_acl_fn = smb_time_audit_fset_nt_acl, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 8e33f2d..4b96963 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -2461,3 +2461,12 @@ NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle, old_cookie, mem_ctx, fsp, new_cookie); } + +NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **attr_data) +{ + VFS_FIND(readdir_attr); + return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data); +} -- 1.9.1 From 48d8ed9b35d03641091f6d96bd92150dd9d1c3ab Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 28 Nov 2014 11:44:09 +0100 Subject: [PATCH 02/12] s3:smbd: allocate out_context_blobs with talloc By tallocing the out_context_blobs instead of using an automatic stack variable, we can use out_context_blobs as talloc parent for individual create tag that we add via smb2_create_blob_add(). This is in preperation of a SMB_VFS_CREATE_FILE modification where I add the in and out_context_blobs as additional args. With this change in place we can add create tags to out_context_blobs from there too. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit af846264d89f21ac7db8d0cdf6e861ba9cc74151) --- source3/smbd/smb2_create.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 26d285c..77e0c96 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -445,7 +445,7 @@ struct smbd_smb2_create_state { uint32_t out_file_attributes; uint64_t out_file_id_persistent; uint64_t out_file_id_volatile; - struct smb2_create_blobs out_context_blobs; + struct smb2_create_blobs *out_context_blobs; }; static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, @@ -467,7 +467,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, struct smb_request *smb1req = NULL; files_struct *result = NULL; int info; - struct smb2_create_blobs out_context_blobs; int requested_oplock_level; struct smb2_create_blob *dhnc = NULL; struct smb2_create_blob *dh2c = NULL; @@ -476,8 +475,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, struct smb2_create_blob *rqls = NULL; struct smbXsrv_open *op = NULL; - ZERO_STRUCT(out_context_blobs); - if(lp_fake_oplocks(SNUM(smb2req->tcon->compat))) { requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE; } else { @@ -508,10 +505,16 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, state = tevent_req_data(req, struct smbd_smb2_create_state); smb1req = state->smb1req; + TALLOC_FREE(state->out_context_blobs); DEBUG(10,("smbd_smb2_create_send: reentrant for file %s\n", in_name )); } + state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs); + if (tevent_req_nomem(state->out_context_blobs, req)) { + return tevent_req_post(req, ev); + } + dhnq = smb2_create_blob_find(&in_context_blobs, SMB2_CREATE_TAG_DHNQ); dhnc = smb2_create_blob_find(&in_context_blobs, @@ -1105,10 +1108,11 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, SIVAL(p, 0, NT_STATUS_V(status)); SIVAL(p, 4, max_access_granted); - status = smb2_create_blob_add(state, - &out_context_blobs, - SMB2_CREATE_TAG_MXAC, - blob); + status = smb2_create_blob_add( + state->out_context_blobs, + state->out_context_blobs, + SMB2_CREATE_TAG_MXAC, + blob); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return tevent_req_post(req, ev); @@ -1150,8 +1154,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, uint8_t p[8] = { 0, }; DATA_BLOB blob = data_blob_const(p, sizeof(p)); - status = smb2_create_blob_add(state, - &out_context_blobs, + status = smb2_create_blob_add(state->out_context_blobs, + state->out_context_blobs, SMB2_CREATE_TAG_DHNQ, blob); if (!NT_STATUS_IS_OK(status)) { @@ -1168,7 +1172,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, SIVAL(p, 0, op->global->durable_timeout_msec); SIVAL(p, 4, durable_v2_response_flags); - status = smb2_create_blob_add(state, &out_context_blobs, + status = smb2_create_blob_add(state->out_context_blobs, + state->out_context_blobs, SMB2_CREATE_TAG_DH2Q, blob); if (!NT_STATUS_IS_OK(status)) { @@ -1192,7 +1197,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, SBVAL(p, 0, file_index); SIVAL(p, 8, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */ - status = smb2_create_blob_add(state, &out_context_blobs, + status = smb2_create_blob_add(state->out_context_blobs, + state->out_context_blobs, SMB2_CREATE_TAG_QFID, blob); if (!NT_STATUS_IS_OK(status)) { @@ -1218,7 +1224,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, } status = smb2_create_blob_add( - state, &out_context_blobs, + state, state->out_context_blobs, SMB2_CREATE_TAG_RQLS, data_blob_const(buf, lease_len)); if (!NT_STATUS_IS_OK(status)) { @@ -1260,7 +1266,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, } state->out_file_id_persistent = result->op->global->open_persistent_id; state->out_file_id_volatile = result->op->global->open_volatile_id; - state->out_context_blobs = out_context_blobs; DEBUG(10,("smbd_smb2_create_send: %s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result))); @@ -1304,9 +1309,9 @@ static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req, *out_file_attributes = state->out_file_attributes; *out_file_id_persistent = state->out_file_id_persistent; *out_file_id_volatile = state->out_file_id_volatile; - *out_context_blobs = state->out_context_blobs; + *out_context_blobs = *(state->out_context_blobs); - talloc_steal(mem_ctx, state->out_context_blobs.blobs); + talloc_steal(mem_ctx, state->out_context_blobs->blobs); tevent_req_received(req); return NT_STATUS_OK; -- 1.9.1 From 48e71d5a4c06e0c0591e82742fa65f3872a16247 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 26 Nov 2014 14:12:51 +0100 Subject: [PATCH 03/12] s3:vfs: add create tags to SMB_VFS_CREATEFILE Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 142db4048f41f793d9b919a93877d547ff593c6d) --- examples/VFS/skel_opaque.c | 4 +++- examples/VFS/skel_transparent.c | 7 +++++-- source3/include/vfs.h | 9 +++++++-- source3/include/vfs_macros.h | 12 +++++++----- source3/modules/vfs_default.c | 6 ++++-- source3/modules/vfs_fruit.c | 7 +++++-- source3/modules/vfs_full_audit.c | 7 +++++-- source3/modules/vfs_media_harmony.c | 12 +++++++++--- source3/modules/vfs_time_audit.c | 7 +++++-- source3/modules/vfs_worm.c | 7 +++++-- source3/printing/nt_printing.c | 9 ++++++--- source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 6 ++++-- source3/smbd/dosmode.c | 3 ++- source3/smbd/nttrans.c | 12 ++++++++---- source3/smbd/open.c | 10 +++++++--- source3/smbd/proto.h | 6 ++++-- source3/smbd/reply.c | 30 ++++++++++++++++++++---------- source3/smbd/smb2_create.c | 4 +++- source3/smbd/trans2.c | 18 ++++++++++++------ source3/smbd/vfs.c | 6 ++++-- 20 files changed, 125 insertions(+), 57 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 6e15a06..b52c381 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -174,7 +174,9 @@ static NTSTATUS skel_create_file(struct vfs_handle_struct *handle, uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, - files_struct **result, int *pinfo) + files_struct **result, int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index b11e29c..925e520 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -169,7 +169,9 @@ static NTSTATUS skel_create_file(struct vfs_handle_struct *handle, uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, - files_struct ** result, int *pinfo) + files_struct ** result, int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { return SMB_VFS_NEXT_CREATE_FILE(handle, req, @@ -184,7 +186,8 @@ static NTSTATUS skel_create_file(struct vfs_handle_struct *handle, lease, allocation_size, private_flags, - sd, ea_list, result, pinfo); + sd, ea_list, result, pinfo, + in_context_blobs, out_context_blobs); } static int skel_close_fn(vfs_handle_struct *handle, files_struct *fsp) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index b10e9a5..1843ef4 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -160,6 +160,7 @@ /* Version 32 - Add "lease" to CREATE_FILE operation */ /* Version 32 - Add "lease" to struct files_struct */ /* Version 32 - Add SMB_VFS_READDIR_ATTR() */ +/* Version 32 - Add in and our create context blobs to create_file */ #define SMB_VFS_INTERFACE_VERSION 32 @@ -553,7 +554,9 @@ struct vfs_fn_pointers { struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo); + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs); int (*close_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp); ssize_t (*read_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, void *data, size_t n); ssize_t (*pread_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, void *data, size_t n, off_t offset); @@ -964,7 +967,9 @@ NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo); + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs); int smb_vfs_call_close(struct vfs_handle_struct *handle, struct files_struct *fsp); ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index df676ad..ef97b49 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -136,13 +136,15 @@ smb_vfs_call_open((handle)->next, (fname), (fsp), (flags), (mode)) #define SMB_VFS_CREATE_FILE(conn, req, root_dir_fid, smb_fname, access_mask, share_access, create_disposition, \ - create_options, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, result, pinfo) \ - smb_vfs_call_create_file((conn)->vfs_handles, (req), (root_dir_fid), (smb_fname), (access_mask), (share_access), (create_disposition), \ - (create_options), (file_attributes), (oplock_request), (lease), (allocation_size), (private_flags), (sd), (ea_list), (result), (pinfo)) + create_options, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, result, pinfo, in_context_blobs, out_context_blobs) \ + smb_vfs_call_create_file((conn)->vfs_handles, (req), (root_dir_fid), (smb_fname), (access_mask), (share_access), (create_disposition), \ + (create_options), (file_attributes), (oplock_request), (lease), (allocation_size), (private_flags), (sd), (ea_list), (result), (pinfo), \ + (in_context_blobs), (out_context_blobs)) #define SMB_VFS_NEXT_CREATE_FILE(handle, req, root_dir_fid, smb_fname, access_mask, share_access, create_disposition, \ - create_options, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, result, pinfo) \ + create_options, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, result, pinfo, in_context_blobs, out_context_blobs) \ smb_vfs_call_create_file((handle)->next, (req), (root_dir_fid), (smb_fname), (access_mask), (share_access), (create_disposition), \ - (create_options), (file_attributes), (oplock_request), (lease), (allocation_size), (private_flags), (sd), (ea_list), (result), (pinfo)) + (create_options), (file_attributes), (oplock_request), (lease), (allocation_size), (private_flags), (sd), (ea_list), (result), (pinfo), \ + (in_context_blobs), (out_context_blobs)) #define SMB_VFS_CLOSE(fsp) \ smb_vfs_call_close((fsp)->conn->vfs_handles, (fsp)) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 834c866..b740de9 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -531,7 +531,9 @@ static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { return create_file_default(handle->conn, req, root_dir_fid, smb_fname, access_mask, share_access, @@ -539,7 +541,7 @@ static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, result, - pinfo); + pinfo, in_context_blobs, out_context_blobs); } static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index c1555f0..ec75d27 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -2874,7 +2874,9 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { NTSTATUS status; struct fruit_config_data *config = NULL; @@ -2887,7 +2889,8 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, lease, allocation_size, private_flags, sd, ea_list, result, - pinfo); + pinfo, + in_context_blobs, out_context_blobs); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 489a28c..c5a9c0d 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -871,7 +871,9 @@ static NTSTATUS smb_full_audit_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result_fsp, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { NTSTATUS result; const char* str_create_disposition; @@ -916,7 +918,8 @@ static NTSTATUS smb_full_audit_create_file(vfs_handle_struct *handle, sd, /* sd */ ea_list, /* ea_list */ result_fsp, /* result */ - pinfo); /* pinfo */ + pinfo, /* pinfo */ + in_context_blobs, out_context_blobs); /* create context */ do_log(SMB_VFS_OP_CREATE_FILE, (NT_STATUS_IS_OK(result)), handle, "0x%x|%s|%s|%s", access_mask, diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index 2418349..f1264c7 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -1210,7 +1210,9 @@ static NTSTATUS mh_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result_fsp, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { NTSTATUS status; struct smb_filename *clientFname; @@ -1238,7 +1240,9 @@ static NTSTATUS mh_create_file(vfs_handle_struct *handle, sd, ea_list, result_fsp, - pinfo); + pinfo, + in_context_blobs, + out_context_blobs); goto out; } @@ -1275,7 +1279,9 @@ static NTSTATUS mh_create_file(vfs_handle_struct *handle, sd, ea_list, result_fsp, - pinfo); + pinfo, + in_context_blobs, + out_context_blobs); err: TALLOC_FREE(clientFname); out: diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 243238a..4ce9238 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -502,7 +502,9 @@ static NTSTATUS smb_time_audit_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result_fsp, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { NTSTATUS result; struct timespec ts1,ts2; @@ -526,7 +528,8 @@ static NTSTATUS smb_time_audit_create_file(vfs_handle_struct *handle, sd, /* sd */ ea_list, /* ea_list */ result_fsp, /* result */ - pinfo); + pinfo, + in_context_blobs, out_context_blobs); /* create context */ clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; diff --git a/source3/modules/vfs_worm.c b/source3/modules/vfs_worm.c index 3097419..9638d96 100644 --- a/source3/modules/vfs_worm.c +++ b/source3/modules/vfs_worm.c @@ -38,7 +38,9 @@ static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { bool readonly = false; const uint32_t write_access_flags = @@ -64,7 +66,8 @@ static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle, handle, req, root_dir_fid, smb_fname, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, lease, allocation_size, - private_flags, sd, ea_list, result, pinfo); + private_flags, sd, ea_list, result, pinfo, + in_context_blobs, out_context_blobs); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 3a3a339..137df16 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -537,7 +537,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { /* Old file not found, so by definition new file is in fact newer */ @@ -591,7 +592,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { /* New file not found, this shouldn't occur if the caller did its job */ @@ -770,7 +772,8 @@ static uint32 get_correct_cversion(struct auth_session_info *session_info, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = " diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c index eaa70e7..483cafa 100644 --- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c +++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c @@ -2369,7 +2369,8 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n", @@ -2517,7 +2518,8 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n", diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 162684b..6fd5d69 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1147,7 +1147,8 @@ static NTSTATUS get_file_handle_for_metadata(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ ret_fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (NT_STATUS_IS_OK(status)) { *need_close = true; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index edad3e4..4423a44 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -579,7 +579,8 @@ void reply_ntcreate_and_X(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -1186,7 +1187,8 @@ static void call_nt_transact_create(connection_struct *conn, sd, /* sd */ ea_list, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if(!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -1430,7 +1432,8 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp1, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { goto out; @@ -1455,7 +1458,8 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp2, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { close_file(NULL, fsp1, ERROR_CLOSE); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f5ad900..c6b67f4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3703,7 +3703,8 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (NT_STATUS_IS_OK(status)) { close_file(req, fsp, NORMAL_CLOSE); @@ -3882,7 +3883,8 @@ NTSTATUS open_streams_for_delete(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &streams[i], /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Could not open stream %s: %s\n", @@ -4831,7 +4833,9 @@ NTSTATUS create_file_default(connection_struct *conn, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { int info = FILE_WAS_OPENED; files_struct *fsp = NULL; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 702da2e..e40a77b 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -648,9 +648,11 @@ NTSTATUS create_file_default(connection_struct *conn, uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, - files_struct **result, - int *pinfo); + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs); + NTSTATUS get_relative_fid_filename(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21be320..8d59412 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2009,7 +2009,8 @@ void reply_open(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -2178,7 +2179,8 @@ void reply_open_and_X(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &smb_action); /* pinfo */ + &smb_action, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -2426,7 +2428,8 @@ void reply_mknew(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -2554,7 +2557,8 @@ void reply_ctemp(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { TALLOC_FREE(fname); @@ -2772,7 +2776,8 @@ static NTSTATUS do_unlink(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n", @@ -6043,7 +6048,8 @@ void reply_rmdir(struct smb_request *req) NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -6811,7 +6817,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not open rename source %s: %s\n", @@ -6958,7 +6965,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE " @@ -7228,7 +7236,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp1, /* result */ - NULL); /* psbuf */ + NULL, /* psbuf */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { goto out; @@ -7258,7 +7267,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, NULL, /* sd */ NULL, /* ea_list */ &fsp2, /* result */ - NULL); /* psbuf */ + NULL, /* psbuf */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { close_file(NULL, fsp1, ERROR_CLOSE); diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 77e0c96..2f9d500 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -1071,7 +1071,9 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, sec_desc, ea_list, &result, - &info); + &info, + &in_context_blobs, + state->out_context_blobs); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(smb1req->xconn, smb1req->mid)) { return req; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 60128ef..e2640e4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1227,7 +1227,8 @@ static void call_trans2open(connection_struct *conn, NULL, /* sd */ ea_list, /* ea_list */ &fsp, /* result */ - &smb_action); /* psbuf */ + &smb_action, /* psbuf */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { @@ -5995,7 +5996,8 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &new_fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ TALLOC_FREE(smb_fname_tmp); @@ -6981,7 +6983,8 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &new_fsp, /* result */ - NULL); /* pinfo */ + NULL, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { /* NB. We check for open_was_deferred in the caller. */ @@ -7497,7 +7500,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (NT_STATUS_IS_OK(status)) { close_file(req, fsp, NORMAL_CLOSE); @@ -7730,7 +7734,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { return status; @@ -7861,7 +7866,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - &info); /* pinfo */ + &info, /* pinfo */ + NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 4b96963..51362c3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1545,7 +1545,9 @@ NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, - int *pinfo) + int *pinfo, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) { VFS_FIND(create_file); return handle->fns->create_file_fn( @@ -1553,7 +1555,7 @@ NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle, share_access, create_disposition, create_options, file_attributes, oplock_request, lease, allocation_size, private_flags, sd, ea_list, - result, pinfo); + result, pinfo, in_context_blobs, out_context_blobs); } int smb_vfs_call_close(struct vfs_handle_struct *handle, -- 1.9.1 From f87c7f09df915c7cf819a4c6c08794864a15cc61 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 22 Aug 2014 03:48:50 +0200 Subject: [PATCH 04/12] s3:smbd: add SMB2 AAPL create context defines Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 80849d31a1be489c292a82b8abb95d843988154a) --- libcli/smb/smb2_constants.h | 1 + libcli/smb/smb2_create_ctx.h | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 libcli/smb/smb2_create_ctx.h diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h index 0b34723..fbab3e1 100644 --- a/libcli/smb/smb2_constants.h +++ b/libcli/smb/smb2_constants.h @@ -207,6 +207,7 @@ #define SMB2_CREATE_TAG_RQLS "RqLs" #define SMB2_CREATE_TAG_DH2Q "DH2Q" #define SMB2_CREATE_TAG_DH2C "DH2C" +#define SMB2_CREATE_TAG_AAPL "AAPL" #define SMB2_CREATE_TAG_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74" /* SMB2 notify flags */ diff --git a/libcli/smb/smb2_create_ctx.h b/libcli/smb/smb2_create_ctx.h new file mode 100644 index 0000000..cb194f5 --- /dev/null +++ b/libcli/smb/smb2_create_ctx.h @@ -0,0 +1,46 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 create context specifc stuff + + Copyright (C) Ralph Boehme 2014 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __LIBCLI_SMB2_CREATE_CTX_H__ +#define __LIBCLI_SMB2_CREATE_CTX_H__ + +/* http://opensource.apple.com/source/smb/smb-697.1.1/kernel/netsmb/smb_2.h */ + +/* "AAPL" Context Command Codes */ +#define SMB2_CRTCTX_AAPL_SERVER_QUERY 1 +#define SMB2_CRTCTX_AAPL_RESOLVE_ID 2 + +/* "AAPL" Server Query request/response bitmap */ +#define SMB2_CRTCTX_AAPL_SERVER_CAPS 1 +#define SMB2_CRTCTX_AAPL_VOLUME_CAPS 2 +#define SMB2_CRTCTX_AAPL_MODEL_INFO 4 + +/* "AAPL" Client/Server Capabilities bitmap */ +#define SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR 1 +#define SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE 2 +#define SMB2_CRTCTX_AAPL_UNIX_BASED 4 +#define SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE 8 + +/* "AAPL" Volume Capabilities bitmap */ +#define SMB2_CRTCTX_AAPL_SUPPORT_RESOLVE_ID 1 +#define SMB2_CRTCTX_AAPL_CASE_SENSITIVE 2 + +#endif -- 1.9.1 From fdcb66996f757827c992fa2744d9dc9115ae8c1c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 8 Sep 2014 23:18:35 +0200 Subject: [PATCH 05/12] libcli/security: add NFS SID mappings Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 549ee51674a3a50f866bcf37b3ae58f5e8a9080e) --- libcli/security/dom_sid.h | 5 +++++ libcli/security/util_sid.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/libcli/security/dom_sid.h b/libcli/security/dom_sid.h index c4a417b..cf3cedea 100644 --- a/libcli/security/dom_sid.h +++ b/libcli/security/dom_sid.h @@ -53,6 +53,11 @@ extern const struct dom_sid global_sid_Builtin_Replicator; extern const struct dom_sid global_sid_Builtin_PreWin2kAccess; extern const struct dom_sid global_sid_Unix_Users; extern const struct dom_sid global_sid_Unix_Groups; +extern const struct dom_sid global_sid_Unix_NFS; +extern const struct dom_sid global_sid_Unix_NFS_Users; +extern const struct dom_sid global_sid_Unix_NFS_Groups; +extern const struct dom_sid global_sid_Unix_NFS_Mode; +extern const struct dom_sid global_sid_Unix_NFS_Other; int dom_sid_compare_auth(const struct dom_sid *sid1, const struct dom_sid *sid2); diff --git a/libcli/security/util_sid.c b/libcli/security/util_sid.c index 8e42826..5127109 100644 --- a/libcli/security/util_sid.c +++ b/libcli/security/util_sid.c @@ -96,6 +96,23 @@ const struct dom_sid global_sid_Unix_Users = /* Unmapped Unix users */ const struct dom_sid global_sid_Unix_Groups = /* Unmapped Unix groups */ { 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +/* + * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx + */ +const struct dom_sid global_sid_Unix_NFS = /* MS NFS and Apple style */ +{ 1, 1, {0,0,0,0,0,5}, {88,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const struct dom_sid global_sid_Unix_NFS_Users = /* Unix uid, MS NFS and Apple style */ +{ 1, 2, {0,0,0,0,0,5}, {88,1,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const struct dom_sid global_sid_Unix_NFS_Groups = /* Unix gid, MS NFS and Apple style */ +{ 1, 2, {0,0,0,0,0,5}, {88,2,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const struct dom_sid global_sid_Unix_NFS_Mode = /* Unix mode */ +{ 1, 2, {0,0,0,0,0,5}, {88,3,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +/* Unused, left here for documentary purposes */ +#if 0 +const struct dom_sid global_sid_Unix_NFS_Other = /* Unix other, MS NFS and Apple style */ +{ 1, 2, {0,0,0,0,0,5}, {88,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +#endif + /* Unused, left here for documentary purposes */ #if 0 #define SECURITY_NULL_SID_AUTHORITY 0 -- 1.9.1 From 75dc39086c110e8750e2e66b76f25d8e43146420 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 14 Oct 2014 13:54:05 +0200 Subject: [PATCH 06/12] libcli/security: add a function that checks for MS NFS ACEs Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 2ab6b43da63715350db8675bd3804e64f4241bca) --- libcli/security/security_descriptor.c | 22 ++++++++++++++++++++++ libcli/security/security_descriptor.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/libcli/security/security_descriptor.c b/libcli/security/security_descriptor.c index 8304b20..a75942c 100644 --- a/libcli/security/security_descriptor.c +++ b/libcli/security/security_descriptor.c @@ -595,3 +595,25 @@ struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, return ace; } + +/******************************************************************* + Check for MS NFS ACEs in a sd +*******************************************************************/ +bool security_descriptor_with_ms_nfs(const struct security_descriptor *psd) +{ + int i; + + if (psd->dacl == NULL) { + return false; + } + + for (i = 0; i < psd->dacl->num_aces; i++) { + if (dom_sid_compare_domain( + &global_sid_Unix_NFS, + &psd->dacl->aces[i].trustee) == 0) { + return true; + } + } + + return false; +} diff --git a/libcli/security/security_descriptor.h b/libcli/security/security_descriptor.h index 1c7f893..87643bc 100644 --- a/libcli/security/security_descriptor.h +++ b/libcli/security/security_descriptor.h @@ -81,4 +81,6 @@ struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx, struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */ uint32_t (*generic_map)(uint32_t access_mask)); +bool security_descriptor_with_ms_nfs(const struct security_descriptor *psd); + #endif /* __SECURITY_DESCRIPTOR_H__ */ -- 1.9.1 From d4784fc966b2780b8866aecda249fcc91cf7be54 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 26 Nov 2014 18:01:37 +0100 Subject: [PATCH 07/12] s3:smbd: ignore dacls with MS NFS ACEs Ignore NFS ACEs in code the modifies * default POSIX ACLs * VFS: NFSv4 ACLs * VFS: xattr and tdb ACLs Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 5ff72827c3b74f28995b45250fe8efa79495e3b6) --- source3/modules/nfs4_acls.c | 3 +++ source3/modules/vfs_acl_common.c | 9 +++++++++ source3/smbd/posix_acls.c | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index cf61af9..1aa819a 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -778,6 +778,9 @@ static bool smbacl4_fill_ace4( ace_v4->who.gid = gid; } else if (sid_to_uid(&ace_nt->trustee, &uid)) { ace_v4->who.uid = uid; + } else if (dom_sid_compare_domain(&ace_nt->trustee, + &global_sid_Unix_NFS) == 0) { + return false; } else { DEBUG(1, ("nfs4_acls.c: file [%s]: could not " "convert %s to uid or gid\n", diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index b749157..920c811 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -775,6 +775,15 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, psd->group_sid = orig_psd->group_sid; } if (security_info_sent & SECINFO_DACL) { + if (security_descriptor_with_ms_nfs(orig_psd)) { + /* + * If the sd contains a MS NFS SID, do + * nothing, it's a chmod() request from OS X + * with AAPL context. + */ + TALLOC_FREE(frame); + return NT_STATUS_OK; + } psd->dacl = orig_psd->dacl; psd->type |= SEC_DESC_DACL_PRESENT; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 126b822..6a5ec85 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3666,6 +3666,16 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s return NT_STATUS_INVALID_PARAMETER; } + /* + * MS NFS mode, here's the deal: the client merely wants to + * modify the mode, but roundtripping get_acl/set/acl would + * add additional POSIX ACEs. So in case we get a request + * containing a MS NFS mode SID, we do nothing here. + */ + if (security_descriptor_with_ms_nfs(psd_orig)) { + return NT_STATUS_OK; + } + psd = security_descriptor_copy(talloc_tos(), psd_orig); if (psd == NULL) { return NT_STATUS_NO_MEMORY; -- 1.9.1 From 602abf390879a8011852df40655ecff75dbc9aba Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 26 Nov 2014 18:11:17 +0100 Subject: [PATCH 08/12] vfs_fruit: AAPL support * readdir_attr VFS functions, used in trans2 when marshalling metadata associated with a directory entry * support for reading and writing UNIX mode via MS NFS ACEs in NT ACL Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 353acb6d294bd32fdaaf1e4d95c663cae30775a0) --- source3/modules/vfs_fruit.c | 459 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 453 insertions(+), 6 deletions(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index ec75d27..c5d92ef 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -28,6 +28,7 @@ #include "smbd/globals.h" #include "messages.h" #include "libcli/security/security.h" +#include "../libcli/smb/smb2_create_ctx.h" /* * Enhanced OS X and Netatalk compatibility @@ -121,6 +122,20 @@ struct fruit_config_data { enum fruit_meta meta; enum fruit_locking locking; enum fruit_encoding encoding; + bool use_aapl; + bool readdir_attr_enabled; + bool unix_info_enabled; + + /* + * Additional undocumented options, all enabled by default, + * possibly useful for analyzing performance. The associated + * operations with each of them may be expensive, so having + * the chance to disable them individually gives a chance + * tweaking the setup for the particular usecase. + */ + bool readdir_attr_rsize; + bool readdir_attr_finder_info; + bool readdir_attr_max_access; }; static const struct enum_list fruit_rsrc[] = { @@ -1250,6 +1265,25 @@ static int init_fruit_config(vfs_handle_struct *handle) } config->encoding = (enum fruit_encoding)enumval; + if (lp_parm_bool(-1, FRUIT_PARAM_TYPE_NAME, "aapl", true)) { + config->use_aapl = true; + } + + if (lp_parm_bool(SNUM(handle->conn), + "readdir_attr", "aapl_rsize", true)) { + config->readdir_attr_rsize = true; + } + + if (lp_parm_bool(SNUM(handle->conn), + "readdir_attr", "aapl_finder_info", true)) { + config->readdir_attr_finder_info = true; + } + + if (lp_parm_bool(SNUM(handle->conn), + "readdir_attr", "aapl_max_access", true)) { + config->readdir_attr_max_access = true; + } + SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct fruit_config_data, return -1); @@ -1662,6 +1696,231 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, return status; } +static NTSTATUS check_aapl(vfs_handle_struct *handle, + struct smb_request *req, + const struct smb2_create_blobs *in_context_blobs, + struct smb2_create_blobs *out_context_blobs) +{ + struct fruit_config_data *config; + NTSTATUS status; + struct smb2_create_blob *aapl = NULL; + uint32_t cmd; + bool ok; + uint8_t p[16]; + DATA_BLOB blob = data_blob_talloc(req, NULL, 0); + uint64_t req_bitmap, client_caps; + uint64_t server_caps = SMB2_CRTCTX_AAPL_UNIX_BASED; + smb_ucs2_t *model; + size_t modellen; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + if (!config->use_aapl + || in_context_blobs == NULL + || out_context_blobs == NULL) { + return NT_STATUS_OK; + } + + aapl = smb2_create_blob_find(in_context_blobs, + SMB2_CREATE_TAG_AAPL); + if (aapl == NULL) { + return NT_STATUS_OK; + } + + if (aapl->data.length != 24) { + DEBUG(1, ("unexpected AAPL ctxt legnth: %ju\n", + (uintmax_t)aapl->data.length)); + return NT_STATUS_INVALID_PARAMETER; + } + + cmd = IVAL(aapl->data.data, 0); + if (cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) { + DEBUG(1, ("unsupported AAPL cmd: %d\n", cmd)); + return NT_STATUS_INVALID_PARAMETER; + } + + req_bitmap = BVAL(aapl->data.data, 8); + client_caps = BVAL(aapl->data.data, 16); + + SIVAL(p, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY); + SIVAL(p, 4, 0); + SBVAL(p, 8, req_bitmap); + ok = data_blob_append(req, &blob, p, 16); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + + if (req_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS) { + if ((client_caps & SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR) && + (handle->conn->tcon->compat->fs_capabilities & FILE_NAMED_STREAMS)) { + server_caps |= SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR; + config->readdir_attr_enabled = true; + } + + /* + * The client doesn't set the flag, so we can't check + * for it and just set it unconditionally + */ + server_caps |= SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE; + config->unix_info_enabled = true; + + SBVAL(p, 0, server_caps); + ok = data_blob_append(req, &blob, p, 8); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + } + + if (req_bitmap & SMB2_CRTCTX_AAPL_VOLUME_CAPS) { + SBVAL(p, 0, + lp_case_sensitive(SNUM(handle->conn->tcon->compat)) ? + SMB2_CRTCTX_AAPL_CASE_SENSITIVE : 0); + ok = data_blob_append(req, &blob, p, 8); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + } + + if (req_bitmap & SMB2_CRTCTX_AAPL_MODEL_INFO) { + ok = convert_string_talloc(req, + CH_UNIX, CH_UTF16LE, + "Samba", strlen("Samba"), + &model, &modellen); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + + SIVAL(p, 0, 0); + SIVAL(p + 4, 0, modellen); + ok = data_blob_append(req, &blob, p, 8); + if (!ok) { + talloc_free(model); + return NT_STATUS_UNSUCCESSFUL; + } + + ok = data_blob_append(req, &blob, model, modellen); + talloc_free(model); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + } + + status = smb2_create_blob_add(out_context_blobs, + out_context_blobs, + SMB2_CREATE_TAG_AAPL, + blob); + + return status; +} + +static NTSTATUS readdir_attr_macmeta(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct readdir_attr_data *attr_data) +{ + NTSTATUS status = NT_STATUS_OK; + uint32_t date_added; + struct adouble *ad = NULL; + struct fruit_config_data *config = NULL; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + + /* Ensure we return a default value in the creation_date field */ + RSIVAL(&attr_data->attr_data.aapl.finder_info, 12, AD_DATE_START); + + /* + * Resource fork length + */ + + if (config->readdir_attr_rsize) { + ad = ad_get(talloc_tos(), handle, smb_fname->base_name, + ADOUBLE_RSRC); + if (ad) { + attr_data->attr_data.aapl.rfork_size = ad_getentrylen( + ad, ADEID_RFORK); + TALLOC_FREE(ad); + } + } + + /* + * FinderInfo + */ + + if (config->readdir_attr_finder_info) { + ad = ad_get(talloc_tos(), handle, smb_fname->base_name, + ADOUBLE_META); + if (ad) { + if (S_ISREG(smb_fname->st.st_ex_mode)) { + /* finder_type */ + memcpy(&attr_data->attr_data.aapl.finder_info[0], + ad_entry(ad, ADEID_FINDERI), 4); + + /* finder_creator */ + memcpy(&attr_data->attr_data.aapl.finder_info[0] + 4, + ad_entry(ad, ADEID_FINDERI) + 4, 4); + } + + /* finder_flags */ + memcpy(&attr_data->attr_data.aapl.finder_info[0] + 8, + ad_entry(ad, ADEID_FINDERI) + 8, 2); + + /* finder_ext_flags */ + memcpy(&attr_data->attr_data.aapl.finder_info[0] + 10, + ad_entry(ad, ADEID_FINDERI) + 24, 2); + + /* creation date */ + date_added = convert_time_t_to_uint32_t( + smb_fname->st.st_ex_btime.tv_sec - AD_DATE_DELTA); + RSIVAL(&attr_data->attr_data.aapl.finder_info[0], 12, date_added); + + TALLOC_FREE(ad); + } + } + + TALLOC_FREE(ad); + return status; +} + +/* Search MS NFS style ACE with UNIX mode */ +static NTSTATUS check_ms_nfs(vfs_handle_struct *handle, + files_struct *fsp, + const struct security_descriptor *psd, + mode_t *pmode, + bool *pdo_chmod) +{ + int i; + struct fruit_config_data *config = NULL; + + *pdo_chmod = false; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + if (psd->dacl == NULL || !config->unix_info_enabled) { + return NT_STATUS_OK; + } + + for (i = 0; i < psd->dacl->num_aces; i++) { + if (dom_sid_compare_domain( + &global_sid_Unix_NFS_Mode, + &psd->dacl->aces[i].trustee) == 0) { + *pmode = (mode_t)psd->dacl->aces[i].trustee.sub_auths[2]; + *pmode &= (S_IRWXU | S_IRWXG | S_IRWXO); + *pdo_chmod = true; + + DEBUG(10, ("MS NFS chmod request %s, %04o\n", + fsp_str_dbg(fsp), *pmode)); + break; + } + } + + return NT_STATUS_OK; +} + /**************************************************************************** * VFS ops ****************************************************************************/ @@ -2881,6 +3140,14 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, NTSTATUS status; struct fruit_config_data *config = NULL; + status = check_aapl(handle, req, in_context_blobs, out_context_blobs); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + status = SMB_VFS_NEXT_CREATE_FILE( handle, req, root_dir_fid, smb_fname, access_mask, share_access, @@ -2889,9 +3156,7 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, lease, allocation_size, private_flags, sd, ea_list, result, - pinfo, - in_context_blobs, out_context_blobs); - + pinfo, in_context_blobs, out_context_blobs); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2902,9 +3167,6 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, return status; } - SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data, - return NT_STATUS_UNSUCCESSFUL); - if (config->locking == FRUIT_LOCKING_NETATALK) { status = fruit_check_access( handle, *result, @@ -2928,6 +3190,186 @@ fail: return status; } +static NTSTATUS fruit_readdir_attr(struct vfs_handle_struct *handle, + const struct smb_filename *fname, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + struct fruit_config_data *config = NULL; + struct readdir_attr_data *attr_data; + NTSTATUS status; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + if (!config->use_aapl) { + return SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data); + } + + DEBUG(10, ("fruit_readdir_attr %s\n", fname->base_name)); + + *pattr_data = talloc_zero(mem_ctx, struct readdir_attr_data); + if (*pattr_data == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + attr_data = *pattr_data; + attr_data->type = RDATTR_AAPL; + + /* + * Mac metadata: compressed FinderInfo, resource fork length + * and creation date + */ + status = readdir_attr_macmeta(handle, fname, attr_data); + if (!NT_STATUS_IS_OK(status)) { + /* + * Error handling is tricky: if we return failure from + * this function, the corresponding directory entry + * will to be passed to the client, so we really just + * want to error out on fatal errors. + */ + if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + goto fail; + } + } + + /* + * UNIX mode + */ + if (config->unix_info_enabled) { + attr_data->attr_data.aapl.unix_mode = fname->st.st_ex_mode; + } + + /* + * max_access + */ + if (!config->readdir_attr_max_access) { + attr_data->attr_data.aapl.max_access = FILE_GENERIC_ALL; + } else { + status = smbd_calculate_access_mask( + handle->conn, + fname, + false, + SEC_FLAG_MAXIMUM_ALLOWED, + &attr_data->attr_data.aapl.max_access); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + return NT_STATUS_OK; + +fail: + DEBUG(1, ("fruit_readdir_attr %s, error: %s\n", + fname->base_name, nt_errstr(status))); + TALLOC_FREE(*pattr_data); + return status; +} + +static NTSTATUS fruit_fget_nt_acl(vfs_handle_struct *handle, + files_struct *fsp, + uint32 security_info, + TALLOC_CTX *mem_ctx, + struct security_descriptor **ppdesc) +{ + NTSTATUS status; + struct security_ace ace; + struct dom_sid sid; + struct fruit_config_data *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, + mem_ctx, ppdesc); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * Add MS NFS style ACEs with uid, gid and mode + */ + if (!config->unix_info_enabled) { + return NT_STATUS_OK; + } + + /* MS NFS style mode */ + sid_compose(&sid, &global_sid_Unix_NFS_Mode, fsp->fsp_name->st.st_ex_mode); + init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0); + status = security_descriptor_dacl_add(*ppdesc, &ace); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("failed to add MS NFS style ACE\n")); + return status; + } + + /* MS NFS style uid */ + sid_compose(&sid, &global_sid_Unix_NFS_Users, fsp->fsp_name->st.st_ex_uid); + init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0); + status = security_descriptor_dacl_add(*ppdesc, &ace); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("failed to add MS NFS style ACE\n")); + return status; + } + + /* MS NFS style gid */ + sid_compose(&sid, &global_sid_Unix_NFS_Groups, fsp->fsp_name->st.st_ex_gid); + init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0); + status = security_descriptor_dacl_add(*ppdesc, &ace); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("failed to add MS NFS style ACE\n")); + return status; + } + + return NT_STATUS_OK; +} + +static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle, + files_struct *fsp, + uint32 security_info_sent, + const struct security_descriptor *psd) +{ + NTSTATUS status; + bool do_chmod; + mode_t ms_nfs_mode; + int result; + + DEBUG(1, ("fruit_fset_nt_acl: %s\n", fsp_str_dbg(fsp))); + + status = check_ms_nfs(handle, fsp, psd, &ms_nfs_mode, &do_chmod); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("fruit_fset_nt_acl: check_ms_nfs failed%s\n", fsp_str_dbg(fsp))); + return status; + } + + status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("fruit_fset_nt_acl: SMB_VFS_NEXT_FSET_NT_ACL failed%s\n", fsp_str_dbg(fsp))); + return status; + } + + if (do_chmod) { + if (fsp->fh->fd != -1) { + DEBUG(1, ("fchmod: %s\n", fsp_str_dbg(fsp))); + result = SMB_VFS_FCHMOD(fsp, ms_nfs_mode); + } else { + DEBUG(1, ("chmod: %s\n", fsp_str_dbg(fsp))); + result = SMB_VFS_CHMOD(fsp->conn, + fsp->fsp_name->base_name, + ms_nfs_mode); + } + + if (result != 0) { + DEBUG(1, ("chmod: %s, result: %d, %04o error %s\n", fsp_str_dbg(fsp), + result, ms_nfs_mode, strerror(errno))); + status = map_nt_error_from_unix(errno); + return status; + } + } + + return NT_STATUS_OK; +} + static struct vfs_fn_pointers vfs_fruit_fns = { .connect_fn = fruit_connect, @@ -2949,6 +3391,11 @@ static struct vfs_fn_pointers vfs_fruit_fns = { .ftruncate_fn = fruit_ftruncate, .fallocate_fn = fruit_fallocate, .create_file_fn = fruit_create_file, + .readdir_attr_fn = fruit_readdir_attr, + + /* NT ACL operations */ + .fget_nt_acl_fn = fruit_fget_nt_acl, + .fset_nt_acl_fn = fruit_fset_nt_acl, }; NTSTATUS vfs_fruit_init(void); -- 1.9.1 From 2b660282bd00ed06127535b431098863d2659690 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 26 Nov 2014 15:21:36 +0100 Subject: [PATCH 09/12] s3:smbd: add SMB_VFS_READDIR_ATTR() to marshall direntry SMB_VFS_READDIR_ATTR is a last minute hook to fetch additional metadata for a directory entry when we're already marshalling the SMB reply buffer. This would we used, when there's a need to repurpose some fields in the the reply, like it's done with Apple's SMB2 extension "AAPL". We then fetch AAPL metadata with the shiny new SMB_VFS_READDIR_ATTR() VFS call and marshall appropiately. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 2236883cdeadab02f0ed367e13b41a32b1f85c34) --- source3/smbd/trans2.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e2640e4..16498b3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -40,6 +40,7 @@ #include "rpc_server/srv_pipe_hnd.h" #include "printing.h" #include "lib/util_ea.h" +#include "lib/readdir_attr.h" #define DIR_ENTRY_SAFETY_MARGIN 4096 @@ -1627,6 +1628,7 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx, int off; int pad = 0; NTSTATUS status; + struct readdir_attr_data *readdir_attr_data = NULL; ZERO_STRUCT(mdate_ts); ZERO_STRUCT(adate_ts); @@ -1638,6 +1640,13 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx, } allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); + status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data); + if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) { + return status; + } + } + file_index = get_FileIndex(conn, &smb_fname->st); mdate_ts = smb_fname->st.st_ex_mtime; @@ -2098,17 +2107,41 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx, q = p; p += 4; /* q is placeholder for name length */ if (mode & FILE_ATTRIBUTE_REPARSE_POINT) { SIVAL(p, 0, IO_REPARSE_TAG_DFS); + } else if (readdir_attr_data && + readdir_attr_data->type == RDATTR_AAPL) { + /* + * OS X specific SMB2 extension negotiated via + * AAPL create context: return max_access in + * ea_size field. + */ + SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access); } else { unsigned int ea_size = estimate_ea_size(conn, NULL, smb_fname); SIVAL(p,0,ea_size); /* Extended attributes */ } p += 4; - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && check_mangled_names) { + + if (readdir_attr_data && + readdir_attr_data->type == RDATTR_AAPL) { + /* + * OS X specific SMB2 extension negotiated via + * AAPL create context: return resource fork + * length and compressed FinderInfo in + * shortname field. + * + * According to documentation short_name_len + * should be 0, but on the wire behaviour + * shows its set to 24 by clients. + */ + SSVAL(p, 0, 24); + + /* Resourefork length */ + SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size); + + /* Compressed FinderInfo */ + memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16); + } else if (!was_8_3 && check_mangled_names) { char mangled_name[13]; /* mangled 8.3 name. */ if (!name_to_8_3(fname,mangled_name,True, conn->params)) { @@ -2128,10 +2161,29 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx, } SSVAL(p, 0, len); } else { + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ memset(p,'\0',26); } p += 26; - SSVAL(p,0,0); p += 2; /* Reserved ? */ + + /* Reserved ? */ + if (readdir_attr_data && + readdir_attr_data->type == RDATTR_AAPL) { + /* + * OS X specific SMB2 extension negotiated via + * AAPL create context: return UNIX mode in + * reserved field. + */ + uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode; + SSVAL(p, 0, aapl_mode); + } else { + SSVAL(p, 0, 0); + } + p += 2; + SBVAL(p,0,file_index); p += 8; status = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), -- 1.9.1 From a7e296f3cb5baa6b6f8d0afc7a857b61dc92225a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 1 Oct 2014 14:36:43 +0200 Subject: [PATCH 10/12] s4:libcli/raw: make short_name available in buffer This will be used in smb2/create AAPL context torture tests, where the server returns an Mac OS X specific data blob in the short name buffer. It's not a string, so the existing string extraction doesn't cut it. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit b942d6b05f5eacfe33631534f559ab8b99369347) --- source4/libcli/raw/interfaces.h | 1 + source4/libcli/raw/rawsearch.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index 05f5da0..621a5b8 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -2740,6 +2740,7 @@ union smb_search_data { uint32_t attrib; uint32_t ea_size; uint64_t file_id; + uint8_t short_name_buf[24]; struct smb_wire_string short_name; struct smb_wire_string name; } id_both_directory_info; diff --git a/source4/libcli/raw/rawsearch.c b/source4/libcli/raw/rawsearch.c index 0705faa..6035cc2 100644 --- a/source4/libcli/raw/rawsearch.c +++ b/source4/libcli/raw/rawsearch.c @@ -456,6 +456,7 @@ NTSTATUS smb_raw_search_common(TALLOC_CTX *mem_ctx, smbcli_blob_pull_string(NULL, mem_ctx, blob, &data->id_both_directory_info.short_name, 68, 70, STR_LEN8BIT | STR_UNICODE); + memcpy(data->id_both_directory_info.short_name_buf, blob->data + 70, 24); data->id_both_directory_info.file_id = BVAL(blob->data, 96); len = smbcli_blob_pull_string(NULL, mem_ctx, blob, &data->id_both_directory_info.name, -- 1.9.1 From 74fc07af094b348f53569784f850ead9b2d66fa9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 27 Sep 2014 17:21:12 +0200 Subject: [PATCH 11/12] s4:torture:vfs_fruit: smb2/create context AAPL test Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 9994f1fed885ed6e413dffadf6ea93a97f57ac5a) --- source4/torture/vfs/fruit.c | 273 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 0c8d3a4..5d4a411 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -24,6 +24,7 @@ #include "libcli/libcli.h" #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" +#include "libcli/smb/smb2_create_ctx.h" #include "lib/cmdline/popt_common.h" #include "param/param.h" #include "libcli/resolve/resolve.h" @@ -1358,6 +1359,277 @@ done: return ret; } +static bool test_aapl(struct torture_context *tctx, + struct smb2_tree *tree1, + struct smb2_tree *tree2) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + const char *fname = BASEDIR "\\test_aapl"; + NTSTATUS status; + struct smb2_handle testdirh; + bool ret = true; + struct smb2_create io; + DATA_BLOB data; + struct smb2_create_blob *aapl = NULL; + AfpInfo *info; + const char *type_creator = "SMB,OLE!"; + char type_creator_buf[9]; + uint32_t aapl_cmd; + uint32_t aapl_reply_bitmap; + uint32_t aapl_server_caps; + uint32_t aapl_vol_caps; + char *model; + struct smb2_find f; + unsigned int count; + union smb_search_data *d; + uint64_t rfork_len; + + smb2_deltree(tree1, BASEDIR); + + status = torture_smb2_testdir(tree1, BASEDIR, &testdirh); + CHECK_STATUS(status, NT_STATUS_OK); + smb2_util_close(tree1, testdirh); + + ZERO_STRUCT(io); + io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF; + io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE | + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE); + io.in.fname = fname; + + /* + * Issuing an SMB2/CREATE with a suitably formed AAPL context, + * controls behaviour of Apple's SMB2 extensions for the whole + * session! + */ + + data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t)); + SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY); + SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS | + SMB2_CRTCTX_AAPL_VOLUME_CAPS | + SMB2_CRTCTX_AAPL_MODEL_INFO)); + SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR | + SMB2_CRTCTX_AAPL_UNIX_BASED | + SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE)); + + torture_comment(tctx, "Testing SMB2 create context AAPL\n"); + status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smb2_create(tree1, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_util_close(tree1, io.out.file.handle); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * Now check returned AAPL context + */ + torture_comment(tctx, "Comparing returned AAPL capabilites\n"); + + aapl = smb2_create_blob_find(&io.out.blobs, + SMB2_CREATE_TAG_AAPL); + + if (aapl->data.length != 50) { + /* + * uint32_t CommandCode = kAAPL_SERVER_QUERY + * uint32_t Reserved = 0; + * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS | + * kAAPL_VOLUME_CAPS | + * kAAPL_MODEL_INFO; + * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR | + * kAAPL_SUPPORTS_OSX_COPYFILE; + * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID | + * kAAPL_CASE_SENSITIVE; + * uint32_t Pad2 = 0; + * uint32_t ModelStringLen = 10; + * ucs2_t ModelString[5] = "Samba"; + */ + ret = false; + goto done; + } + + aapl_cmd = IVAL(aapl->data.data, 0); + if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) { + torture_result(tctx, TORTURE_FAIL, + "(%s) unexpected cmd: %d", + __location__, (int)aapl_cmd); + ret = false; + goto done; + } + + aapl_reply_bitmap = BVAL(aapl->data.data, 8); + if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS | + SMB2_CRTCTX_AAPL_VOLUME_CAPS | + SMB2_CRTCTX_AAPL_MODEL_INFO)) { + torture_result(tctx, TORTURE_FAIL, + "(%s) unexpected reply_bitmap: %d", + __location__, (int)aapl_reply_bitmap); + ret = false; + goto done; + } + + aapl_server_caps = BVAL(aapl->data.data, 16); + if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED | + SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR | + SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE)) { + torture_result(tctx, TORTURE_FAIL, + "(%s) unexpected server_caps: %d", + __location__, (int)aapl_server_caps); + ret = false; + goto done; + } + + aapl_vol_caps = BVAL(aapl->data.data, 24); + if (aapl_vol_caps != SMB2_CRTCTX_AAPL_CASE_SENSITIVE) { + /* this will fail on a case insensitive fs ... */ + torture_result(tctx, TORTURE_FAIL, + "(%s) unexpected vol_caps: %d", + __location__, (int)aapl_vol_caps); + ret = false; + goto done; + } + + ret = convert_string_talloc(mem_ctx, + CH_UTF16LE, CH_UNIX, + aapl->data.data + 40, 10, + &model, NULL); + if (ret == false) { + torture_result(tctx, TORTURE_FAIL, + "(%s) convert_string_talloc() failed", + __location__); + goto done; + } + if (strncmp(model, "Samba", 5) != 0) { + torture_result(tctx, TORTURE_FAIL, + "(%s) expected model \"Samba\", got: \"%s\"", + __location__, model); + ret = false; + goto done; + } + + /* + * Now that Requested AAPL extensions are enabled, setup some + * Mac files with metadata and resource fork + */ + ret = torture_setup_file(mem_ctx, tree1, fname, false); + if (ret == false) { + torture_result(tctx, TORTURE_FAIL, + "(%s) torture_setup_file() failed", + __location__); + goto done; + } + + info = torture_afpinfo_new(mem_ctx); + if (info == NULL) { + torture_result(tctx, TORTURE_FAIL, + "(%s) torture_afpinfo_new() failed", + __location__); + ret = false; + goto done; + } + + memcpy(info->afpi_FinderInfo, type_creator, 8); + ret = torture_write_afpinfo(tree1, tctx, mem_ctx, fname, info); + if (ret == false) { + torture_result(tctx, TORTURE_FAIL, + "(%s) torture_write_afpinfo() failed", + __location__); + goto done; + } + + ret = write_stream(tree1, __location__, tctx, mem_ctx, + fname, AFPRESOURCE_STREAM, + 0, 3, "foo"); + if (ret == false) { + torture_result(tctx, TORTURE_FAIL, + "(%s) write_stream() failed", + __location__); + goto done; + } + + /* + * Ok, file is prepared, now call smb2/find + */ + + ZERO_STRUCT(io); + io.in.desired_access = SEC_RIGHTS_DIR_ALL; + io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; + io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE); + io.in.create_disposition = NTCREATEX_DISP_OPEN; + io.in.fname = BASEDIR; + status = smb2_create(tree1, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + ZERO_STRUCT(f); + f.in.file.handle = io.out.file.handle; + f.in.pattern = "test_aapl"; + f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE; + f.in.max_response_size = 0x1000; + f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO; + + status = smb2_find_level(tree1, tree1, &f, &count, &d); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smb2_util_close(tree1, io.out.file.handle); + CHECK_STATUS(status, NT_STATUS_OK); + + if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) { + torture_result(tctx, TORTURE_FAIL, + "(%s) write_stream() failed", + __location__); + ret = false; + goto done; + } + + if (d[0].id_both_directory_info.short_name.private_length != 24) { + torture_result(tctx, TORTURE_FAIL, + "(%s) bad short_name length %" PRIu32 ", expected 24", + __location__, d[0].id_both_directory_info.short_name.private_length); + ret = false; + goto done; + } + + torture_comment(tctx, "short_name buffer:\n"); + dump_data(0, d[0].id_both_directory_info.short_name_buf, 24); + + /* + * Extract data as specified by the AAPL extension: + * - ea_size contains max_access + * - short_name contains resource fork length + FinderInfo + * - reserved2 contains the unix mode + */ + torture_comment(tctx, "mac_access: %" PRIx32 "\n", + d[0].id_both_directory_info.ea_size); + + rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0); + if (rfork_len != 3) { + torture_result(tctx, TORTURE_FAIL, + "(%s) expected resource fork length 3, got: %" PRIu64, + __location__, rfork_len); + ret = false; + goto done; + } + + memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8); + type_creator_buf[8] = 0; + if (strcmp(type_creator, type_creator_buf) != 0) { + torture_result(tctx, TORTURE_FAIL, + "(%s) expected type/creator \"%s\" , got: %s", + __location__, type_creator, type_creator_buf); + ret = false; + goto done; + } + +done: + talloc_free(mem_ctx); + return ret; +} + /* * Note: This test depends on "vfs objects = catia fruit * streams_xattr". Note: To run this test, use @@ -1376,6 +1648,7 @@ struct torture_suite *torture_vfs_fruit(void) torture_suite_add_2ns_smb2_test(suite, "write metadata", test_write_atalk_metadata); torture_suite_add_2ns_smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io); torture_suite_add_2ns_smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion); + torture_suite_add_2ns_smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl); return suite; } -- 1.9.1 From bde896ddd8dee60a683a6fe01a1fb84310f10630 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 28 Nov 2014 22:44:29 +0100 Subject: [PATCH 12/12] vfs_fruit: add AAPL options Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Dec 5 00:34:01 CET 2014 on sn-devel-104 (cherry picked from commit 8f4813ff3070858cfa7e7da6fb703294bdedabed) --- docs-xml/manpages/vfs_fruit.8.xml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs-xml/manpages/vfs_fruit.8.xml b/docs-xml/manpages/vfs_fruit.8.xml index 47caeb0..a9e2e6d 100644 --- a/docs-xml/manpages/vfs_fruit.8.xml +++ b/docs-xml/manpages/vfs_fruit.8.xml @@ -153,6 +153,41 @@ + + fruit:aapl = yes | no + + A global option whether to enable Apple's SMB2+ + extension codenamed AAPL. Default + yes. This extension enhances + several deficiencies when connecting from Macs: + + + directory enumeration is enriched with + Mac relevant filesystem metadata (UNIX mode, + FinderInfo, resource fork size and effective + permission), as a result the Mac client doesn't need + to fetch this metadata individuallly per directory + entry resulting in an often tremendous performance + increase. + + The ability to query and modify the + UNIX mode of directory entries. + + + There's a set of per share options that can be + used to disable the computation of specific Mac metadata + in the directory enumeration context, all are enabled by + default: + + + readdir_attr:aapl_rsize = true | false + readdir_attr:aapl_finder_info = true | false + readdir_attr:aapl_max_access = true | false + + + + + -- 1.9.1