s3: smbd: Add SMB2_FILE_POSIX_INFORMATION getinfo info level (100 on the wire).
[Samba.git] / source3 / modules / nfs4acl_xattr_ndr.c
blobffa3e69cbb50cda6277520a6c890080bc6ce91b2
1 /*
2 * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
4 * Copyright (C) Jiri Sasek, 2007
5 * based on the foobar.c module which is copyrighted by Volker Lendecke
6 * based on pvfs_acl_nfs4.c Copyright (C) Andrew Tridgell 2006
8 * based on vfs_fake_acls:
9 * Copyright (C) Tim Potter, 1999-2000
10 * Copyright (C) Alexander Bokovoy, 2002
11 * Copyright (C) Andrew Bartlett, 2002,2012
12 * Copyright (C) Ralph Boehme 2017
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 #include "includes.h"
30 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "nfs4_acls.h"
33 #include "librpc/gen_ndr/ndr_nfs4acl.h"
34 #include "nfs4acl_xattr.h"
35 #include "nfs4acl_xattr_ndr.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
40 static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
42 enum ndr_err_code ndr_err;
43 struct nfs4acl *acl = talloc_zero(mem_ctx, struct nfs4acl);
45 if (acl == NULL) {
46 errno = ENOMEM;
47 return NULL;
50 ndr_err = ndr_pull_struct_blob(blob, acl, acl,
51 (ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
53 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
54 DBG_ERR("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err));
55 TALLOC_FREE(acl);
56 return NULL;
58 return acl;
61 static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
63 enum ndr_err_code ndr_err;
64 DATA_BLOB blob;
66 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
67 (ndr_push_flags_fn_t)ndr_push_nfs4acl);
69 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
70 DBG_ERR("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err));
71 return data_blob_null;
73 return blob;
76 static uint16_t nfs4acl_to_smb4acl_flags(uint8_t nfs4acl_flags)
78 uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE;
80 if (nfs4acl_flags & ACL4_AUTO_INHERIT) {
81 smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED;
83 if (nfs4acl_flags & ACL4_PROTECTED) {
84 smb4acl_flags |= SEC_DESC_DACL_PROTECTED;
86 if (nfs4acl_flags & ACL4_DEFAULTED) {
87 smb4acl_flags |= SEC_DESC_DACL_DEFAULTED;
90 return smb4acl_flags;
93 NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle,
94 TALLOC_CTX *mem_ctx,
95 DATA_BLOB *blob,
96 struct SMB4ACL_T **_smb4acl)
98 struct nfs4acl *nfs4acl = NULL;
99 struct SMB4ACL_T *smb4acl = NULL;
100 TALLOC_CTX *frame = talloc_stackframe();
101 struct nfs4acl_config *config = NULL;
102 int i;
104 SMB_VFS_HANDLE_GET_DATA(handle, config,
105 struct nfs4acl_config,
106 return NT_STATUS_INTERNAL_ERROR);
108 nfs4acl = nfs4acl_blob2acl(blob, frame);
109 if (nfs4acl == NULL) {
110 TALLOC_FREE(frame);
111 return NT_STATUS_INTERNAL_ERROR;
114 smb4acl = smb_create_smb4acl(mem_ctx);
115 if (smb4acl == NULL) {
116 TALLOC_FREE(frame);
117 return NT_STATUS_NO_MEMORY;
120 if (config->nfs_version > ACL4_XATTR_VERSION_40 &&
121 nfs4acl->a_version > ACL4_XATTR_VERSION_40)
123 uint16_t smb4acl_flags;
125 smb4acl_flags = nfs4acl_to_smb4acl_flags(nfs4acl->a_flags);
126 smbacl4_set_controlflags(smb4acl, smb4acl_flags);
129 for (i = 0; i < nfs4acl->a_count; i++) {
130 SMB_ACE4PROP_T aceprop;
132 aceprop.aceType = (uint32_t) nfs4acl->ace[i].e_type;
133 aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags;
134 aceprop.aceMask = (uint32_t) nfs4acl->ace[i].e_mask;
135 aceprop.who.id = (uint32_t) nfs4acl->ace[i].e_id;
137 if (!strcmp(nfs4acl->ace[i].e_who,
138 NFS4ACL_XATTR_OWNER_WHO)) {
139 aceprop.flags = SMB_ACE4_ID_SPECIAL;
140 aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
141 } else if (!strcmp(nfs4acl->ace[i].e_who,
142 NFS4ACL_XATTR_GROUP_WHO)) {
143 aceprop.flags = SMB_ACE4_ID_SPECIAL;
144 aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
145 } else if (!strcmp(nfs4acl->ace[i].e_who,
146 NFS4ACL_XATTR_EVERYONE_WHO)) {
147 aceprop.flags = SMB_ACE4_ID_SPECIAL;
148 aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
149 } else {
150 aceprop.flags = 0;
153 if (smb_add_ace4(smb4acl, &aceprop) == NULL) {
154 TALLOC_FREE(frame);
155 return NT_STATUS_NO_MEMORY;
159 *_smb4acl = smb4acl;
160 TALLOC_FREE(frame);
161 return NT_STATUS_OK;
164 static uint8_t smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
166 uint8_t flags = 0;
168 if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) {
169 flags |= ACL4_AUTO_INHERIT;
171 if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) {
172 flags |= ACL4_PROTECTED;
174 if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) {
175 flags |= ACL4_DEFAULTED;
178 return flags;
181 static bool nfs4acl_smb4acl2nfs4acl(vfs_handle_struct *handle,
182 TALLOC_CTX *mem_ctx,
183 struct SMB4ACL_T *smbacl,
184 struct nfs4acl **_nfs4acl,
185 bool denymissingspecial)
187 struct nfs4acl_config *config = NULL;
188 struct nfs4acl *nfs4acl = NULL;
189 struct SMB4ACE_T *smbace = NULL;
190 bool have_special_id = false;
191 int i;
193 SMB_VFS_HANDLE_GET_DATA(handle, config,
194 struct nfs4acl_config,
195 return false);
197 nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
198 if (nfs4acl == NULL) {
199 errno = ENOMEM;
200 return false;
203 nfs4acl->a_count = smb_get_naces(smbacl);
205 nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
206 nfs4acl->a_count);
207 if (nfs4acl->ace == NULL) {
208 TALLOC_FREE(nfs4acl);
209 errno = ENOMEM;
210 return false;
213 nfs4acl->a_version = config->nfs_version;
214 if (nfs4acl->a_version > ACL4_XATTR_VERSION_40) {
215 uint16_t smb4acl_flags;
216 uint8_t flags;
218 smb4acl_flags = smbacl4_get_controlflags(smbacl);
219 flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
220 nfs4acl->a_flags = flags;
223 for (smbace = smb_first_ace4(smbacl), i = 0;
224 smbace != NULL;
225 smbace = smb_next_ace4(smbace), i++)
227 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
229 nfs4acl->ace[i].e_type = aceprop->aceType;
230 nfs4acl->ace[i].e_flags = aceprop->aceFlags;
231 nfs4acl->ace[i].e_mask = aceprop->aceMask;
232 nfs4acl->ace[i].e_id = aceprop->who.id;
233 if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
234 switch(aceprop->who.special_id) {
235 case SMB_ACE4_WHO_EVERYONE:
236 nfs4acl->ace[i].e_who =
237 NFS4ACL_XATTR_EVERYONE_WHO;
238 break;
239 case SMB_ACE4_WHO_OWNER:
240 nfs4acl->ace[i].e_who =
241 NFS4ACL_XATTR_OWNER_WHO;
242 break;
243 case SMB_ACE4_WHO_GROUP:
244 nfs4acl->ace[i].e_who =
245 NFS4ACL_XATTR_GROUP_WHO;
246 break;
247 default:
248 DBG_DEBUG("unsupported special_id %d\n",
249 aceprop->who.special_id);
250 continue; /* don't add it !!! */
252 have_special_id = true;
253 } else {
254 nfs4acl->ace[i].e_who = "";
258 if (!have_special_id && denymissingspecial) {
259 TALLOC_FREE(nfs4acl);
260 errno = EACCES;
261 return false;
264 SMB_ASSERT(i == nfs4acl->a_count);
266 *_nfs4acl = nfs4acl;
267 return true;
270 NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle,
271 TALLOC_CTX *mem_ctx,
272 struct SMB4ACL_T *smb4acl,
273 DATA_BLOB *_blob)
275 struct nfs4acl *nfs4acl = NULL;
276 DATA_BLOB blob;
277 bool denymissingspecial;
278 bool ok;
280 denymissingspecial = lp_parm_bool(SNUM(handle->conn),
281 "nfs4acl_xattr",
282 "denymissingspecial", false);
284 ok = nfs4acl_smb4acl2nfs4acl(handle, talloc_tos(), smb4acl, &nfs4acl,
285 denymissingspecial);
286 if (!ok) {
287 DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n");
288 return NT_STATUS_INTERNAL_ERROR;
291 blob = nfs4acl_acl2blob(mem_ctx, nfs4acl);
292 TALLOC_FREE(nfs4acl);
293 if (blob.data == NULL) {
294 DBG_ERR("Failed to convert ACL to linear blob for xattr\n");
295 return NT_STATUS_INTERNAL_ERROR;
298 *_blob = blob;
299 return NT_STATUS_OK;