Hopefullt final fix for 6802 - acl_xattr.c module: A created folder does not properly...
[idra/samba.git] / source3 / modules / vfs_acl_common.c
1 /*
2  * Store Windows ACLs in data store - common functions.
3  * #included into modules/vfs_acl_xattr.c and modules/vfs_acl_tdb.c
4  *
5  * Copyright (C) Volker Lendecke, 2008
6  * Copyright (C) Jeremy Allison, 2009
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
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]);
26
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);
32
33 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
34                         files_struct *fsp,
35                         DATA_BLOB *pblob);
36
37 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
38                                 GROUP_SECURITY_INFORMATION | \
39                                 DACL_SECURITY_INFORMATION | \
40                                 SACL_SECURITY_INFORMATION)
41
42 /*******************************************************************
43  Hash a security descriptor.
44 *******************************************************************/
45
46 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
47                         uint8_t *hash)
48 {
49         DATA_BLOB blob;
50         SHA256_CTX tctx;
51         NTSTATUS status;
52
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;
57         }
58
59         SHA256_Init(&tctx);
60         SHA256_Update(&tctx, blob.data, blob.length);
61         SHA256_Final(hash, &tctx);
62
63         return NT_STATUS_OK;
64 }
65
66 /*******************************************************************
67  Parse out a struct security_descriptor from a DATA_BLOB.
68 *******************************************************************/
69
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])
74 {
75         TALLOC_CTX *ctx = talloc_tos();
76         struct xattr_NTACL xacl;
77         enum ndr_err_code ndr_err;
78         size_t sd_size;
79
80         ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
81                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
82
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);;
87         }
88
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;
116         }
117
118         TALLOC_FREE(xacl.info.sd);
119
120         return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
121 }
122
123 /*******************************************************************
124  Create a DATA_BLOB from a security descriptor.
125 *******************************************************************/
126
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])
131 {
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();
136
137         ZERO_STRUCT(xacl);
138         ZERO_STRUCT(sd_hs3);
139
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);
145
146         ndr_err = ndr_push_struct_blob(
147                         pblob, ctx, NULL, &xacl,
148                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
149
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);;
154         }
155
156         return NT_STATUS_OK;
157 }
158
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 *******************************************************************/
164
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)
170 {
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;
178
179         if (fsp && name == NULL) {
180                 name = fsp->fsp_name->base_name;
181         }
182
183         DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
184
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);
197         }
198
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;
205         }
206
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;
213         }
214
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;
222         }
223
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;
239         }
240
241
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;
247         }
248
249         if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
250                 /* Hash matches, return blob sd. */
251                 goto out;
252         }
253
254         /* Hash doesn't match, return underlying sd. */
255         TALLOC_FREE(psd);
256         psd = pdesc_next;
257
258   out:
259
260         if (psd != pdesc_next) {
261                 /* We're returning the blob, throw
262                  * away the filesystem SD. */
263                 TALLOC_FREE(pdesc_next);
264         }
265
266         if (!(security_info & OWNER_SECURITY_INFORMATION)) {
267                 psd->owner_sid = NULL;
268         }
269         if (!(security_info & GROUP_SECURITY_INFORMATION)) {
270                 psd->group_sid = NULL;
271         }
272         if (!(security_info & DACL_SECURITY_INFORMATION)) {
273                 psd->dacl = NULL;
274         }
275         if (!(security_info & SACL_SECURITY_INFORMATION)) {
276                 psd->sacl = NULL;
277         }
278
279         TALLOC_FREE(blob.data);
280         *ppdesc = psd;
281         return NT_STATUS_OK;
282 }
283
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 *********************************************************************/
290
291 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
292                                         files_struct *fsp,
293                                         struct security_descriptor *parent_desc,
294                                         bool is_directory)
295 {
296         TALLOC_CTX *ctx = talloc_tos();
297         NTSTATUS status = NT_STATUS_OK;
298         struct security_descriptor *psd = NULL;
299         size_t size;
300
301         if (!parent_desc || !sd_has_inheritable_components(parent_desc, is_directory)) {
302                 return NT_STATUS_OK;
303         }
304
305         /* Create an inherited descriptor from the parent. */
306
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);
311         }
312
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;
322         }
323
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);
328         }
329
330         return SMB_VFS_FSET_NT_ACL(fsp,
331                                 (OWNER_SECURITY_INFORMATION |
332                                  GROUP_SECURITY_INFORMATION |
333                                  DACL_SECURITY_INFORMATION),
334                                 psd);
335 }
336
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)
341 {
342         char *parent_name = NULL;
343         struct security_descriptor *parent_desc = NULL;
344         uint32_t access_granted = 0;
345         NTSTATUS status;
346
347         if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
348                 return NT_STATUS_NO_MEMORY;
349         }
350
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);
358
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;
367         }
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;
381         }
382         if (pp_parent_desc) {
383                 *pp_parent_desc = parent_desc;
384         }
385         return NT_STATUS_OK;
386 }
387
388 static void free_sd_common(void **ptr)
389 {
390         TALLOC_FREE(*ptr);
391 }
392
393 /*********************************************************************
394  Check ACL on open. For new files inherit from parent directory.
395 *********************************************************************/
396
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)
402 {
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;
409
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);
415         }
416
417         status = get_full_smb_filename(talloc_tos(), smb_fname,
418                                        &fname);
419         if (!NT_STATUS_IS_OK(status)) {
420                 goto err;
421         }
422
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;
442                 }
443         } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
444                 file_existed = false;
445                 /*
446                  * If O_CREAT is true then we're trying to create a file.
447                  * Check the parent directory ACL will allow this.
448                  */
449                 if (flags & O_CREAT) {
450                         struct security_descriptor *psd = NULL;
451
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;
456                         }
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. */
461
462                         /* Attach this to the conn, move from talloc_tos(). */
463                         psd = (struct security_descriptor *)talloc_move(handle->conn,
464                                 &parent_desc);
465
466                         if (!psd) {
467                                 status = NT_STATUS_NO_MEMORY;
468                                 goto err;
469                         }
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;
474                 }
475         }
476
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) ));
481
482         fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
483         return fsp->fh->fd;
484
485   err:
486
487         errno = map_errno_from_nt_status(status);
488         return -1;
489 }
490
491 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
492 {
493         int ret;
494         NTSTATUS status;
495         SMB_STRUCT_STAT sbuf;
496
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;
501
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;
508                 }
509
510                 /* Cache the parent security descriptor for
511                  * later use. We don't have an fsp here so
512                  * use the handle. */
513
514                 /* Attach this to the conn, move from talloc_tos(). */
515                 psd = (struct security_descriptor *)talloc_move(handle->conn,
516                                 &parent_desc);
517
518                 if (!psd) {
519                         return -1;
520                 }
521                 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
522                         struct security_descriptor *, return -1);
523         }
524
525         return SMB_VFS_NEXT_MKDIR(handle, path, mode);
526 }
527
528 /*********************************************************************
529  Fetch a security descriptor given an fsp.
530 *********************************************************************/
531
532 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
533         uint32_t security_info, struct security_descriptor **ppdesc)
534 {
535         return get_nt_acl_internal(handle, fsp,
536                                 NULL, security_info, ppdesc);
537 }
538
539 /*********************************************************************
540  Fetch a security descriptor given a pathname.
541 *********************************************************************/
542
543 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
544         const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
545 {
546         return get_nt_acl_internal(handle, NULL,
547                                 name, security_info, ppdesc);
548 }
549
550 /*********************************************************************
551  Store a security descriptor given an fsp.
552 *********************************************************************/
553
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)
556 {
557         NTSTATUS status;
558         DATA_BLOB blob;
559         struct security_descriptor *pdesc_next = NULL;
560         uint8_t hash[XATTR_SD_HASH_SIZE];
561
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));
567         }
568
569         /* Ensure we have OWNER/GROUP/DACL set. */
570
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;
579
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);
586
587                 if (!NT_STATUS_IS_OK(status)) {
588                         return status;
589                 }
590
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;
594                 }
595                 security_info_sent |= OWNER_SECURITY_INFORMATION;
596
597                 if (security_info_sent & GROUP_SECURITY_INFORMATION) {
598                         nc_psd->group_sid = psd->group_sid;
599                 }
600                 security_info_sent |= GROUP_SECURITY_INFORMATION;
601
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;
606                         }
607                 }
608                 security_info_sent |= DACL_SECURITY_INFORMATION;
609                 psd = nc_psd;
610         }
611
612         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
613         if (!NT_STATUS_IS_OK(status)) {
614                 return status;
615         }
616
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);
622
623         if (!NT_STATUS_IS_OK(status)) {
624                 return status;
625         }
626
627         status = hash_sd_sha256(pdesc_next, hash);
628         if (!NT_STATUS_IS_OK(status)) {
629                 return status;
630         }
631
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));
637         }
638         create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
639         store_acl_blob_fsp(handle, fsp, &blob);
640
641         return NT_STATUS_OK;
642 }
643
644 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
645                         const char *fname, const char *mask, uint32 attr)
646 {
647         NTSTATUS status = check_parent_acl_common(handle, fname,
648                                         SEC_DIR_LIST, NULL);
649
650         if (!NT_STATUS_IS_OK(status)) {
651                 errno = map_errno_from_nt_status(status);
652                 return NULL;
653         }
654         return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
655 }
656
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)
672 {
673         NTSTATUS status, status1;
674         files_struct *fsp = NULL;
675         int info;
676         struct security_descriptor *parent_sd = NULL;
677
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,
689                                         sd,
690                                         ea_list,
691                                         result,
692                                         &info);
693
694         if (info != FILE_WAS_CREATED) {
695                 /* File/directory was opened, not created. */
696                 goto out;
697         }
698
699         fsp = *result;
700
701         if (!NT_STATUS_IS_OK(status) || fsp == NULL) {
702                 /* Only handle success. */
703                 goto out;
704         }
705
706         if (sd) {
707                 /* Security descriptor already set. */
708                 goto out;
709         }
710
711         if (fsp->base_fsp) {
712                 /* Stream open. */
713                 goto out;
714         }
715
716
717         /* We must have a cached parent sd in this case.
718          * attached to the handle. */
719
720         SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
721                 struct security_descriptor,
722                 goto err);
723
724         /* New directory - inherit from parent. */
725         status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
726
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) ));
732         }
733
734   out:
735
736         /* Ensure we never leave attached data around. */
737         SMB_VFS_HANDLE_FREE_DATA(handle);
738
739         if (NT_STATUS_IS_OK(status) && pinfo) {
740                 *pinfo = info;
741         }
742         return status;
743
744   err:
745
746         smb_panic("create_file_acl_common: logic error.\n");
747         /* NOTREACHED */
748         return status;
749 }