vfs_nfs4acl_xattr: move interesting functions pointers to the top
[samba.git] / source3 / modules / vfs_nfs4acl_xattr.c
1 /*
2  * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
3  *
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
7  *
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  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, see <http://www.gnu.org/licenses/>.
25  *
26  */
27
28 #include "includes.h"
29 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "nfs4_acls.h"
32 #include "librpc/gen_ndr/ndr_nfs4acl.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_VFS
36
37 static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
38 {
39         enum ndr_err_code ndr_err;
40         struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl);
41         if (!acl) {
42                 errno = ENOMEM;
43                 return NULL;
44         }
45
46         ndr_err = ndr_pull_struct_blob(blob, acl, acl,
47                 (ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
48
49         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
50                 DEBUG(0, ("ndr_pull_acl_t failed: %s\n",
51                           ndr_errstr(ndr_err)));
52                 TALLOC_FREE(acl);
53                 return NULL;
54         }
55         return acl;
56 }
57
58 static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
59 {
60         enum ndr_err_code ndr_err;
61         DATA_BLOB blob;
62         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
63                 (ndr_push_flags_fn_t)ndr_push_nfs4acl);
64
65         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
66                 DEBUG(0, ("ndr_push_acl_t failed: %s\n",
67                           ndr_errstr(ndr_err)));
68                 return data_blob_null;
69         }
70         return blob;
71 }
72
73 static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx,
74                                          DATA_BLOB *blob,
75                                          struct SMB4ACL_T **ppacl)
76 {
77         int i;
78         struct nfs4acl *nfs4acl = NULL;
79         struct SMB4ACL_T *pacl = NULL;
80         TALLOC_CTX *frame = talloc_stackframe();
81         nfs4acl = nfs4acl_blob2acl(blob, frame);
82
83         /* create SMB4ACL data */
84         if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
85                 TALLOC_FREE(frame);
86                 return NT_STATUS_NO_MEMORY;
87         }
88         for(i=0; i<nfs4acl->a_count; i++) {
89                 SMB_ACE4PROP_T aceprop;
90
91                 aceprop.aceType  = (uint32_t) nfs4acl->ace[i].e_type;
92                 aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags;
93                 aceprop.aceMask  = (uint32_t) nfs4acl->ace[i].e_mask;
94                 aceprop.who.id   = (uint32_t) nfs4acl->ace[i].e_id;
95                 if (!strcmp(nfs4acl->ace[i].e_who,
96                             NFS4ACL_XATTR_OWNER_WHO)) {
97                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
98                         aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
99                 } else if (!strcmp(nfs4acl->ace[i].e_who,
100                                    NFS4ACL_XATTR_GROUP_WHO)) {
101                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
102                         aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
103                 } else if (!strcmp(nfs4acl->ace[i].e_who,
104                                    NFS4ACL_XATTR_EVERYONE_WHO)) {
105                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
106                         aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
107                 } else {
108                         aceprop.flags = 0;
109                 }
110                 if(smb_add_ace4(pacl, &aceprop) == NULL) {
111                         TALLOC_FREE(frame);
112                         return NT_STATUS_NO_MEMORY;
113                 }
114         }
115
116         *ppacl = pacl;
117         TALLOC_FREE(frame);
118         return NT_STATUS_OK;
119 }
120
121 /* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
122 static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
123                                    files_struct *fsp, struct SMB4ACL_T **ppacl)
124 {
125         NTSTATUS status;
126         DATA_BLOB blob = data_blob_null;
127         ssize_t length;
128         TALLOC_CTX *frame = talloc_stackframe();
129
130         do {
131                 blob.length += 1000;
132                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
133                 if (!blob.data) {
134                         TALLOC_FREE(frame);
135                         errno = ENOMEM;
136                         return NT_STATUS_NO_MEMORY;
137                 }
138                 length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length);
139                 blob.length = length;
140         } while (length == -1 && errno == ERANGE);
141         if (length == -1) {
142                 TALLOC_FREE(frame);
143                 return map_nt_error_from_unix(errno);
144         }
145         status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
146         TALLOC_FREE(frame);
147         return status;
148 }
149
150 /* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
151 static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle,
152                                 TALLOC_CTX *mem_ctx,
153                                 const struct smb_filename *smb_fname,
154                                 struct SMB4ACL_T **ppacl)
155 {
156         NTSTATUS status;
157         DATA_BLOB blob = data_blob_null;
158         ssize_t length;
159         TALLOC_CTX *frame = talloc_stackframe();
160
161         do {
162                 blob.length += 1000;
163                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
164                 if (!blob.data) {
165                         TALLOC_FREE(frame);
166                         errno = ENOMEM;
167                         return NT_STATUS_NO_MEMORY;
168                 }
169                 length = SMB_VFS_NEXT_GETXATTR(handle, smb_fname,
170                                 NFS4ACL_XATTR_NAME, blob.data, blob.length);
171                 blob.length = length;
172         } while (length == -1 && errno == ERANGE);
173         if (length == -1) {
174                 TALLOC_FREE(frame);
175                 return map_nt_error_from_unix(errno);
176         }
177         status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
178         TALLOC_FREE(frame);
179         return status;
180 }
181
182 static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
183                                     struct SMB4ACL_T *smbacl,
184                                     struct nfs4acl **pnfs4acl,
185                                     bool denymissingspecial)
186 {
187         struct nfs4acl *nfs4acl;
188         struct SMB4ACE_T *smbace;
189         bool have_special_id = false;
190         int i;
191
192         /* allocate the field of NFS4 aces */
193         nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
194         if(nfs4acl == NULL) {
195                 errno = ENOMEM;
196                 return false;
197         }
198
199         nfs4acl->a_count = smb_get_naces(smbacl);
200
201         nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
202                                          nfs4acl->a_count);
203         if(nfs4acl->ace == NULL) {
204                 TALLOC_FREE(nfs4acl);
205                 errno = ENOMEM;
206                 return false;
207         }
208
209         /* handle all aces */
210         for(smbace = smb_first_ace4(smbacl), i = 0;
211                         smbace!=NULL;
212                         smbace = smb_next_ace4(smbace), i++) {
213                 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
214
215                 nfs4acl->ace[i].e_type        = aceprop->aceType;
216                 nfs4acl->ace[i].e_flags       = aceprop->aceFlags;
217                 nfs4acl->ace[i].e_mask        = aceprop->aceMask;
218                 nfs4acl->ace[i].e_id          = aceprop->who.id;
219                 if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
220                         switch(aceprop->who.special_id) {
221                         case SMB_ACE4_WHO_EVERYONE:
222                                 nfs4acl->ace[i].e_who =
223                                         NFS4ACL_XATTR_EVERYONE_WHO;
224                                 break;
225                         case SMB_ACE4_WHO_OWNER:
226                                 nfs4acl->ace[i].e_who =
227                                         NFS4ACL_XATTR_OWNER_WHO;
228                                 break;
229                         case SMB_ACE4_WHO_GROUP:
230                                 nfs4acl->ace[i].e_who =
231                                         NFS4ACL_XATTR_GROUP_WHO;
232                                 break;
233                         default:
234                                 DEBUG(8, ("unsupported special_id %d\n", \
235                                         aceprop->who.special_id));
236                                 continue; /* don't add it !!! */
237                         }
238                         have_special_id = true;
239                 } else {
240                         nfs4acl->ace[i].e_who = "";
241                 }
242         }
243
244         if (!have_special_id && denymissingspecial) {
245                 TALLOC_FREE(nfs4acl);
246                 errno = EACCES;
247                 return false;
248         }
249
250         SMB_ASSERT(i == nfs4acl->a_count);
251
252         *pnfs4acl = nfs4acl;
253         return true;
254 }
255
256 static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
257                                       const struct smb_filename *smb_fname,
258                                       struct SMB4ACL_T *smbacl)
259 {
260         TALLOC_CTX *frame = talloc_stackframe();
261         struct nfs4acl *nfs4acl;
262         int ret;
263         bool denymissingspecial;
264         DATA_BLOB blob;
265
266         denymissingspecial = lp_parm_bool(handle->conn->params->service,
267                                           "nfs4acl_xattr",
268                                           "denymissingspecial", false);
269
270         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
271                                      denymissingspecial)) {
272                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
273                 TALLOC_FREE(frame);
274                 return false;
275         }
276
277         blob = nfs4acl_acl2blob(frame, nfs4acl);
278         if (!blob.data) {
279                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
280                 TALLOC_FREE(frame);
281                 errno = EINVAL;
282                 return false;
283         }
284         ret = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, NFS4ACL_XATTR_NAME,
285                                     blob.data, blob.length, 0);
286         if (ret != 0) {
287                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
288         }
289         TALLOC_FREE(frame);
290         return ret == 0;
291 }
292
293 /* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
294 static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle,
295                                        files_struct *fsp,
296                                        struct SMB4ACL_T *smbacl)
297 {
298         TALLOC_CTX *frame = talloc_stackframe();
299         struct nfs4acl *nfs4acl;
300         int ret;
301         bool denymissingspecial;
302         DATA_BLOB blob;
303
304         denymissingspecial = lp_parm_bool(fsp->conn->params->service,
305                                           "nfs4acl_xattr",
306                                           "denymissingspecial", false);
307
308         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
309                                      denymissingspecial)) {
310                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
311                 TALLOC_FREE(frame);
312                 return false;
313         }
314
315         blob = nfs4acl_acl2blob(frame, nfs4acl);
316         if (!blob.data) {
317                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
318                 TALLOC_FREE(frame);
319                 errno = EINVAL;
320                 return false;
321         }
322         if (fsp->fh->fd == -1) {
323                 DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
324         }
325         ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME,
326                                      blob.data, blob.length, 0);
327         if (ret != 0) {
328                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
329         }
330         TALLOC_FREE(frame);
331         return ret == 0;
332 }
333
334 static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
335 {
336         struct SMB4ACL_T *pacl = NULL;
337         struct SMB4ACE_T *pace;
338         SMB_ACE4PROP_T ace = {
339                 .flags = SMB_ACE4_ID_SPECIAL,
340                 .who = {
341                         .id = SMB_ACE4_WHO_EVERYONE,
342                 },
343                 .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
344                 .aceFlags = 0,
345                 .aceMask = SMB_ACE4_ALL_MASKS,
346         };
347
348         DEBUG(10, ("Building default full access acl\n"));
349
350         pacl = smb_create_smb4acl(mem_ctx);
351         if (pacl == NULL) {
352                 DEBUG(0, ("talloc failed\n"));
353                 errno = ENOMEM;
354                 return NULL;
355         }
356
357         pace = smb_add_ace4(pacl, &ace);
358         if (pace == NULL) {
359                 DEBUG(0, ("talloc failed\n"));
360                 TALLOC_FREE(pacl);
361                 errno = ENOMEM;
362                 return NULL;
363         }
364
365         return pacl;
366 }
367
368 /*
369  * Because there is no good way to guarantee that a new xattr will be
370  * created on file creation there might be no acl xattr on a file when
371  * trying to read the acl. In this case the acl xattr will get
372  * constructed at that time from the parent acl.
373  * If the parent ACL doesn't have an xattr either the call will
374  * recurse to the next parent directory until the share root is
375  * reached. If the share root doesn't contain an ACL xattr either a
376  * default ACL will be used.
377  * Also a default ACL will be set if a non inheriting ACL is encountered.
378  *
379  * Basic algorithm:
380  *   read acl xattr blob
381  *   if acl xattr blob doesn't exist
382  *     stat current directory to know if it's a file or directory
383  *     read acl xattr blob from parent dir
384  *     acl xattr blob to smb nfs4 acl
385  *     calculate inherited smb nfs4 acl
386  *     without inheritance use default smb nfs4 acl
387  *     smb nfs4 acl to acl xattr blob
388  *     set acl xattr blob
389  *     return smb nfs4 acl
390  *   else
391  *     acl xattr blob to smb nfs4 acl
392  *
393  * Todo: Really use mem_ctx after fixing interface of nfs4_acls
394  */
395 static struct SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
396         const struct smb_filename *smb_fname_in,
397         TALLOC_CTX *mem_ctx)
398 {
399         char *parent_dir = NULL;
400         struct SMB4ACL_T *pparentacl = NULL;
401         struct SMB4ACL_T *pchildacl = NULL;
402         struct SMB4ACE_T *pace;
403         SMB_ACE4PROP_T ace;
404         bool isdir;
405         struct smb_filename *smb_fname = NULL;
406         struct smb_filename *smb_fname_parent = NULL;
407         NTSTATUS status;
408         int ret;
409         TALLOC_CTX *frame = talloc_stackframe();
410
411         DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n",
412                         smb_fname_in->base_name));
413         smb_fname = cp_smb_filename_nostream(frame, smb_fname_in);
414         if (smb_fname == NULL) {
415                 TALLOC_FREE(frame);
416                 errno = ENOMEM;
417                 return NULL;
418         }
419
420         ret = SMB_VFS_STAT(handle->conn, smb_fname);
421         if (ret == -1) {
422                 DEBUG(0,("nfs4acls_inheritacl: failed to stat "
423                          "directory %s. Error was %s\n",
424                          smb_fname_str_dbg(smb_fname),
425                          strerror(errno)));
426                 TALLOC_FREE(frame);
427                 return NULL;
428         }
429         isdir = S_ISDIR(smb_fname->st.st_ex_mode);
430
431         if (!parent_dirname(talloc_tos(),
432                             smb_fname->base_name,
433                             &parent_dir,
434                             NULL)) {
435                 TALLOC_FREE(frame);
436                 errno = ENOMEM;
437                 return NULL;
438         }
439
440         smb_fname_parent = synthetic_smb_fname(talloc_tos(),
441                                 parent_dir,
442                                 NULL,
443                                 NULL,
444                                 0);
445         if (smb_fname_parent == NULL) {
446                 TALLOC_FREE(frame);
447                 errno = ENOMEM;
448                 return NULL;
449         }
450
451         status = nfs4_get_nfs4_acl(handle, frame, smb_fname_parent,
452                                         &pparentacl);
453         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)
454             && strncmp(parent_dir, ".", 2) != 0) {
455                 pparentacl = nfs4acls_inheritacl(handle,
456                                                 smb_fname_parent,
457                                                 frame);
458         }
459         else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
460                 pparentacl = nfs4acls_defaultacl(frame);
461
462         }
463         else if (!NT_STATUS_IS_OK(status)) {
464                 TALLOC_FREE(frame);
465                 return NULL;
466         }
467
468         pchildacl = smb_create_smb4acl(mem_ctx);
469         if (pchildacl == NULL) {
470                 DEBUG(0, ("talloc failed\n"));
471                 TALLOC_FREE(frame);
472                 errno = ENOMEM;
473                 return NULL;
474         }
475
476         for (pace = smb_first_ace4(pparentacl); pace != NULL;
477              pace = smb_next_ace4(pace)) {
478                 struct SMB4ACE_T *pchildace;
479                 ace = *smb_get_ace4(pace);
480                 if ((isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) ||
481                     (!isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))) {
482                         DEBUG(10, ("non inheriting ace type: %d, iflags: %x, "
483                                    "flags: %x, mask: %x, who: %d\n",
484                                    ace.aceType, ace.flags, ace.aceFlags,
485                                    ace.aceMask, ace.who.id));
486                         continue;
487                 }
488                 DEBUG(10, ("inheriting ace type: %d, iflags: %x, "
489                            "flags: %x, mask: %x, who: %d\n",
490                            ace.aceType, ace.flags, ace.aceFlags,
491                            ace.aceMask, ace.who.id));
492                 ace.aceFlags |= SMB_ACE4_INHERITED_ACE;
493                 if (ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) {
494                         ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE;
495                 }
496                 if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) {
497                         ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE;
498                         ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE;
499                         ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE;
500                 }
501                 pchildace = smb_add_ace4(pchildacl, &ace);
502                 if (pchildace == NULL) {
503                         DEBUG(0, ("talloc failed\n"));
504                         TALLOC_FREE(frame);
505                         errno = ENOMEM;
506                         return NULL;
507                 }
508         }
509
510         /* Set a default ACL if we didn't inherit anything. */
511         if (smb_first_ace4(pchildacl) == NULL) {
512                 TALLOC_FREE(pchildacl);
513                 pchildacl = nfs4acls_defaultacl(mem_ctx);
514         }
515
516         /* store the returned ACL to get it directly in the
517            future and avoid dynamic inheritance behavior. */
518         nfs4acl_xattr_set_smb4acl(handle, smb_fname, pchildacl);
519
520         TALLOC_FREE(frame);
521         return pchildacl;
522 }
523
524 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
525                                    struct files_struct *fsp,
526                                    uint32_t security_info,
527                                    TALLOC_CTX *mem_ctx,
528                                    struct security_descriptor **ppdesc)
529 {
530         struct SMB4ACL_T *pacl;
531         NTSTATUS status;
532         TALLOC_CTX *frame = talloc_stackframe();
533
534         status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
535         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
536                 pacl = nfs4acls_inheritacl(handle, fsp->fsp_name,
537                                            frame);
538         }
539         else if (!NT_STATUS_IS_OK(status)) {
540                 TALLOC_FREE(frame);
541                 return status;
542         }
543
544         status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx,
545                                       ppdesc, pacl);
546         TALLOC_FREE(frame);
547         return status;
548 }
549
550 static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
551                                   const struct smb_filename *smb_fname,
552                                   uint32_t security_info,
553                                   TALLOC_CTX *mem_ctx,
554                                   struct security_descriptor **ppdesc)
555 {
556         struct SMB4ACL_T *pacl;
557         NTSTATUS status;
558         TALLOC_CTX *frame = talloc_stackframe();
559
560         status = nfs4_get_nfs4_acl(handle, frame, smb_fname, &pacl);
561         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
562                 pacl = nfs4acls_inheritacl(handle, smb_fname, frame);
563         }
564         else if (!NT_STATUS_IS_OK(status)) {
565                 TALLOC_FREE(frame);
566                 return status;
567         }
568
569         status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, NULL,
570                                      security_info, mem_ctx, ppdesc,
571                                      pacl);
572         TALLOC_FREE(frame);
573         return status;
574 }
575
576 static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
577                          files_struct *fsp,
578                          uint32_t security_info_sent,
579                          const struct security_descriptor *psd)
580 {
581         return smb_set_nt_acl_nfs4(handle, fsp, NULL, security_info_sent,
582                                    psd, nfs4acl_xattr_fset_smb4acl);
583 }
584
585 /*
586    As long as Samba does not support an exiplicit method for a module
587    to define conflicting vfs methods, we should override all conflicting
588    methods here.  That way, we know we are using the NFSv4 storage
589
590    Function declarations taken from vfs_solarisacl
591 */
592
593 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
594                                         const struct smb_filename *smb_fname,
595                                         SMB_ACL_TYPE_T type,
596                                         TALLOC_CTX *mem_ctx)
597 {
598         return (SMB_ACL_T)NULL;
599 }
600
601 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
602                                                     files_struct *fsp,
603                                                     TALLOC_CTX *mem_ctx)
604 {
605         return (SMB_ACL_T)NULL;
606 }
607
608 static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
609                                          const struct smb_filename *smb_fname,
610                                          SMB_ACL_TYPE_T type,
611                                          SMB_ACL_T theacl)
612 {
613         return -1;
614 }
615
616 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
617                                        files_struct *fsp,
618                                        SMB_ACL_T theacl)
619 {
620         return -1;
621 }
622
623 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
624                         const struct smb_filename *smb_fname)
625 {
626         return -1;
627 }
628
629 static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle,
630                         const struct smb_filename *smb_fname,
631                         TALLOC_CTX *mem_ctx,
632                         char **blob_description,
633                         DATA_BLOB *blob)
634 {
635         return -1;
636 }
637
638 static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *fsp, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
639 {
640         return -1;
641 }
642
643 /* VFS operations structure */
644
645 static struct vfs_fn_pointers nfs4acl_xattr_fns = {
646         .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
647         .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
648         .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
649
650         .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
651         .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
652         .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
653         .sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
654         .sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
655         .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
656         .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
657 };
658
659 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *);
660 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *ctx)
661 {
662         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
663                                 &nfs4acl_xattr_fns);
664 }