Hopefullt final fix for 6802 - acl_xattr.c module: A created folder does not properly...
[Samba/gbeck.git] / source3 / modules / vfs_acl_common.c
blob735660d4bdb784b7eb44f587d764bbcdd755650c
1 /*
2 * Store Windows ACLs in data store - common functions.
3 * #included into modules/vfs_acl_xattr.c and modules/vfs_acl_tdb.c
5 * Copyright (C) Volker Lendecke, 2008
6 * Copyright (C) Jeremy Allison, 2009
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
23 DATA_BLOB *pblob,
24 uint16_t hash_type,
25 uint8_t hash[XATTR_SD_HASH_SIZE]);
27 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
28 vfs_handle_struct *handle,
29 files_struct *fsp,
30 const char *name,
31 DATA_BLOB *pblob);
33 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
34 files_struct *fsp,
35 DATA_BLOB *pblob);
37 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
38 GROUP_SECURITY_INFORMATION | \
39 DACL_SECURITY_INFORMATION | \
40 SACL_SECURITY_INFORMATION)
42 /*******************************************************************
43 Hash a security descriptor.
44 *******************************************************************/
46 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
47 uint8_t *hash)
49 DATA_BLOB blob;
50 SHA256_CTX tctx;
51 NTSTATUS status;
53 memset(hash, '\0', XATTR_SD_HASH_SIZE);
54 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
55 if (!NT_STATUS_IS_OK(status)) {
56 return status;
59 SHA256_Init(&tctx);
60 SHA256_Update(&tctx, blob.data, blob.length);
61 SHA256_Final(hash, &tctx);
63 return NT_STATUS_OK;
66 /*******************************************************************
67 Parse out a struct security_descriptor from a DATA_BLOB.
68 *******************************************************************/
70 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
71 struct security_descriptor **ppdesc,
72 uint16_t *p_hash_type,
73 uint8_t hash[XATTR_SD_HASH_SIZE])
75 TALLOC_CTX *ctx = talloc_tos();
76 struct xattr_NTACL xacl;
77 enum ndr_err_code ndr_err;
78 size_t sd_size;
80 ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
81 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
83 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
84 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
85 ndr_errstr(ndr_err)));
86 return ndr_map_error2ntstatus(ndr_err);;
89 switch (xacl.version) {
90 case 2:
91 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
92 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
93 xacl.info.sd_hs2->sd->owner_sid,
94 xacl.info.sd_hs2->sd->group_sid,
95 xacl.info.sd_hs2->sd->sacl,
96 xacl.info.sd_hs2->sd->dacl,
97 &sd_size);
98 /* No hash - null out. */
99 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
100 memset(hash, '\0', XATTR_SD_HASH_SIZE);
101 break;
102 case 3:
103 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
104 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
105 xacl.info.sd_hs3->sd->owner_sid,
106 xacl.info.sd_hs3->sd->group_sid,
107 xacl.info.sd_hs3->sd->sacl,
108 xacl.info.sd_hs3->sd->dacl,
109 &sd_size);
110 *p_hash_type = xacl.info.sd_hs3->hash_type;
111 /* Current version 3. */
112 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
113 break;
114 default:
115 return NT_STATUS_REVISION_MISMATCH;
118 TALLOC_FREE(xacl.info.sd);
120 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
123 /*******************************************************************
124 Create a DATA_BLOB from a security descriptor.
125 *******************************************************************/
127 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
128 DATA_BLOB *pblob,
129 uint16_t hash_type,
130 uint8_t hash[XATTR_SD_HASH_SIZE])
132 struct xattr_NTACL xacl;
133 struct security_descriptor_hash_v3 sd_hs3;
134 enum ndr_err_code ndr_err;
135 TALLOC_CTX *ctx = talloc_tos();
137 ZERO_STRUCT(xacl);
138 ZERO_STRUCT(sd_hs3);
140 xacl.version = 3;
141 xacl.info.sd_hs3 = &sd_hs3;
142 xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
143 xacl.info.sd_hs3->hash_type = hash_type;
144 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
146 ndr_err = ndr_push_struct_blob(
147 pblob, ctx, NULL, &xacl,
148 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
150 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
151 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
152 ndr_errstr(ndr_err)));
153 return ndr_map_error2ntstatus(ndr_err);;
156 return NT_STATUS_OK;
159 /*******************************************************************
160 Pull a DATA_BLOB from an xattr given a pathname.
161 If the hash doesn't match, or doesn't exist - return the underlying
162 filesystem sd.
163 *******************************************************************/
165 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
166 files_struct *fsp,
167 const char *name,
168 uint32_t security_info,
169 struct security_descriptor **ppdesc)
171 DATA_BLOB blob;
172 NTSTATUS status;
173 uint16_t hash_type;
174 uint8_t hash[XATTR_SD_HASH_SIZE];
175 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
176 struct security_descriptor *psd = NULL;
177 struct security_descriptor *pdesc_next = NULL;
179 if (fsp && name == NULL) {
180 name = fsp->fsp_name->base_name;
183 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
185 /* Get the full underlying sd for the hash
186 or to return as backup. */
187 if (fsp) {
188 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
189 fsp,
190 HASH_SECURITY_INFO,
191 &pdesc_next);
192 } else {
193 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
194 name,
195 HASH_SECURITY_INFO,
196 &pdesc_next);
199 if (!NT_STATUS_IS_OK(status)) {
200 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
201 "returned %s\n",
202 name,
203 nt_errstr(status)));
204 return status;
207 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
208 if (!NT_STATUS_IS_OK(status)) {
209 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
210 nt_errstr(status)));
211 psd = pdesc_next;
212 goto out;
215 status = parse_acl_blob(&blob, &psd,
216 &hash_type, &hash[0]);
217 if (!NT_STATUS_IS_OK(status)) {
218 DEBUG(10, ("parse_acl_blob returned %s\n",
219 nt_errstr(status)));
220 psd = pdesc_next;
221 goto out;
224 /* Ensure the hash type is one we know. */
225 switch (hash_type) {
226 case XATTR_SD_HASH_TYPE_NONE:
227 /* No hash, just return blob sd. */
228 goto out;
229 case XATTR_SD_HASH_TYPE_SHA256:
230 break;
231 default:
232 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
233 "mismatch (%u) for file %s\n",
234 (unsigned int)hash_type,
235 name));
236 TALLOC_FREE(psd);
237 psd = pdesc_next;
238 goto out;
242 status = hash_sd_sha256(pdesc_next, hash_tmp);
243 if (!NT_STATUS_IS_OK(status)) {
244 TALLOC_FREE(psd);
245 psd = pdesc_next;
246 goto out;
249 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
250 /* Hash matches, return blob sd. */
251 goto out;
254 /* Hash doesn't match, return underlying sd. */
255 TALLOC_FREE(psd);
256 psd = pdesc_next;
258 out:
260 if (psd != pdesc_next) {
261 /* We're returning the blob, throw
262 * away the filesystem SD. */
263 TALLOC_FREE(pdesc_next);
266 if (!(security_info & OWNER_SECURITY_INFORMATION)) {
267 psd->owner_sid = NULL;
269 if (!(security_info & GROUP_SECURITY_INFORMATION)) {
270 psd->group_sid = NULL;
272 if (!(security_info & DACL_SECURITY_INFORMATION)) {
273 psd->dacl = NULL;
275 if (!(security_info & SACL_SECURITY_INFORMATION)) {
276 psd->sacl = NULL;
279 TALLOC_FREE(blob.data);
280 *ppdesc = psd;
281 return NT_STATUS_OK;
284 /*********************************************************************
285 Create a default ACL by inheriting from the parent. If no inheritance
286 from the parent available, don't set anything. This will leave the actual
287 permissions the new file or directory already got from the filesystem
288 as the NT ACL when read.
289 *********************************************************************/
291 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
292 files_struct *fsp,
293 struct security_descriptor *parent_desc,
294 bool is_directory)
296 TALLOC_CTX *ctx = talloc_tos();
297 NTSTATUS status = NT_STATUS_OK;
298 struct security_descriptor *psd = NULL;
299 size_t size;
301 if (!parent_desc || !sd_has_inheritable_components(parent_desc, is_directory)) {
302 return NT_STATUS_OK;
305 /* Create an inherited descriptor from the parent. */
307 if (DEBUGLEVEL >= 10) {
308 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
309 fsp_str_dbg(fsp) ));
310 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
313 status = se_create_child_secdesc(ctx,
314 &psd,
315 &size,
316 parent_desc,
317 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
318 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
319 is_directory);
320 if (!NT_STATUS_IS_OK(status)) {
321 return status;
324 if (DEBUGLEVEL >= 10) {
325 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
326 fsp_str_dbg(fsp) ));
327 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
330 return SMB_VFS_FSET_NT_ACL(fsp,
331 (OWNER_SECURITY_INFORMATION |
332 GROUP_SECURITY_INFORMATION |
333 DACL_SECURITY_INFORMATION),
334 psd);
337 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
338 const char *path,
339 uint32_t access_mask,
340 struct security_descriptor **pp_parent_desc)
342 char *parent_name = NULL;
343 struct security_descriptor *parent_desc = NULL;
344 uint32_t access_granted = 0;
345 NTSTATUS status;
347 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
348 return NT_STATUS_NO_MEMORY;
351 status = get_nt_acl_internal(handle,
352 NULL,
353 parent_name,
354 (OWNER_SECURITY_INFORMATION |
355 GROUP_SECURITY_INFORMATION |
356 DACL_SECURITY_INFORMATION),
357 &parent_desc);
359 if (!NT_STATUS_IS_OK(status)) {
360 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
361 "on directory %s for "
362 "path %s returned %s\n",
363 parent_name,
364 path,
365 nt_errstr(status) ));
366 return status;
368 status = smb1_file_se_access_check(parent_desc,
369 handle->conn->server_info->ptok,
370 access_mask,
371 &access_granted);
372 if(!NT_STATUS_IS_OK(status)) {
373 DEBUG(10,("check_parent_acl_common: access check "
374 "on directory %s for "
375 "path %s for mask 0x%x returned %s\n",
376 parent_name,
377 path,
378 access_mask,
379 nt_errstr(status) ));
380 return status;
382 if (pp_parent_desc) {
383 *pp_parent_desc = parent_desc;
385 return NT_STATUS_OK;
388 static void free_sd_common(void **ptr)
390 TALLOC_FREE(*ptr);
393 /*********************************************************************
394 Check ACL on open. For new files inherit from parent directory.
395 *********************************************************************/
397 static int open_acl_common(vfs_handle_struct *handle,
398 struct smb_filename *smb_fname,
399 files_struct *fsp,
400 int flags,
401 mode_t mode)
403 uint32_t access_granted = 0;
404 struct security_descriptor *pdesc = NULL;
405 struct security_descriptor *parent_desc = NULL;
406 bool file_existed = true;
407 char *fname = NULL;
408 NTSTATUS status;
410 if (fsp->base_fsp) {
411 /* Stream open. Base filename open already did the ACL check. */
412 DEBUG(10,("open_acl_common: stream open on %s\n",
413 fsp_str_dbg(fsp) ));
414 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
417 status = get_full_smb_filename(talloc_tos(), smb_fname,
418 &fname);
419 if (!NT_STATUS_IS_OK(status)) {
420 goto err;
423 status = get_nt_acl_internal(handle,
424 NULL,
425 fname,
426 (OWNER_SECURITY_INFORMATION |
427 GROUP_SECURITY_INFORMATION |
428 DACL_SECURITY_INFORMATION),
429 &pdesc);
430 if (NT_STATUS_IS_OK(status)) {
431 /* See if we can access it. */
432 status = smb1_file_se_access_check(pdesc,
433 handle->conn->server_info->ptok,
434 fsp->access_mask,
435 &access_granted);
436 if (!NT_STATUS_IS_OK(status)) {
437 DEBUG(10,("open_acl_xattr: %s open "
438 "refused with error %s\n",
439 fsp_str_dbg(fsp),
440 nt_errstr(status) ));
441 goto err;
443 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
444 file_existed = false;
446 * If O_CREAT is true then we're trying to create a file.
447 * Check the parent directory ACL will allow this.
449 if (flags & O_CREAT) {
450 struct security_descriptor *psd = NULL;
452 status = check_parent_acl_common(handle, fname,
453 SEC_DIR_ADD_FILE, &parent_desc);
454 if (!NT_STATUS_IS_OK(status)) {
455 goto err;
457 /* Cache the parent security descriptor for
458 * later use. We do have an fsp here, but to
459 * keep the code consistent with the directory
460 * case which doesn't, use the handle. */
462 /* Attach this to the conn, move from talloc_tos(). */
463 psd = (struct security_descriptor *)talloc_move(handle->conn,
464 &parent_desc);
466 if (!psd) {
467 status = NT_STATUS_NO_MEMORY;
468 goto err;
470 status = NT_STATUS_NO_MEMORY;
471 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
472 struct security_descriptor *, goto err);
473 status = NT_STATUS_OK;
477 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
478 "%s returned %s\n",
479 fsp_str_dbg(fsp),
480 nt_errstr(status) ));
482 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
483 return fsp->fh->fd;
485 err:
487 errno = map_errno_from_nt_status(status);
488 return -1;
491 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
493 int ret;
494 NTSTATUS status;
495 SMB_STRUCT_STAT sbuf;
497 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
498 if (ret == -1 && errno == ENOENT) {
499 struct security_descriptor *parent_desc = NULL;
500 struct security_descriptor *psd = NULL;
502 /* We're creating a new directory. */
503 status = check_parent_acl_common(handle, path,
504 SEC_DIR_ADD_SUBDIR, &parent_desc);
505 if (!NT_STATUS_IS_OK(status)) {
506 errno = map_errno_from_nt_status(status);
507 return -1;
510 /* Cache the parent security descriptor for
511 * later use. We don't have an fsp here so
512 * use the handle. */
514 /* Attach this to the conn, move from talloc_tos(). */
515 psd = (struct security_descriptor *)talloc_move(handle->conn,
516 &parent_desc);
518 if (!psd) {
519 return -1;
521 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
522 struct security_descriptor *, return -1);
525 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
528 /*********************************************************************
529 Fetch a security descriptor given an fsp.
530 *********************************************************************/
532 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
533 uint32_t security_info, struct security_descriptor **ppdesc)
535 return get_nt_acl_internal(handle, fsp,
536 NULL, security_info, ppdesc);
539 /*********************************************************************
540 Fetch a security descriptor given a pathname.
541 *********************************************************************/
543 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
544 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
546 return get_nt_acl_internal(handle, NULL,
547 name, security_info, ppdesc);
550 /*********************************************************************
551 Store a security descriptor given an fsp.
552 *********************************************************************/
554 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
555 uint32_t security_info_sent, const struct security_descriptor *psd)
557 NTSTATUS status;
558 DATA_BLOB blob;
559 struct security_descriptor *pdesc_next = NULL;
560 uint8_t hash[XATTR_SD_HASH_SIZE];
562 if (DEBUGLEVEL >= 10) {
563 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
564 fsp_str_dbg(fsp)));
565 NDR_PRINT_DEBUG(security_descriptor,
566 CONST_DISCARD(struct security_descriptor *,psd));
569 /* Ensure we have OWNER/GROUP/DACL set. */
571 if ((security_info_sent & (OWNER_SECURITY_INFORMATION|
572 GROUP_SECURITY_INFORMATION|
573 DACL_SECURITY_INFORMATION)) !=
574 (OWNER_SECURITY_INFORMATION|
575 GROUP_SECURITY_INFORMATION|
576 DACL_SECURITY_INFORMATION)) {
577 /* No we don't - read from the existing SD. */
578 struct security_descriptor *nc_psd = NULL;
580 status = get_nt_acl_internal(handle, fsp,
581 NULL,
582 (OWNER_SECURITY_INFORMATION|
583 GROUP_SECURITY_INFORMATION|
584 DACL_SECURITY_INFORMATION),
585 &nc_psd);
587 if (!NT_STATUS_IS_OK(status)) {
588 return status;
591 /* This is safe as nc_psd is discarded at fn exit. */
592 if (security_info_sent & OWNER_SECURITY_INFORMATION) {
593 nc_psd->owner_sid = psd->owner_sid;
595 security_info_sent |= OWNER_SECURITY_INFORMATION;
597 if (security_info_sent & GROUP_SECURITY_INFORMATION) {
598 nc_psd->group_sid = psd->group_sid;
600 security_info_sent |= GROUP_SECURITY_INFORMATION;
602 if (security_info_sent & DACL_SECURITY_INFORMATION) {
603 nc_psd->dacl = dup_sec_acl(talloc_tos(), psd->dacl);
604 if (nc_psd->dacl == NULL) {
605 return NT_STATUS_NO_MEMORY;
608 security_info_sent |= DACL_SECURITY_INFORMATION;
609 psd = nc_psd;
612 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
613 if (!NT_STATUS_IS_OK(status)) {
614 return status;
617 /* Get the full underlying sd, then hash. */
618 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
619 fsp,
620 HASH_SECURITY_INFO,
621 &pdesc_next);
623 if (!NT_STATUS_IS_OK(status)) {
624 return status;
627 status = hash_sd_sha256(pdesc_next, hash);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 if (DEBUGLEVEL >= 10) {
633 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
634 fsp_str_dbg(fsp)));
635 NDR_PRINT_DEBUG(security_descriptor,
636 CONST_DISCARD(struct security_descriptor *,psd));
638 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
639 store_acl_blob_fsp(handle, fsp, &blob);
641 return NT_STATUS_OK;
644 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
645 const char *fname, const char *mask, uint32 attr)
647 NTSTATUS status = check_parent_acl_common(handle, fname,
648 SEC_DIR_LIST, NULL);
650 if (!NT_STATUS_IS_OK(status)) {
651 errno = map_errno_from_nt_status(status);
652 return NULL;
654 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
657 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
658 struct smb_request *req,
659 uint16_t root_dir_fid,
660 struct smb_filename *smb_fname,
661 uint32_t access_mask,
662 uint32_t share_access,
663 uint32_t create_disposition,
664 uint32_t create_options,
665 uint32_t file_attributes,
666 uint32_t oplock_request,
667 uint64_t allocation_size,
668 struct security_descriptor *sd,
669 struct ea_list *ea_list,
670 files_struct **result,
671 int *pinfo)
673 NTSTATUS status, status1;
674 files_struct *fsp = NULL;
675 int info;
676 struct security_descriptor *parent_sd = NULL;
678 status = SMB_VFS_NEXT_CREATE_FILE(handle,
679 req,
680 root_dir_fid,
681 smb_fname,
682 access_mask,
683 share_access,
684 create_disposition,
685 create_options,
686 file_attributes,
687 oplock_request,
688 allocation_size,
690 ea_list,
691 result,
692 &info);
694 if (info != FILE_WAS_CREATED) {
695 /* File/directory was opened, not created. */
696 goto out;
699 fsp = *result;
701 if (!NT_STATUS_IS_OK(status) || fsp == NULL) {
702 /* Only handle success. */
703 goto out;
706 if (sd) {
707 /* Security descriptor already set. */
708 goto out;
711 if (fsp->base_fsp) {
712 /* Stream open. */
713 goto out;
717 /* We must have a cached parent sd in this case.
718 * attached to the handle. */
720 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
721 struct security_descriptor,
722 goto err);
724 /* New directory - inherit from parent. */
725 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
727 if (!NT_STATUS_IS_OK(status1)) {
728 DEBUG(1,("create_file_acl_common: error setting "
729 "sd for %s (%s)\n",
730 fsp_str_dbg(fsp),
731 nt_errstr(status1) ));
734 out:
736 /* Ensure we never leave attached data around. */
737 SMB_VFS_HANDLE_FREE_DATA(handle);
739 if (NT_STATUS_IS_OK(status) && pinfo) {
740 *pinfo = info;
742 return status;
744 err:
746 smb_panic("create_file_acl_common: logic error.\n");
747 /* NOTREACHED */
748 return status;