s3:passdb: ENCTYPE_DES_CBC_MD5 is not longer used in secrets_domain_info_kerberos_keys()
[Samba.git] / source3 / modules / vfs_nfs4acl_xattr.c
blob1fd3519ca020c889828dfb4edf2d53d461101651
1 /*
2 * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
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
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
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.
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.
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/>.
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"
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_VFS
44 static const struct enum_list nfs4acl_encoding[] = {
45 {NFS4ACL_ENCODING_NDR, "ndr"},
46 {NFS4ACL_ENCODING_XDR, "xdr"},
47 {NFS4ACL_ENCODING_NFS, "nfs"},
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.
54 static bool nfs4acl_validate_blob(vfs_handle_struct *handle,
55 files_struct *fsp)
57 struct nfs4acl_config *config = NULL;
58 mode_t expected_mode;
59 int ret;
61 SMB_VFS_HANDLE_GET_DATA(handle, config,
62 struct nfs4acl_config,
63 return false);
65 if (!config->validate_mode) {
66 return true;
69 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
70 expected_mode = 0777;
71 } else {
72 expected_mode = 0666;
74 if ((fsp->fsp_name->st.st_ex_mode & expected_mode) == expected_mode) {
75 return true;
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;
86 return true;
89 static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
90 files_struct *fsp,
91 TALLOC_CTX *mem_ctx,
92 DATA_BLOB *blob)
94 struct nfs4acl_config *config = NULL;
95 size_t allocsize = 256;
96 ssize_t length;
97 bool ok;
99 SMB_VFS_HANDLE_GET_DATA(handle, config,
100 struct nfs4acl_config,
101 return NT_STATUS_INTERNAL_ERROR);
103 *blob = data_blob_null;
105 ok = nfs4acl_validate_blob(handle, fsp);
106 if (!ok) {
107 return NT_STATUS_INTERNAL_ERROR;
110 do {
112 allocsize *= 4;
113 ok = data_blob_realloc(mem_ctx, blob, allocsize);
114 if (!ok) {
115 return NT_STATUS_NO_MEMORY;
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);
125 if (length == -1) {
126 return map_nt_error_from_unix(errno);
129 return NT_STATUS_OK;
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)
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;
144 SMB_VFS_HANDLE_GET_DATA(handle, config,
145 struct nfs4acl_config,
146 return NT_STATUS_INTERNAL_ERROR);
148 default_acl_style = config->default_acl_style;
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);
159 if (S_ISDIR(sbuf.st_ex_mode)) {
160 required_mode = 0777;
161 } else {
162 required_mode = 0666;
164 if ((sbuf.st_ex_mode & required_mode) != required_mode) {
165 default_acl_style = DEFAULT_ACL_POSIX;
168 return make_default_filesystem_acl(mem_ctx,
169 default_acl_style,
170 smb_fname->base_name,
171 &sbuf,
172 sd);
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)
180 struct nfs4acl_config *config = NULL;
181 NTSTATUS status;
183 SMB_VFS_HANDLE_GET_DATA(handle, config,
184 struct nfs4acl_config,
185 return NT_STATUS_INTERNAL_ERROR);
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;
202 return status;
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)
211 struct SMB4ACL_T *smb4acl = NULL;
212 TALLOC_CTX *frame = talloc_stackframe();
213 DATA_BLOB blob;
214 NTSTATUS status;
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);
222 if (!NT_STATUS_IS_OK(status)) {
223 TALLOC_FREE(frame);
224 return status;
227 status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl);
228 if (!NT_STATUS_IS_OK(status)) {
229 TALLOC_FREE(frame);
230 return status;
233 status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx,
234 sd, smb4acl);
235 TALLOC_FREE(frame);
236 return status;
239 static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle,
240 files_struct *fsp,
241 struct SMB4ACL_T *smb4acl)
243 struct nfs4acl_config *config = NULL;
244 DATA_BLOB blob;
245 NTSTATUS status;
246 int saved_errno = 0;
247 int ret;
249 SMB_VFS_HANDLE_GET_DATA(handle, config,
250 struct nfs4acl_config,
251 return false);
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;
270 if (!NT_STATUS_IS_OK(status)) {
271 return false;
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;
279 data_blob_free(&blob);
280 if (saved_errno != 0) {
281 errno = saved_errno;
283 if (ret != 0) {
284 DBG_ERR("can't store acl in xattr: %s\n", strerror(errno));
285 return false;
288 return true;
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)
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;
306 SMB_VFS_HANDLE_GET_DATA(handle, config,
307 struct nfs4acl_config,
308 return NT_STATUS_INTERNAL_ERROR);
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;
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;
321 if (!config->validate_mode) {
322 existing_mode = 0;
323 expected_mode = 0;
325 if ((existing_mode & expected_mode) != expected_mode) {
327 restored_mode = existing_mode | expected_mode;
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);
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;
349 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
350 return status;
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.
359 if ((security_info_sent & SECINFO_OWNER) &&
360 (psd->owner_sid != NULL))
362 chown_needed = true;
364 if ((security_info_sent & SECINFO_GROUP) &&
365 (psd->group_sid != NULL))
367 chown_needed = true;
370 if (get_current_uid(handle->conn) == 0 ||
371 chown_needed == false)
373 return NT_STATUS_ACCESS_DENIED;
375 status = check_any_access_fsp(fsp, SEC_STD_WRITE_OWNER);
376 if (!NT_STATUS_IS_OK(status)) {
377 return status;
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.
387 token = get_current_nttok(fsp->conn);
388 if (!security_token_is_sid(token, psd->owner_sid)) {
389 return NT_STATUS_INVALID_OWNER;
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));
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;
405 static int nfs4acl_connect(struct vfs_handle_struct *handle,
406 const char *service,
407 const char *user)
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;
419 default_acl_style_list = get_default_acl_style_list();
421 config = talloc_zero(handle->conn, struct nfs4acl_config);
422 if (config == NULL) {
423 DBG_ERR("talloc_zero() failed\n");
424 return -1;
427 ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
428 if (ret < 0) {
429 TALLOC_FREE(config);
430 return ret;
433 ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params);
434 if (ret < 0) {
435 TALLOC_FREE(config);
436 return ret;
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;
448 config->encoding = (enum nfs4acl_encoding)enumval;
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;
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;
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);
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);
492 config->nfs4_id_numeric = lp_parm_bool(SNUM(handle->conn),
493 "nfs4acl_xattr",
494 "nfs4_id_numeric",
495 false);
498 config->validate_mode = lp_parm_bool(SNUM(handle->conn),
499 "nfs4acl_xattr",
500 "validate_mode",
501 default_validate_mode);
503 SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config,
504 return -1);
507 * Ensure we have the parameters correct if we're using this module.
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);
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");
524 return 0;
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
532 Function declarations taken from vfs_solarisacl
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)
540 return (SMB_ACL_T)NULL;
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)
548 return -1;
551 static int nfs4acl_xattr_fail__sys_acl_delete_def_fd(vfs_handle_struct *handle,
552 files_struct *fsp)
554 return -1;
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)
559 return -1;
562 /* VFS operations structure */
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,
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,
575 static_decl_vfs;
576 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *ctx)
578 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
579 &nfs4acl_xattr_fns);