[PATCH] SMB2 AAPL create context
Ralph Böhme
rb at sernet.de
Sun Nov 30 10:26:05 MST 2014
Hi all,
On Sat, Nov 22, 2014 at 08:41:54AM +0100, Ralph Böhme wrote:
> > >>>> diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
> > >>>> index d0015d5..5137e5e 100644
> > >>>> --- a/source3/smbd/globals.h
> > >>>> +++ b/source3/smbd/globals.h
> > >>>> @@ -504,6 +504,9 @@ struct smbXsrv_connection {
> > >>>> uint32_t max_trans;
> > >>>> uint32_t max_read;
> > >>>> uint32_t max_write;
> > >>>> + bool use_aapl_crtctx;
> > >>>> + bool smb2_crtctx_aapl_readdir_attr;
> > >>>> + bool smb2_crtctx_aapl_unix_info;
> > >>>> } server;
> > >>>>
> > >>>> struct smbd_smb2_request *requests;
> > >>>
> > >>> OK, adding these into the struct smbXsrv_connection is
> > >>> *so* the wrong place to put these :-).
> > >>
> > >> :)
> > >>
> > >>>
> > >>> I'm not sure what the right place is yet, but I don't
> > >>> think it's there... :-).
> > >>
> > >> I'd highly appreciate a recommendation where to hang them off, in the
> > >> meantime I'll poke around some more looking for the right place.
> > >
> > > smbXsrv_connection also has smb1.unix_info.client_cap_low which is
> > > used similiarily in trans2.c with a bunch of feature flags.
> > >
> > > I've looked arond some more, but couldn't come up with any other place
> > > to hang the AAPL flags off.
> >
> > If we need to access this in vfs modules...
>
> the patchset at hand does not do that, but the full
> SMB_VFS_CREATE_FILE() in trans2.c totally kills performance in a
> cluster setup, so as recommended by Volker I'm currently looking into
> adding a new lightweight VFS call whose purpose will be to fetch and
> return the required Mac metadata.
huh, glad this isn't wasn't merged yet. Tests on a cluster revealed
the calling SMB_VFS_CREATE_FILE() for every directory entry causes a
tremendeous performance hit.
Fixing this is done by moving the whole functionality out of trans2
and into vfs_fruit, which makes sense anyway. For this I needed two
modifications to the VFS interface:
* modify SMB_VFS_CREATE_FILE to include the create tags
* add a new VFS call (SMB_VFS_READDIR_ATTR) that allows fetching
arbitrary custom filesystem metadata and stashing it into the reply
buffer
With this changes in place, the remaining code is nicely consolidated
in vfs_fruit. And performance is good even in a cluster because I can
change the low-level AppleDouble metadata API from within vfs_fruit.
Comments and reviews welcome! Shipping 4.2 with this would be awesome
for Mac clients.
-Ralph
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de,mailto:kontakt@sernet.de
-------------- next part --------------
>From 048fff2616162aa109efb94d35c8dfaf45d1fbb5 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <rb at sernet.de>
Date: Fri, 22 Aug 2014 03:48:50 +0200
Subject: [PATCH 01/12] s3:smbd: add SMB2 AAPL create context defines and
options
Add a global SMB2 specific option 'use_aapl_crtctx'. It's off by
default, but later enabled in the vfs_fruit module.
Add a AAPL specific capability flag 'smb2_crtctx_aapl_readdir_attr',
when used several fields in an SMB2/FIND reply are repurposed
returning Mac specific file attributes including resource fork length,
unix mode and max_access.
Add define and flag for NFS ACE in AAPL create context. With this
extension, a client can use get_info(sec)/set_info(sec) for
- retrieving UNIX uid,gid and mode of a file with get_info
- modifying UNIX mode with set_info
Signed-off-by: Ralph Boehme <rb at sernet.de>
---
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 191de2b..1a6c5ad 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -222,6 +222,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 <http://www.gnu.org/licenses/>.
+*/
+
+#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.3
>From 75f552bb660fe72bbf11390a1a8539dbb9ae571d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <rb at sernet.de>
Date: Mon, 8 Sep 2014 23:18:35 +0200
Subject: [PATCH 02/12] libcli/security: add NFS SID mappings
Signed-off-by: Ralph Boehme <rb at sernet.de>
---
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.3
>From 0dc4db51154e663a265672d770b8afec13c38058 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 14 Oct 2014 13:54:05 +0200
Subject: [PATCH 03/12] libcli/security: add a function that checks for MS NFS
ACEs
Signed-off-by: Ralph Boehme <slow at samba.org>
---
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.3
>From 393338a7a3266da7487b5468a2e2c95c25fa0e92 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 26 Nov 2014 18:01:37 +0100
Subject: [PATCH 04/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 <slow at samba.org>
---
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.3
>From 33e7c750c36a86889a5bacebbc39b9b490914b06 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 26 Nov 2014 14:30:37 +0100
Subject: [PATCH 05/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 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".
Signed-off-by: Ralph Boehme <slow at samba.org>
---
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/smbd/vfs.c | 9 +++++++++
6 files changed, 71 insertions(+)
create mode 100644 source3/lib/readdir_attr.h
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 53d3edc..108b59d 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 b0f00e8..e443b96 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
@@ -787,6 +788,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);
};
/*
@@ -1232,6 +1238,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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 2ac7100..7610e65 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);
@@ -2521,6 +2529,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/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.3
>From 7aea51ab3e0c8abc2981299ffc5f7f292ac5d422 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Nov 2014 11:44:09 +0100
Subject: [PATCH 06/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 <slow at samba.org>
---
source3/smbd/smb2_create.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 1e31cbf..f548860 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -388,7 +388,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,
@@ -410,7 +410,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;
@@ -418,8 +417,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
struct smb2_create_blob *dh2q = 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 {
@@ -450,10 +447,13 @@ 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);
+
dhnq = smb2_create_blob_find(&in_context_blobs,
SMB2_CREATE_TAG_DHNQ);
dhnc = smb2_create_blob_find(&in_context_blobs,
@@ -986,10 +986,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);
@@ -1031,8 +1032,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)) {
@@ -1049,7 +1050,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)) {
@@ -1073,7 +1075,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)) {
@@ -1115,7 +1118,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)));
@@ -1159,9 +1161,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.3
>From 7974c6aa8c4f25fb0bf147cdc4262abbdf9f7c30 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 26 Nov 2014 14:12:51 +0100
Subject: [PATCH 07/12] s3:vfs: add create tags to SMB_VFS_CREATEFILE
Signed-off-by: Ralph Boehme <slow at samba.org>
---
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_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 ++++--
18 files changed, 117 insertions(+), 54 deletions(-)
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index fbb1323..2e2597c 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 e443b96..2f31655 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
@@ -551,7 +552,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);
@@ -962,7 +965,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 7610e65..613101a 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_full_audit.c b/source3/modules/vfs_full_audit.c
index a51ab75..6f2f48f 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -869,7 +869,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;
@@ -914,7 +916,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 9dbbf8b..617ff9f 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 5c26f15..7e42272 100644
--- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
@@ -2364,7 +2364,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",
@@ -2512,7 +2513,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 1952823..40c6108 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3408,7 +3408,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);
@@ -3587,7 +3588,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",
@@ -4344,7 +4346,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 1080895..ec2e01b9 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -636,9 +636,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 9b3ed65..fd4ec53 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",
@@ -6039,7 +6044,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)) {
@@ -6807,7 +6813,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",
@@ -6954,7 +6961,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 "
@@ -7224,7 +7232,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;
@@ -7254,7 +7263,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 f548860..2247edc 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -948,7 +948,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)) {
SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
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.3
>From 6322af8c073fc4d75c8df1ad755a8902c5217c50 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
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 <slow at samba.org>
---
source3/modules/vfs_fruit.c | 470 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 464 insertions(+), 6 deletions(-)
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index da1ec7f..97a4567 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,237 @@ 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;
+ }
+ }
+
+
+ /*
+ * FIXME: wrong talloc ctx! smb2_create uses
+ * smb2_req_state. Seems to work ok, but ...
+ */
+ 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);
+ }
+ }
+
+error:
+ 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
****************************************************************************/
@@ -2874,11 +3139,21 @@ 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;
+ 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,
@@ -2887,8 +3162,7 @@ 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;
}
@@ -2899,9 +3173,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,
@@ -2925,6 +3196,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,
@@ -2946,6 +3397,13 @@ static struct vfs_fn_pointers vfs_fruit_fns = {
.ftruncate_fn = fruit_ftruncate,
.fallocate_fn = fruit_fallocate,
.create_file_fn = fruit_create_file,
+
+ /* Directory operations */
+ .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.3
>From 482f92218d5f22e255bdb81e5086d9b47df0ab1e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
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 <slow at samba.org>
---
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..1a62345 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
+ * lenght 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.3
>From 0fcc1c61acb0e52b3dda67864101c7f69b4ae786 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <rb at sernet.de>
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 <rb at sernet.de>
---
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 dd0c3bd..5804a6b 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.3
>From 98ec07c6b9b86dfbd1398a4a7e643e683de3a1f0 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <rb at sernet.de>
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 <rb at sernet.de>
---
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.3
>From 70ab1777514f0e87729336cc114555858c3cb3af Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Nov 2014 22:44:29 +0100
Subject: [PATCH 12/12] vfs_fruit: add AAPL options
Signed-off-by: Ralph Boehme <slow at samba.org>
---
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 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>fruit:aapl = yes | no</term>
+ <listitem>
+ <para>A global option whether to enable Apple's SMB2+
+ extension codenamed AAPL. Default
+ <emphasis>yes</emphasis>. This extension enhances
+ several deficiencies when connecting from Macs:</para>
+
+ <itemizedlist>
+ <listitem><para>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.</para></listitem>
+
+ <listitem><para>The ability to query and modify the
+ UNIX mode of directory entries.</para></listitem>
+ </itemizedlist>
+
+ <para>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:</para>
+
+ <itemizedlist>
+ <listitem><para>readdir_attr:aapl_rsize = true | false</para></listitem>
+ <listitem><para>readdir_attr:aapl_finder_info = true | false</para></listitem>
+ <listitem><para>readdir_attr:aapl_max_access = true | false</para></listitem>
+ </itemizedlist>
+
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
--
1.9.3
More information about the samba-technical
mailing list