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