bdaca82b8ca52b4a5bdf45f17412aa4d2ea2bc7d
[kamenim/samba-autobuild/.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                                          SMB4ACL_T **ppacl)
76 {
77         int i;
78         struct nfs4acl *nfs4acl = NULL;
79         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) nfs4acl->ace[i].e_type;
92                 aceprop.aceFlags = (uint32) nfs4acl->ace[i].e_flags;
93                 aceprop.aceMask  = (uint32) nfs4acl->ace[i].e_mask;
94                 aceprop.who.id   = (uint32) 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, 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, TALLOC_CTX *mem_ctx,
152                                   const char *path, SMB4ACL_T **ppacl)
153 {
154         NTSTATUS status;
155         DATA_BLOB blob = data_blob_null;
156         ssize_t length;
157         TALLOC_CTX *frame = talloc_stackframe();
158
159         do {
160                 blob.length += 1000;
161                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
162                 if (!blob.data) {
163                         TALLOC_FREE(frame);
164                         errno = ENOMEM;
165                         return NT_STATUS_NO_MEMORY;
166                 }
167                 length = SMB_VFS_NEXT_GETXATTR(handle, path, NFS4ACL_XATTR_NAME, blob.data, blob.length);
168                 blob.length = length;
169         } while (length == -1 && errno == ERANGE);
170         if (length == -1) {
171                 TALLOC_FREE(frame);
172                 return map_nt_error_from_unix(errno);
173         }
174         status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
175         TALLOC_FREE(frame);
176         return status;
177 }
178
179 static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
180                                     SMB4ACL_T *smbacl,
181                                     struct nfs4acl **pnfs4acl,
182                                     bool denymissingspecial)
183 {
184         struct nfs4acl *nfs4acl;
185         SMB4ACE_T *smbace;
186         bool have_special_id = false;
187         int i;
188
189         /* allocate the field of NFS4 aces */
190         nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
191         if(nfs4acl == NULL) {
192                 errno = ENOMEM;
193                 return false;
194         }
195
196         nfs4acl->a_count = smb_get_naces(smbacl);
197
198         nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
199                                          nfs4acl->a_count);
200         if(nfs4acl->ace == NULL) {
201                 TALLOC_FREE(nfs4acl);
202                 errno = ENOMEM;
203                 return false;
204         }
205
206         /* handle all aces */
207         for(smbace = smb_first_ace4(smbacl), i = 0;
208                         smbace!=NULL;
209                         smbace = smb_next_ace4(smbace), i++) {
210                 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
211
212                 nfs4acl->ace[i].e_type        = aceprop->aceType;
213                 nfs4acl->ace[i].e_flags       = aceprop->aceFlags;
214                 nfs4acl->ace[i].e_mask        = aceprop->aceMask;
215                 nfs4acl->ace[i].e_id          = aceprop->who.id;
216                 if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
217                         switch(aceprop->who.special_id) {
218                         case SMB_ACE4_WHO_EVERYONE:
219                                 nfs4acl->ace[i].e_who =
220                                         NFS4ACL_XATTR_EVERYONE_WHO;
221                                 break;
222                         case SMB_ACE4_WHO_OWNER:
223                                 nfs4acl->ace[i].e_who =
224                                         NFS4ACL_XATTR_OWNER_WHO;
225                                 break;
226                         case SMB_ACE4_WHO_GROUP:
227                                 nfs4acl->ace[i].e_who =
228                                         NFS4ACL_XATTR_GROUP_WHO;
229                                 break;
230                         default:
231                                 DEBUG(8, ("unsupported special_id %d\n", \
232                                         aceprop->who.special_id));
233                                 continue; /* don't add it !!! */
234                         }
235                         have_special_id = true;
236                 } else {
237                         nfs4acl->ace[i].e_who = "";
238                 }
239         }
240
241         if (!have_special_id && denymissingspecial) {
242                 TALLOC_FREE(nfs4acl);
243                 errno = EACCES;
244                 return false;
245         }
246
247         SMB_ASSERT(i == nfs4acl->a_count);
248
249         *pnfs4acl = nfs4acl;
250         return true;
251 }
252
253 static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
254                                       const char *path,
255                                       SMB4ACL_T *smbacl)
256 {
257         TALLOC_CTX *frame = talloc_stackframe();
258         struct nfs4acl *nfs4acl;
259         int ret;
260         bool denymissingspecial;
261         DATA_BLOB blob;
262
263         denymissingspecial = lp_parm_bool(handle->conn->params->service,
264                                           "nfs4acl_xattr",
265                                           "denymissingspecial", false);
266
267         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
268                                      denymissingspecial)) {
269                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
270                 TALLOC_FREE(frame);
271                 return false;
272         }
273
274         blob = nfs4acl_acl2blob(frame, nfs4acl);
275         if (!blob.data) {
276                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
277                 TALLOC_FREE(frame);
278                 errno = EINVAL;
279                 return false;
280         }
281         ret = SMB_VFS_NEXT_SETXATTR(handle, path, NFS4ACL_XATTR_NAME,
282                                     blob.data, blob.length, 0);
283         if (ret != 0) {
284                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
285         }
286         TALLOC_FREE(frame);
287         return ret == 0;
288 }
289
290 /* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
291 static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle,
292                                        files_struct *fsp,
293                                        SMB4ACL_T *smbacl)
294 {
295         TALLOC_CTX *frame = talloc_stackframe();
296         struct nfs4acl *nfs4acl;
297         int ret;
298         bool denymissingspecial;
299         DATA_BLOB blob;
300
301         denymissingspecial = lp_parm_bool(fsp->conn->params->service,
302                                           "nfs4acl_xattr",
303                                           "denymissingspecial", false);
304
305         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
306                                      denymissingspecial)) {
307                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
308                 TALLOC_FREE(frame);
309                 return false;
310         }
311
312         blob = nfs4acl_acl2blob(frame, nfs4acl);
313         if (!blob.data) {
314                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
315                 TALLOC_FREE(frame);
316                 errno = EINVAL;
317                 return false;
318         }
319         if (fsp->fh->fd == -1) {
320                 DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
321         }
322         ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME,
323                                      blob.data, blob.length, 0);
324         if (ret != 0) {
325                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
326         }
327         TALLOC_FREE(frame);
328         return ret == 0;
329 }
330
331 /* nfs4_set_nt_acl()
332  * set the local file's acls obtaining it in NT form
333  * using the NFSv4 format conversion
334  */
335 static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
336                            uint32 security_info_sent,
337                            const struct security_descriptor *psd)
338 {
339         return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
340                         nfs4acl_xattr_fset_smb4acl);
341 }
342
343 static SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
344 {
345         SMB4ACL_T *pacl = NULL;
346         SMB4ACE_T *pace;
347         SMB_ACE4PROP_T ace = { SMB_ACE4_ID_SPECIAL,
348                 SMB_ACE4_WHO_EVERYONE,
349                 SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
350                 0,
351                 SMB_ACE4_ALL_MASKS };
352
353         DEBUG(10, ("Building default full access acl\n"));
354
355         pacl = smb_create_smb4acl(mem_ctx);
356         if (pacl == NULL) {
357                 DEBUG(0, ("talloc failed\n"));
358                 errno = ENOMEM;
359                 return NULL;
360         }
361
362         pace = smb_add_ace4(pacl, &ace);
363         if (pace == NULL) {
364                 DEBUG(0, ("talloc failed\n"));
365                 TALLOC_FREE(pacl);
366                 errno = ENOMEM;
367                 return NULL;
368         }
369
370         return pacl;
371 }
372
373 /*
374  * Because there is no good way to guarantee that a new xattr will be
375  * created on file creation there might be no acl xattr on a file when
376  * trying to read the acl. In this case the acl xattr will get
377  * constructed at that time from the parent acl.
378  * If the parent ACL doesn't have an xattr either the call will
379  * recurse to the next parent directory until the share root is
380  * reached. If the share root doesn't contain an ACL xattr either a
381  * default ACL will be used.
382  * Also a default ACL will be set if a non inheriting ACL is encountered.
383  *
384  * Basic algorithm:
385  *   read acl xattr blob
386  *   if acl xattr blob doesn't exist
387  *     stat current directory to know if it's a file or directory
388  *     read acl xattr blob from parent dir
389  *     acl xattr blob to smb nfs4 acl
390  *     calculate inherited smb nfs4 acl
391  *     without inheritance use default smb nfs4 acl
392  *     smb nfs4 acl to acl xattr blob
393  *     set acl xattr blob
394  *     return smb nfs4 acl
395  *   else
396  *     acl xattr blob to smb nfs4 acl
397  *
398  * Todo: Really use mem_ctx after fixing interface of nfs4_acls
399  */
400 static SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
401         const char *path,
402         TALLOC_CTX *mem_ctx)
403 {
404         char *parent_dir = NULL;
405         SMB4ACL_T *pparentacl = NULL;
406         SMB4ACL_T *pchildacl = NULL;
407         SMB4ACE_T *pace;
408         SMB_ACE4PROP_T ace;
409         bool isdir;
410         struct smb_filename *smb_fname = NULL;
411         NTSTATUS status;
412         int ret;
413         TALLOC_CTX *frame = talloc_stackframe();
414
415         DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n", path));
416         smb_fname = synthetic_smb_fname(frame, path, NULL, NULL);
417         if (smb_fname == NULL) {
418                 TALLOC_FREE(frame);
419                 errno = ENOMEM;
420                 return NULL;
421         }
422
423         ret = SMB_VFS_STAT(handle->conn, smb_fname);
424         if (ret == -1) {
425                 DEBUG(0,("nfs4acls_inheritacl: failed to stat "
426                          "directory %s. Error was %s\n",
427                          smb_fname_str_dbg(smb_fname),
428                          strerror(errno)));
429                 TALLOC_FREE(frame);
430                 return NULL;
431         }
432         isdir = S_ISDIR(smb_fname->st.st_ex_mode);
433
434         if (!parent_dirname(talloc_tos(),
435                             path,
436                             &parent_dir,
437                             NULL)) {
438                 TALLOC_FREE(frame);
439                 errno = ENOMEM;
440                 return NULL;
441         }
442
443         status = nfs4_get_nfs4_acl(handle, frame, parent_dir, &pparentacl);
444         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)
445             && strncmp(parent_dir, ".", 2) != 0) {
446                 pparentacl = nfs4acls_inheritacl(handle, parent_dir,
447                                                  frame);
448         }
449         else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
450                 pparentacl = nfs4acls_defaultacl(frame);
451
452         }
453         else if (!NT_STATUS_IS_OK(status)) {
454                 TALLOC_FREE(frame);
455                 return NULL;
456         }
457
458         pchildacl = smb_create_smb4acl(mem_ctx);
459         if (pchildacl == NULL) {
460                 DEBUG(0, ("talloc failed\n"));
461                 TALLOC_FREE(frame);
462                 errno = ENOMEM;
463                 return NULL;
464         }
465
466         for (pace = smb_first_ace4(pparentacl); pace != NULL;
467              pace = smb_next_ace4(pace)) {
468                 SMB4ACE_T *pchildace;
469                 ace = *smb_get_ace4(pace);
470                 if (isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
471                     || !isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
472                         DEBUG(10, ("non inheriting ace type: %d, iflags: %x, "
473                                    "flags: %x, mask: %x, who: %d\n",
474                                    ace.aceType, ace.flags, ace.aceFlags,
475                                    ace.aceMask, ace.who.id));
476                         continue;
477                 }
478                 DEBUG(10, ("inheriting ace type: %d, iflags: %x, "
479                            "flags: %x, mask: %x, who: %d\n",
480                            ace.aceType, ace.flags, ace.aceFlags,
481                            ace.aceMask, ace.who.id));
482                 ace.aceFlags |= SMB_ACE4_INHERITED_ACE;
483                 if ((isdir && (ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
484                      || !isdir && (ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))
485                     && ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) {
486                         ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE;
487                 }
488                 if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) {
489                         ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE;
490                         ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE;
491                         ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE;
492                 }
493                 pchildace = smb_add_ace4(pchildacl, &ace);
494                 if (pchildace == NULL) {
495                         DEBUG(0, ("talloc failed\n"));
496                         TALLOC_FREE(frame);
497                         errno = ENOMEM;
498                         return NULL;
499                 }
500         }
501
502         /* Set a default ACL if we didn't inherit anything. */
503         if (smb_first_ace4(pchildacl) == NULL) {
504                 TALLOC_FREE(pchildacl);
505                 pchildacl = nfs4acls_defaultacl(mem_ctx);
506         }
507
508         /* store the returned ACL to get it directly in the
509            future and avoid dynamic inheritance behavior. */
510         nfs4acl_xattr_set_smb4acl(handle, path, pchildacl);
511
512         TALLOC_FREE(frame);
513         return pchildacl;
514 }
515
516 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
517                                    struct files_struct *fsp,
518                                    uint32 security_info,
519                                    TALLOC_CTX *mem_ctx,
520                                    struct security_descriptor **ppdesc)
521 {
522         SMB4ACL_T *pacl;
523         NTSTATUS status;
524         TALLOC_CTX *frame = talloc_stackframe();
525
526         status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
527         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
528                 pacl = nfs4acls_inheritacl(handle, fsp->fsp_name->base_name,
529                                            frame);
530         }
531         else if (!NT_STATUS_IS_OK(status)) {
532                 TALLOC_FREE(frame);
533                 return status;
534         }
535
536         status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
537         TALLOC_FREE(frame);
538         return status;
539 }
540
541 static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
542                                   const char *name, uint32 security_info,
543                                   TALLOC_CTX *mem_ctx,
544                                   struct security_descriptor **ppdesc)
545 {
546         SMB4ACL_T *pacl;
547         NTSTATUS status;
548         TALLOC_CTX *frame = talloc_stackframe();
549
550         status = nfs4_get_nfs4_acl(handle, frame, name, &pacl);
551         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
552                 pacl = nfs4acls_inheritacl(handle, name, frame);
553         }
554         else if (!NT_STATUS_IS_OK(status)) {
555                 TALLOC_FREE(frame);
556                 return status;
557         }
558
559         status = smb_get_nt_acl_nfs4(handle->conn, name, security_info,
560                                      mem_ctx, ppdesc,
561                                      pacl);
562         TALLOC_FREE(frame);
563         return status;
564 }
565
566 static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
567                          files_struct *fsp,
568                          uint32 security_info_sent,
569                          const struct security_descriptor *psd)
570 {
571         return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd);
572 }
573
574 /*
575    As long as Samba does not support an exiplicit method for a module
576    to define conflicting vfs methods, we should override all conflicting
577    methods here.  That way, we know we are using the NFSv4 storage
578
579    Function declarations taken from vfs_solarisacl
580 */
581
582 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
583                                                       const char *path_p,
584                                                       SMB_ACL_TYPE_T type,
585                                                       TALLOC_CTX *mem_ctx)
586 {
587         return (SMB_ACL_T)NULL;
588 }
589
590 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
591                                                     files_struct *fsp,
592                                                     TALLOC_CTX *mem_ctx)
593 {
594         return (SMB_ACL_T)NULL;
595 }
596
597 static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
598                                          const char *name,
599                                          SMB_ACL_TYPE_T type,
600                                          SMB_ACL_T theacl)
601 {
602         return -1;
603 }
604
605 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
606                                        files_struct *fsp,
607                                        SMB_ACL_T theacl)
608 {
609         return -1;
610 }
611
612 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
613                                                 const char *path)
614 {
615         return -1;
616 }
617
618 static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle, const char *path_p, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
619 {
620         return -1;
621 }
622
623 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)
624 {
625         return -1;
626 }
627
628 /* VFS operations structure */
629
630 static struct vfs_fn_pointers nfs4acl_xattr_fns = {
631         .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
632         .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
633         .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
634         .sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
635         .sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
636         .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
637         .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
638         .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
639         .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
640         .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
641 };
642
643 NTSTATUS vfs_nfs4acl_xattr_init(void);
644 NTSTATUS vfs_nfs4acl_xattr_init(void)
645 {
646         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
647                                 &nfs4acl_xattr_fns);
648 }