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