vfs: RIP SMB_VFS_SYS_ACL_SET_FILE()
[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  * Copyright (C) Ralph Boehme 2017
13  *
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.
18  *
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.
23  *
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/>.
26  *
27  */
28
29 #include "includes.h"
30 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "libcli/security/security_token.h"
33 #include "libcli/security/dom_sid.h"
34 #include "nfs4_acls.h"
35 #include "librpc/gen_ndr/ndr_nfs4acl.h"
36 #include "nfs4acl_xattr.h"
37 #include "nfs4acl_xattr_ndr.h"
38 #include "nfs4acl_xattr_xdr.h"
39 #include "nfs4acl_xattr_nfs.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_VFS
43
44 static const struct enum_list nfs4acl_encoding[] = {
45         {NFS4ACL_ENCODING_NDR, "ndr"},
46         {NFS4ACL_ENCODING_XDR, "xdr"},
47         {NFS4ACL_ENCODING_NFS, "nfs"},
48 };
49
50 /*
51  * Check if someone changed the POSIX mode, for files we expect 0666, for
52  * directories 0777. Discard the ACL blob if the mode is different.
53  */
54 static bool nfs4acl_validate_blob(vfs_handle_struct *handle,
55                                   const struct smb_filename *smb_fname)
56 {
57         struct nfs4acl_config *config = NULL;
58         mode_t expected_mode;
59         int ret;
60
61         SMB_VFS_HANDLE_GET_DATA(handle, config,
62                                 struct nfs4acl_config,
63                                 return false);
64
65         if (!config->validate_mode) {
66                 return true;
67         }
68
69         if (!VALID_STAT(smb_fname->st)) {
70                 /* might be a create */
71                 return true;
72         }
73
74         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
75                 expected_mode = 0777;
76         } else {
77                 expected_mode = 0666;
78         }
79         if ((smb_fname->st.st_ex_mode & expected_mode) == expected_mode) {
80                 return true;
81         }
82
83         ret = SMB_VFS_NEXT_REMOVEXATTR(handle,
84                                        smb_fname,
85                                        config->xattr_name);
86         if (ret != 0 && errno != ENOATTR) {
87                 DBG_ERR("Removing NFS4 xattr failed: %s\n", strerror(errno));
88                 return false;
89         }
90
91         return true;
92 }
93
94 static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
95                                  files_struct *fsp,
96                                  const struct smb_filename *smb_fname_in,
97                                  TALLOC_CTX *mem_ctx,
98                                  DATA_BLOB *blob)
99 {
100         struct nfs4acl_config *config = NULL;
101         const struct smb_filename *smb_fname = NULL;
102         size_t allocsize = 256;
103         ssize_t length;
104         bool ok;
105
106         SMB_VFS_HANDLE_GET_DATA(handle, config,
107                                 struct nfs4acl_config,
108                                 return NT_STATUS_INTERNAL_ERROR);
109
110         *blob = data_blob_null;
111
112         if (fsp == NULL && smb_fname_in == NULL) {
113                 return NT_STATUS_INTERNAL_ERROR;
114         }
115         smb_fname = smb_fname_in;
116         if (smb_fname == NULL) {
117                 smb_fname = fsp->fsp_name;
118         }
119         if (smb_fname == NULL) {
120                 return NT_STATUS_INTERNAL_ERROR;
121         }
122
123         ok = nfs4acl_validate_blob(handle, smb_fname);
124         if (!ok) {
125                 return NT_STATUS_INTERNAL_ERROR;
126         }
127
128         do {
129
130                 allocsize *= 4;
131                 ok = data_blob_realloc(mem_ctx, blob, allocsize);
132                 if (!ok) {
133                         return NT_STATUS_NO_MEMORY;
134                 }
135
136                 if (fsp != NULL && fsp_get_pathref_fd(fsp) != -1) {
137                         length = SMB_VFS_NEXT_FGETXATTR(handle,
138                                                         fsp,
139                                                         config->xattr_name,
140                                                         blob->data,
141                                                         blob->length);
142                 } else {
143                         length = SMB_VFS_NEXT_GETXATTR(handle,
144                                                        smb_fname,
145                                                        config->xattr_name,
146                                                        blob->data,
147                                                        blob->length);
148                 }
149         } while (length == -1 && errno == ERANGE && allocsize <= 65536);
150
151         if (length == -1) {
152                 return map_nt_error_from_unix(errno);
153         }
154
155         return NT_STATUS_OK;
156 }
157
158 static NTSTATUS nfs4acl_xattr_default_sd(
159         struct vfs_handle_struct *handle,
160         const struct smb_filename *smb_fname,
161         TALLOC_CTX *mem_ctx,
162         struct security_descriptor **sd)
163 {
164         struct nfs4acl_config *config = NULL;
165         enum default_acl_style default_acl_style;
166         mode_t required_mode;
167         SMB_STRUCT_STAT sbuf = smb_fname->st;
168         int ret;
169
170         SMB_VFS_HANDLE_GET_DATA(handle, config,
171                                 struct nfs4acl_config,
172                                 return NT_STATUS_INTERNAL_ERROR);
173
174         default_acl_style = config->default_acl_style;
175
176         if (!VALID_STAT(sbuf)) {
177                 ret = vfs_stat_smb_basename(handle->conn,
178                                             smb_fname,
179                                             &sbuf);
180                 if (ret != 0) {
181                         return map_nt_error_from_unix(errno);
182                 }
183         }
184
185         if (S_ISDIR(sbuf.st_ex_mode)) {
186                 required_mode = 0777;
187         } else {
188                 required_mode = 0666;
189         }
190         if ((sbuf.st_ex_mode & required_mode) != required_mode) {
191                 default_acl_style = DEFAULT_ACL_POSIX;
192         }
193
194         return make_default_filesystem_acl(mem_ctx,
195                                            default_acl_style,
196                                            smb_fname->base_name,
197                                            &sbuf,
198                                            sd);
199 }
200
201 static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle,
202                                      DATA_BLOB *blob,
203                                      TALLOC_CTX *mem_ctx,
204                                      struct SMB4ACL_T **smb4acl)
205 {
206         struct nfs4acl_config *config = NULL;
207         NTSTATUS status;
208
209         SMB_VFS_HANDLE_GET_DATA(handle, config,
210                                 struct nfs4acl_config,
211                                 return NT_STATUS_INTERNAL_ERROR);
212
213         switch (config->encoding) {
214         case NFS4ACL_ENCODING_NDR:
215                 status = nfs4acl_ndr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
216                 break;
217         case NFS4ACL_ENCODING_XDR:
218                 status = nfs4acl_xdr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
219                 break;
220         case NFS4ACL_ENCODING_NFS:
221                 status = nfs4acl_nfs_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
222                 break;
223         default:
224                 status = NT_STATUS_INTERNAL_ERROR;
225                 break;
226         }
227
228         return status;
229 }
230
231 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
232                                    struct files_struct *fsp,
233                                    uint32_t security_info,
234                                    TALLOC_CTX *mem_ctx,
235                                    struct security_descriptor **sd)
236 {
237         struct SMB4ACL_T *smb4acl = NULL;
238         TALLOC_CTX *frame = talloc_stackframe();
239         DATA_BLOB blob;
240         NTSTATUS status;
241
242         status = nfs4acl_get_blob(handle, fsp, NULL, frame, &blob);
243         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
244                 TALLOC_FREE(frame);
245                 return nfs4acl_xattr_default_sd(
246                         handle, fsp->fsp_name, mem_ctx, sd);
247         }
248         if (!NT_STATUS_IS_OK(status)) {
249                 TALLOC_FREE(frame);
250                 return status;
251         }
252
253         status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl);
254         if (!NT_STATUS_IS_OK(status)) {
255                 TALLOC_FREE(frame);
256                 return status;
257         }
258
259         status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx,
260                                       sd, smb4acl);
261         TALLOC_FREE(frame);
262         return status;
263 }
264
265 static NTSTATUS nfs4acl_xattr_get_nt_acl_at(struct vfs_handle_struct *handle,
266                                 struct files_struct *dirfsp,
267                                 const struct smb_filename *smb_fname,
268                                 uint32_t security_info,
269                                 TALLOC_CTX *mem_ctx,
270                                 struct security_descriptor **sd)
271 {
272         struct SMB4ACL_T *smb4acl = NULL;
273         TALLOC_CTX *frame = talloc_stackframe();
274         DATA_BLOB blob;
275         NTSTATUS status;
276
277         SMB_ASSERT(dirfsp == handle->conn->cwd_fsp);
278
279         status = nfs4acl_get_blob(handle, NULL, smb_fname, frame, &blob);
280         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
281                 TALLOC_FREE(frame);
282                 return nfs4acl_xattr_default_sd(
283                         handle, smb_fname, mem_ctx, sd);
284         }
285         if (!NT_STATUS_IS_OK(status)) {
286                 TALLOC_FREE(frame);
287                 return status;
288         }
289
290         status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl);
291         if (!NT_STATUS_IS_OK(status)) {
292                 TALLOC_FREE(frame);
293                 return status;
294         }
295
296         status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, NULL,
297                                      security_info, mem_ctx, sd,
298                                      smb4acl);
299         TALLOC_FREE(frame);
300         return status;
301 }
302
303 static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle,
304                                    files_struct *fsp,
305                                    struct SMB4ACL_T *smb4acl)
306 {
307         struct nfs4acl_config *config = NULL;
308         DATA_BLOB blob;
309         NTSTATUS status;
310         int saved_errno = 0;
311         int ret;
312
313         SMB_VFS_HANDLE_GET_DATA(handle, config,
314                                 struct nfs4acl_config,
315                                 return false);
316
317         switch (config->encoding) {
318         case NFS4ACL_ENCODING_NDR:
319                 status = nfs4acl_smb4acl_to_ndr_blob(handle, talloc_tos(),
320                                                      smb4acl, &blob);
321                 break;
322         case NFS4ACL_ENCODING_XDR:
323                 status = nfs4acl_smb4acl_to_xdr_blob(handle, talloc_tos(),
324                                                      smb4acl, &blob);
325                 break;
326         case NFS4ACL_ENCODING_NFS:
327                 status = nfs4acl_smb4acl_to_nfs_blob(handle, talloc_tos(),
328                                                      smb4acl, &blob);
329                 break;
330         default:
331                 status = NT_STATUS_INTERNAL_ERROR;
332                 break;
333         }
334         if (!NT_STATUS_IS_OK(status)) {
335                 return false;
336         }
337
338         if (fsp_get_pathref_fd(fsp) != -1) {
339                 ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name,
340                                              blob.data, blob.length, 0);
341         } else {
342                 ret = SMB_VFS_NEXT_SETXATTR(handle, fsp->fsp_name,
343                                             config->xattr_name,
344                                             blob.data, blob.length, 0);
345         }
346         if (ret != 0) {
347                 saved_errno = errno;
348         }
349         data_blob_free(&blob);
350         if (saved_errno != 0) {
351                 errno = saved_errno;
352         }
353         if (ret != 0) {
354                 DBG_ERR("can't store acl in xattr: %s\n", strerror(errno));
355                 return false;
356         }
357
358         return true;
359 }
360
361 static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
362                          files_struct *fsp,
363                          uint32_t security_info_sent,
364                          const struct security_descriptor *psd)
365 {
366         struct nfs4acl_config *config = NULL;
367         const struct security_token *token = NULL;
368         mode_t existing_mode;
369         mode_t expected_mode;
370         mode_t restored_mode;
371         bool chown_needed = false;
372         struct dom_sid_buf buf;
373         NTSTATUS status;
374         int ret;
375
376         SMB_VFS_HANDLE_GET_DATA(handle, config,
377                                 struct nfs4acl_config,
378                                 return NT_STATUS_INTERNAL_ERROR);
379
380         if (!VALID_STAT(fsp->fsp_name->st)) {
381                 DBG_ERR("Invalid stat info on [%s]\n", fsp_str_dbg(fsp));
382                 return NT_STATUS_INTERNAL_ERROR;
383         }
384
385         existing_mode = fsp->fsp_name->st.st_ex_mode;
386         if (S_ISDIR(existing_mode)) {
387                 expected_mode = 0777;
388         } else {
389                 expected_mode = 0666;
390         }
391         if (!config->validate_mode) {
392                 existing_mode = 0;
393                 expected_mode = 0;
394         }
395         if ((existing_mode & expected_mode) != expected_mode) {
396
397                 restored_mode = existing_mode | expected_mode;
398
399                 if (fsp_get_io_fd(fsp) != -1) {
400                         ret = SMB_VFS_NEXT_FCHMOD(handle,
401                                                   fsp,
402                                                   restored_mode);
403                 } else {
404                         ret = SMB_VFS_NEXT_CHMOD(handle,
405                                                  fsp->fsp_name,
406                                                  restored_mode);
407                 }
408                 if (ret != 0) {
409                         DBG_ERR("Resetting POSIX mode on [%s] from [0%o]: %s\n",
410                                 fsp_str_dbg(fsp), existing_mode,
411                                 strerror(errno));
412                         return map_nt_error_from_unix(errno);
413                 }
414         }
415
416         status = smb_set_nt_acl_nfs4(handle,
417                                      fsp,
418                                      &config->nfs4_params,
419                                      security_info_sent,
420                                      psd,
421                                      nfs4acl_smb4acl_set_fn);
422         if (NT_STATUS_IS_OK(status)) {
423                 return NT_STATUS_OK;
424         }
425         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
426                 return status;
427         }
428
429         /*
430          * We got access denied. If we're already root, or we didn't
431          * need to do a chown, or the fsp isn't open with WRITE_OWNER
432          * access, just return.
433          */
434
435         if ((security_info_sent & SECINFO_OWNER) &&
436             (psd->owner_sid != NULL))
437         {
438                 chown_needed = true;
439         }
440         if ((security_info_sent & SECINFO_GROUP) &&
441             (psd->group_sid != NULL))
442         {
443                 chown_needed = true;
444         }
445
446         if (get_current_uid(handle->conn) == 0 ||
447             chown_needed == false ||
448             !(fsp->access_mask & SEC_STD_WRITE_OWNER))
449         {
450                 return NT_STATUS_ACCESS_DENIED;
451         }
452
453         /*
454          * Only allow take-ownership, not give-ownership. That's the way Windows
455          * implements SEC_STD_WRITE_OWNER. MS-FSA 2.1.5.16 just states: If
456          * InputBuffer.OwnerSid is not a valid owner SID for a file in the
457          * objectstore, as determined in an implementation specific manner, the
458          * object store MUST return STATUS_INVALID_OWNER.
459          */
460         token = get_current_nttok(fsp->conn);
461         if (!security_token_is_sid(token, psd->owner_sid)) {
462                 return NT_STATUS_INVALID_OWNER;
463         }
464
465         DBG_DEBUG("overriding chown on file %s for sid %s\n",
466                   fsp_str_dbg(fsp),
467                   dom_sid_str_buf(psd->owner_sid, &buf));
468
469         status = smb_set_nt_acl_nfs4(handle,
470                                      fsp,
471                                      &config->nfs4_params,
472                                      security_info_sent,
473                                      psd,
474                                      nfs4acl_smb4acl_set_fn);
475         return status;
476 }
477
478 static int nfs4acl_connect(struct vfs_handle_struct *handle,
479                            const char *service,
480                            const char *user)
481 {
482         const struct loadparm_substitution *lp_sub =
483                 loadparm_s3_global_substitution();
484         struct nfs4acl_config *config = NULL;
485         const struct enum_list *default_acl_style_list = NULL;
486         const char *default_xattr_name = NULL;
487         bool default_validate_mode = true;
488         int enumval;
489         unsigned nfs_version;
490         int ret;
491
492         default_acl_style_list = get_default_acl_style_list();
493
494         config = talloc_zero(handle->conn, struct nfs4acl_config);
495         if (config == NULL) {
496                 DBG_ERR("talloc_zero() failed\n");
497                 return -1;
498         }
499
500         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
501         if (ret < 0) {
502                 TALLOC_FREE(config);
503                 return ret;
504         }
505
506         ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params);
507         if (ret < 0) {
508                 TALLOC_FREE(config);
509                 return ret;
510         }
511
512         enumval = lp_parm_enum(SNUM(handle->conn),
513                                "nfs4acl_xattr",
514                                "encoding",
515                                nfs4acl_encoding,
516                                NFS4ACL_ENCODING_NDR);
517         if (enumval == -1) {
518                 DBG_ERR("Invalid \"nfs4acl_xattr:encoding\" parameter\n");
519                 return -1;
520         }
521         config->encoding = (enum nfs4acl_encoding)enumval;
522
523         switch (config->encoding) {
524         case NFS4ACL_ENCODING_XDR:
525                 default_xattr_name = NFS4ACL_XDR_XATTR_NAME;
526                 break;
527         case NFS4ACL_ENCODING_NFS:
528                 default_xattr_name = NFS4ACL_NFS_XATTR_NAME;
529                 default_validate_mode = false;
530                 break;
531         case NFS4ACL_ENCODING_NDR:
532         default:
533                 default_xattr_name = NFS4ACL_NDR_XATTR_NAME;
534                 break;
535         }
536
537         nfs_version = (unsigned)lp_parm_int(SNUM(handle->conn),
538                                             "nfs4acl_xattr",
539                                             "version",
540                                             41);
541         switch (nfs_version) {
542         case 40:
543                 config->nfs_version = ACL4_XATTR_VERSION_40;
544                 break;
545         case 41:
546                 config->nfs_version = ACL4_XATTR_VERSION_41;
547                 break;
548         default:
549                 config->nfs_version = ACL4_XATTR_VERSION_DEFAULT;
550                 break;
551         }
552
553         config->default_acl_style = lp_parm_enum(SNUM(handle->conn),
554                                                  "nfs4acl_xattr",
555                                                  "default acl style",
556                                                  default_acl_style_list,
557                                                  DEFAULT_ACL_EVERYONE);
558
559         config->xattr_name = lp_parm_substituted_string(config, lp_sub,
560                                                    SNUM(handle->conn),
561                                                    "nfs4acl_xattr",
562                                                    "xattr_name",
563                                                    default_xattr_name);
564
565         config->nfs4_id_numeric = lp_parm_bool(SNUM(handle->conn),
566                                                "nfs4acl_xattr",
567                                                "nfs4_id_numeric",
568                                                false);
569
570
571         config->validate_mode = lp_parm_bool(SNUM(handle->conn),
572                                              "nfs4acl_xattr",
573                                              "validate_mode",
574                                              default_validate_mode);
575
576         SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config,
577                                 return -1);
578
579         /*
580          * Ensure we have the parameters correct if we're using this module.
581          */
582         DBG_NOTICE("Setting 'inherit acls = true', "
583                    "'dos filemode = true', "
584                    "'force unknown acl user = true', "
585                    "'create mask = 0666', "
586                    "'directory mask = 0777' and "
587                    "'store dos attributes = yes' "
588                    "for service [%s]\n", service);
589
590         lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
591         lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
592         lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
593         lp_do_parameter(SNUM(handle->conn), "create mask", "0666");
594         lp_do_parameter(SNUM(handle->conn), "directory mask", "0777");
595         lp_do_parameter(SNUM(handle->conn), "store dos attributes", "yes");
596
597         return 0;
598 }
599
600 /*
601    As long as Samba does not support an exiplicit method for a module
602    to define conflicting vfs methods, we should override all conflicting
603    methods here.  That way, we know we are using the NFSv4 storage
604
605    Function declarations taken from vfs_solarisacl
606 */
607
608 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
609                                         const struct smb_filename *smb_fname,
610                                         SMB_ACL_TYPE_T type,
611                                         TALLOC_CTX *mem_ctx)
612 {
613         return (SMB_ACL_T)NULL;
614 }
615
616 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
617                                                     files_struct *fsp,
618                                                     TALLOC_CTX *mem_ctx)
619 {
620         return (SMB_ACL_T)NULL;
621 }
622
623 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
624                                        files_struct *fsp,
625                                        SMB_ACL_TYPE_T type,
626                                        SMB_ACL_T theacl)
627 {
628         return -1;
629 }
630
631 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
632                         const struct smb_filename *smb_fname)
633 {
634         return -1;
635 }
636
637 static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle,
638                         const struct smb_filename *smb_fname,
639                         TALLOC_CTX *mem_ctx,
640                         char **blob_description,
641                         DATA_BLOB *blob)
642 {
643         return -1;
644 }
645
646 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)
647 {
648         return -1;
649 }
650
651 /* VFS operations structure */
652
653 static struct vfs_fn_pointers nfs4acl_xattr_fns = {
654         .connect_fn = nfs4acl_connect,
655         .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
656         .get_nt_acl_at_fn = nfs4acl_xattr_get_nt_acl_at,
657         .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
658
659         .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
660         .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
661         .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
662         .sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
663         .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
664         .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
665 };
666
667 static_decl_vfs;
668 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *ctx)
669 {
670         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
671                                 &nfs4acl_xattr_fns);
672 }