Add acl_xattr:ignore system acls boolean (normally false) to allow
[ira/wip.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 #include "../libcli/security/security.h"
23 #include "../librpc/gen_ndr/ndr_security.h"
24
25 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
26                         DATA_BLOB *pblob,
27                         uint16_t hash_type,
28                         uint8_t hash[XATTR_SD_HASH_SIZE]);
29
30 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
31                         vfs_handle_struct *handle,
32                         files_struct *fsp,
33                         const char *name,
34                         DATA_BLOB *pblob);
35
36 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
37                         files_struct *fsp,
38                         DATA_BLOB *pblob);
39
40 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
41                                 SECINFO_GROUP | \
42                                 SECINFO_DACL | \
43                                 SECINFO_SACL)
44
45 /*******************************************************************
46  Hash a security descriptor.
47 *******************************************************************/
48
49 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
50                         uint8_t *hash)
51 {
52         DATA_BLOB blob;
53         SHA256_CTX tctx;
54         NTSTATUS status;
55
56         memset(hash, '\0', XATTR_SD_HASH_SIZE);
57         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
58         if (!NT_STATUS_IS_OK(status)) {
59                 return status;
60         }
61
62         SHA256_Init(&tctx);
63         SHA256_Update(&tctx, blob.data, blob.length);
64         SHA256_Final(hash, &tctx);
65
66         return NT_STATUS_OK;
67 }
68
69 /*******************************************************************
70  Parse out a struct security_descriptor from a DATA_BLOB.
71 *******************************************************************/
72
73 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
74                                 struct security_descriptor **ppdesc,
75                                 uint16_t *p_hash_type,
76                                 uint8_t hash[XATTR_SD_HASH_SIZE])
77 {
78         TALLOC_CTX *ctx = talloc_tos();
79         struct xattr_NTACL xacl;
80         enum ndr_err_code ndr_err;
81         size_t sd_size;
82
83         ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
84                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
85
86         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
87                 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
88                         ndr_errstr(ndr_err)));
89                 return ndr_map_error2ntstatus(ndr_err);;
90         }
91
92         switch (xacl.version) {
93                 case 2:
94                         *ppdesc = make_sec_desc(ctx, SD_REVISION,
95                                         xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
96                                         xacl.info.sd_hs2->sd->owner_sid,
97                                         xacl.info.sd_hs2->sd->group_sid,
98                                         xacl.info.sd_hs2->sd->sacl,
99                                         xacl.info.sd_hs2->sd->dacl,
100                                         &sd_size);
101                         /* No hash - null out. */
102                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
103                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
104                         break;
105                 case 3:
106                         *ppdesc = make_sec_desc(ctx, SD_REVISION,
107                                         xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
108                                         xacl.info.sd_hs3->sd->owner_sid,
109                                         xacl.info.sd_hs3->sd->group_sid,
110                                         xacl.info.sd_hs3->sd->sacl,
111                                         xacl.info.sd_hs3->sd->dacl,
112                                         &sd_size);
113                         *p_hash_type = xacl.info.sd_hs3->hash_type;
114                         /* Current version 3. */
115                         memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
116                         break;
117                 default:
118                         return NT_STATUS_REVISION_MISMATCH;
119         }
120
121         TALLOC_FREE(xacl.info.sd);
122
123         return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
124 }
125
126 /*******************************************************************
127  Create a DATA_BLOB from a security descriptor.
128 *******************************************************************/
129
130 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
131                         DATA_BLOB *pblob,
132                         uint16_t hash_type,
133                         uint8_t hash[XATTR_SD_HASH_SIZE])
134 {
135         struct xattr_NTACL xacl;
136         struct security_descriptor_hash_v3 sd_hs3;
137         enum ndr_err_code ndr_err;
138         TALLOC_CTX *ctx = talloc_tos();
139
140         ZERO_STRUCT(xacl);
141         ZERO_STRUCT(sd_hs3);
142
143         xacl.version = 3;
144         xacl.info.sd_hs3 = &sd_hs3;
145         xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
146         xacl.info.sd_hs3->hash_type = hash_type;
147         memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
148
149         ndr_err = ndr_push_struct_blob(
150                         pblob, ctx, &xacl,
151                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
152
153         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
154                 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
155                         ndr_errstr(ndr_err)));
156                 return ndr_map_error2ntstatus(ndr_err);;
157         }
158
159         return NT_STATUS_OK;
160 }
161
162 /*******************************************************************
163  Add in 3 inheritable components for a non-inheritable directory ACL.
164  CREATOR_OWNER/CREATOR_GROUP/WORLD.
165 *******************************************************************/
166
167 static void add_directory_inheritable_components(vfs_handle_struct *handle,
168                                 const char *name,
169                                 SMB_STRUCT_STAT *psbuf,
170                                 struct security_descriptor *psd)
171 {
172         struct connection_struct *conn = handle->conn;
173         int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
174         struct smb_filename smb_fname;
175         enum security_ace_type acltype;
176         uint32_t access_mask;
177         mode_t dir_mode;
178         mode_t file_mode;
179         mode_t mode;
180         struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
181                                                 struct security_ace,
182                                                 num_aces + 3);
183
184         if (new_ace_list == NULL) {
185                 return;
186         }
187
188         /* Fake a quick smb_filename. */
189         ZERO_STRUCT(smb_fname);
190         smb_fname.st = *psbuf;
191         smb_fname.base_name = CONST_DISCARD(char *, name);
192
193         dir_mode = unix_mode(conn,
194                         FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
195         file_mode = unix_mode(conn,
196                         FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
197
198         mode = dir_mode | file_mode;
199
200         DEBUG(10, ("add_directory_inheritable_components: directory %s, "
201                 "mode = 0%o\n",
202                 name,
203                 (unsigned int)mode ));
204
205         if (num_aces) {
206                 memcpy(new_ace_list, psd->dacl->aces,
207                         num_aces * sizeof(struct security_ace));
208         }
209         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
210                                 mode & 0700, false);
211
212         init_sec_ace(&new_ace_list[num_aces],
213                         &global_sid_Creator_Owner,
214                         acltype,
215                         access_mask,
216                         SEC_ACE_FLAG_CONTAINER_INHERIT|
217                                 SEC_ACE_FLAG_OBJECT_INHERIT|
218                                 SEC_ACE_FLAG_INHERIT_ONLY);
219         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
220                                 (mode << 3) & 0700, false);
221         init_sec_ace(&new_ace_list[num_aces+1],
222                         &global_sid_Creator_Group,
223                         acltype,
224                         access_mask,
225                         SEC_ACE_FLAG_CONTAINER_INHERIT|
226                                 SEC_ACE_FLAG_OBJECT_INHERIT|
227                                 SEC_ACE_FLAG_INHERIT_ONLY);
228         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
229                                 (mode << 6) & 0700, false);
230         init_sec_ace(&new_ace_list[num_aces+2],
231                         &global_sid_World,
232                         acltype,
233                         access_mask,
234                         SEC_ACE_FLAG_CONTAINER_INHERIT|
235                                 SEC_ACE_FLAG_OBJECT_INHERIT|
236                                 SEC_ACE_FLAG_INHERIT_ONLY);
237         psd->dacl->aces = new_ace_list;
238         psd->dacl->num_aces += 3;
239 }
240
241 /*******************************************************************
242  Pull a DATA_BLOB from an xattr given a pathname.
243  If the hash doesn't match, or doesn't exist - return the underlying
244  filesystem sd.
245 *******************************************************************/
246
247 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
248                                 files_struct *fsp,
249                                 const char *name,
250                                 uint32_t security_info,
251                                 struct security_descriptor **ppdesc)
252 {
253         DATA_BLOB blob;
254         NTSTATUS status;
255         uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
256         uint8_t hash[XATTR_SD_HASH_SIZE];
257         uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
258         struct security_descriptor *psd = NULL;
259         struct security_descriptor *pdesc_next = NULL;
260         bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
261                                                 ACL_MODULE_NAME,
262                                                 "ignore system acls",
263                                                 false);
264
265         if (fsp && name == NULL) {
266                 name = fsp->fsp_name->base_name;
267         }
268
269         DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
270
271         /* Get the full underlying sd for the hash
272            or to return as backup. */
273         if (fsp) {
274                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
275                                 fsp,
276                                 HASH_SECURITY_INFO,
277                                 &pdesc_next);
278         } else {
279                 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
280                                 name,
281                                 HASH_SECURITY_INFO,
282                                 &pdesc_next);
283         }
284
285         if (!NT_STATUS_IS_OK(status)) {
286                 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
287                         "returned %s\n",
288                         name,
289                         nt_errstr(status)));
290                 return status;
291         }
292
293         status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
294         if (!NT_STATUS_IS_OK(status)) {
295                 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
296                         nt_errstr(status)));
297                 psd = pdesc_next;
298                 goto out;
299         }
300
301         status = parse_acl_blob(&blob, &psd,
302                                 &hash_type, &hash[0]);
303         if (!NT_STATUS_IS_OK(status)) {
304                 DEBUG(10, ("parse_acl_blob returned %s\n",
305                                 nt_errstr(status)));
306                 psd = pdesc_next;
307                 goto out;
308         }
309
310         /* Ensure the hash type is one we know. */
311         switch (hash_type) {
312                 case XATTR_SD_HASH_TYPE_NONE:
313                         /* No hash, just return blob sd. */
314                         goto out;
315                 case XATTR_SD_HASH_TYPE_SHA256:
316                         break;
317                 default:
318                         DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
319                                 "mismatch (%u) for file %s\n",
320                                 (unsigned int)hash_type,
321                                 name));
322                         TALLOC_FREE(psd);
323                         psd = pdesc_next;
324                         goto out;
325         }
326
327         if (ignore_file_system_acl) {
328                 goto out;
329         }
330
331         status = hash_sd_sha256(pdesc_next, hash_tmp);
332         if (!NT_STATUS_IS_OK(status)) {
333                 TALLOC_FREE(psd);
334                 psd = pdesc_next;
335                 goto out;
336         }
337
338         if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
339                 /* Hash matches, return blob sd. */
340                 DEBUG(10, ("get_nt_acl_internal: blob hash "
341                         "matches for file %s\n",
342                         name ));
343                 goto out;
344         }
345
346         /* Hash doesn't match, return underlying sd. */
347         TALLOC_FREE(psd);
348         psd = pdesc_next;
349
350   out:
351
352         if (psd != pdesc_next) {
353                 /* We're returning the blob, throw
354                  * away the filesystem SD. */
355                 TALLOC_FREE(pdesc_next);
356         } else {
357                 SMB_STRUCT_STAT sbuf;
358                 SMB_STRUCT_STAT *psbuf = &sbuf;
359                 bool is_directory = false;
360                 /*
361                  * We're returning the underlying ACL from the
362                  * filesystem. If it's a directory, and has no
363                  * inheritable ACE entries we have to fake them.
364                  */
365                 if (fsp) {
366                         status = vfs_stat_fsp(fsp);
367                         if (!NT_STATUS_IS_OK(status)) {
368                                 return status;
369                         }
370                         psbuf = &fsp->fsp_name->st;
371                 } else {
372                         int ret = vfs_stat_smb_fname(handle->conn,
373                                                 name,
374                                                 &sbuf);
375                         if (ret == -1) {
376                                 return map_nt_error_from_unix(errno);
377                         }
378                 }
379                 is_directory = S_ISDIR(sbuf.st_ex_mode);
380
381                 if (ignore_file_system_acl) {
382                         TALLOC_FREE(pdesc_next);
383                         status = make_default_filesystem_acl(talloc_tos(),
384                                                 name,
385                                                 psbuf,
386                                                 &psd);
387                         if (!NT_STATUS_IS_OK(status)) {
388                                 return status;
389                         }
390                 } else {
391                         if (is_directory &&
392                                 !sd_has_inheritable_components(psd,
393                                                         true)) {
394                                 add_directory_inheritable_components(handle,
395                                                         name,
396                                                         psbuf,
397                                                         psd);
398                         }
399                         /* The underlying POSIX module always sets
400                            the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
401                            can't be inherited in this way under POSIX.
402                            Remove it for Windows-style ACLs. */
403                         psd->type &= ~SEC_DESC_DACL_PROTECTED;
404                 }
405         }
406
407         if (!(security_info & SECINFO_OWNER)) {
408                 psd->owner_sid = NULL;
409         }
410         if (!(security_info & SECINFO_GROUP)) {
411                 psd->group_sid = NULL;
412         }
413         if (!(security_info & SECINFO_DACL)) {
414                 psd->dacl = NULL;
415         }
416         if (!(security_info & SECINFO_SACL)) {
417                 psd->sacl = NULL;
418         }
419
420         TALLOC_FREE(blob.data);
421         *ppdesc = psd;
422
423         if (DEBUGLEVEL >= 10) {
424                 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
425                         name ));
426                 NDR_PRINT_DEBUG(security_descriptor, psd);
427         }
428
429         return NT_STATUS_OK;
430 }
431
432 /*********************************************************************
433  Create a default ACL by inheriting from the parent. If no inheritance
434  from the parent available, don't set anything. This will leave the actual
435  permissions the new file or directory already got from the filesystem
436  as the NT ACL when read.
437 *********************************************************************/
438
439 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
440                                         files_struct *fsp,
441                                         struct security_descriptor *parent_desc,
442                                         bool is_directory)
443 {
444         TALLOC_CTX *ctx = talloc_tos();
445         NTSTATUS status = NT_STATUS_OK;
446         struct security_descriptor *psd = NULL;
447         size_t size;
448
449         if (!sd_has_inheritable_components(parent_desc, is_directory)) {
450                 return NT_STATUS_OK;
451         }
452
453         /* Create an inherited descriptor from the parent. */
454
455         if (DEBUGLEVEL >= 10) {
456                 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
457                         fsp_str_dbg(fsp) ));
458                 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
459         }
460
461         status = se_create_child_secdesc(ctx,
462                         &psd,
463                         &size,
464                         parent_desc,
465                         &handle->conn->server_info->ptok->sids[PRIMARY_USER_SID_INDEX],
466                         &handle->conn->server_info->ptok->sids[PRIMARY_GROUP_SID_INDEX],
467                         is_directory);
468         if (!NT_STATUS_IS_OK(status)) {
469                 return status;
470         }
471
472         if (DEBUGLEVEL >= 10) {
473                 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
474                         fsp_str_dbg(fsp) ));
475                 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
476         }
477
478         return SMB_VFS_FSET_NT_ACL(fsp,
479                                 (SECINFO_OWNER |
480                                  SECINFO_GROUP |
481                                  SECINFO_DACL),
482                                 psd);
483 }
484
485 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
486                                 const char *path,
487                                 uint32_t access_mask,
488                                 struct security_descriptor **pp_parent_desc)
489 {
490         char *parent_name = NULL;
491         struct security_descriptor *parent_desc = NULL;
492         uint32_t access_granted = 0;
493         NTSTATUS status;
494
495         if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
496                 return NT_STATUS_NO_MEMORY;
497         }
498
499         status = get_nt_acl_internal(handle,
500                                         NULL,
501                                         parent_name,
502                                         (SECINFO_OWNER |
503                                          SECINFO_GROUP |
504                                          SECINFO_DACL),
505                                         &parent_desc);
506
507         if (!NT_STATUS_IS_OK(status)) {
508                 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
509                         "on directory %s for "
510                         "path %s returned %s\n",
511                         parent_name,
512                         path,
513                         nt_errstr(status) ));
514                 return status;
515         }
516         if (pp_parent_desc) {
517                 *pp_parent_desc = parent_desc;
518         }
519         status = smb1_file_se_access_check(handle->conn,
520                                         parent_desc,
521                                         get_current_nttok(handle->conn),
522                                         access_mask,
523                                         &access_granted);
524         if(!NT_STATUS_IS_OK(status)) {
525                 DEBUG(10,("check_parent_acl_common: access check "
526                         "on directory %s for "
527                         "path %s for mask 0x%x returned %s\n",
528                         parent_name,
529                         path,
530                         access_mask,
531                         nt_errstr(status) ));
532                 return status;
533         }
534         return NT_STATUS_OK;
535 }
536
537 static void free_sd_common(void **ptr)
538 {
539         TALLOC_FREE(*ptr);
540 }
541
542 /*********************************************************************
543  Check ACL on open. For new files inherit from parent directory.
544 *********************************************************************/
545
546 static int open_acl_common(vfs_handle_struct *handle,
547                         struct smb_filename *smb_fname,
548                         files_struct *fsp,
549                         int flags,
550                         mode_t mode)
551 {
552         uint32_t access_granted = 0;
553         struct security_descriptor *pdesc = NULL;
554         struct security_descriptor *parent_desc = NULL;
555         bool file_existed = true;
556         char *fname = NULL;
557         NTSTATUS status;
558
559         if (fsp->base_fsp) {
560                 /* Stream open. Base filename open already did the ACL check. */
561                 DEBUG(10,("open_acl_common: stream open on %s\n",
562                         fsp_str_dbg(fsp) ));
563                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
564         }
565
566         status = get_full_smb_filename(talloc_tos(), smb_fname,
567                                        &fname);
568         if (!NT_STATUS_IS_OK(status)) {
569                 goto err;
570         }
571
572         status = get_nt_acl_internal(handle,
573                                 NULL,
574                                 fname,
575                                 (SECINFO_OWNER |
576                                  SECINFO_GROUP |
577                                  SECINFO_DACL),
578                                 &pdesc);
579         if (NT_STATUS_IS_OK(status)) {
580                 /* See if we can access it. */
581                 status = smb1_file_se_access_check(handle->conn,
582                                         pdesc,
583                                         get_current_nttok(handle->conn),
584                                         fsp->access_mask,
585                                         &access_granted);
586                 if (!NT_STATUS_IS_OK(status)) {
587                         DEBUG(10,("open_acl_xattr: %s open "
588                                 "refused with error %s\n",
589                                 fsp_str_dbg(fsp),
590                                 nt_errstr(status) ));
591                         goto err;
592                 }
593         } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
594                 file_existed = false;
595                 /*
596                  * If O_CREAT is true then we're trying to create a file.
597                  * Check the parent directory ACL will allow this.
598                  */
599                 if (flags & O_CREAT) {
600                         struct security_descriptor *psd = NULL;
601
602                         status = check_parent_acl_common(handle, fname,
603                                         SEC_DIR_ADD_FILE, &parent_desc);
604                         if (!NT_STATUS_IS_OK(status)) {
605                                 goto err;
606                         }
607                         /* Cache the parent security descriptor for
608                          * later use. We do have an fsp here, but to
609                          * keep the code consistent with the directory
610                          * case which doesn't, use the handle. */
611
612                         /* Attach this to the conn, move from talloc_tos(). */
613                         psd = (struct security_descriptor *)talloc_move(handle->conn,
614                                 &parent_desc);
615
616                         if (!psd) {
617                                 status = NT_STATUS_NO_MEMORY;
618                                 goto err;
619                         }
620                         status = NT_STATUS_NO_MEMORY;
621                         SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
622                                 struct security_descriptor *, goto err);
623                         status = NT_STATUS_OK;
624                 }
625         }
626
627         DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
628                 "%s returned %s\n",
629                 fsp_str_dbg(fsp),
630                 nt_errstr(status) ));
631
632         fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
633         return fsp->fh->fd;
634
635   err:
636
637         errno = map_errno_from_nt_status(status);
638         return -1;
639 }
640
641 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
642 {
643         int ret;
644         NTSTATUS status;
645         SMB_STRUCT_STAT sbuf;
646
647         ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
648         if (ret == -1 && errno == ENOENT) {
649                 struct security_descriptor *parent_desc = NULL;
650                 struct security_descriptor *psd = NULL;
651
652                 /* We're creating a new directory. */
653                 status = check_parent_acl_common(handle, path,
654                                 SEC_DIR_ADD_SUBDIR, &parent_desc);
655                 if (!NT_STATUS_IS_OK(status)) {
656                         errno = map_errno_from_nt_status(status);
657                         return -1;
658                 }
659
660                 /* Cache the parent security descriptor for
661                  * later use. We don't have an fsp here so
662                  * use the handle. */
663
664                 /* Attach this to the conn, move from talloc_tos(). */
665                 psd = (struct security_descriptor *)talloc_move(handle->conn,
666                                 &parent_desc);
667
668                 if (!psd) {
669                         return -1;
670                 }
671                 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
672                         struct security_descriptor *, return -1);
673         }
674
675         return SMB_VFS_NEXT_MKDIR(handle, path, mode);
676 }
677
678 /*********************************************************************
679  Fetch a security descriptor given an fsp.
680 *********************************************************************/
681
682 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
683         uint32_t security_info, struct security_descriptor **ppdesc)
684 {
685         return get_nt_acl_internal(handle, fsp,
686                                 NULL, security_info, ppdesc);
687 }
688
689 /*********************************************************************
690  Fetch a security descriptor given a pathname.
691 *********************************************************************/
692
693 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
694         const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
695 {
696         return get_nt_acl_internal(handle, NULL,
697                                 name, security_info, ppdesc);
698 }
699
700 /*********************************************************************
701  Store a security descriptor given an fsp.
702 *********************************************************************/
703
704 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
705         uint32_t security_info_sent, const struct security_descriptor *orig_psd)
706 {
707         NTSTATUS status;
708         DATA_BLOB blob;
709         struct security_descriptor *pdesc_next = NULL;
710         struct security_descriptor *psd = NULL;
711         uint8_t hash[XATTR_SD_HASH_SIZE];
712
713         if (DEBUGLEVEL >= 10) {
714                 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
715                           fsp_str_dbg(fsp)));
716                 NDR_PRINT_DEBUG(security_descriptor,
717                         CONST_DISCARD(struct security_descriptor *,orig_psd));
718         }
719
720         status = get_nt_acl_internal(handle, fsp,
721                         NULL,
722                         SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
723                         &psd);
724
725         if (!NT_STATUS_IS_OK(status)) {
726                 return status;
727         }
728
729         if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
730                 psd->owner_sid = orig_psd->owner_sid;
731         }
732         if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
733                 psd->group_sid = orig_psd->group_sid;
734         }
735         if (security_info_sent & SECINFO_DACL) {
736                 psd->dacl = orig_psd->dacl;
737         }
738         if (security_info_sent & SECINFO_SACL) {
739                 psd->sacl = orig_psd->sacl;
740         }
741
742         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
743         if (!NT_STATUS_IS_OK(status)) {
744                 return status;
745         }
746
747         /* Get the full underlying sd, then hash. */
748         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
749                                 fsp,
750                                 HASH_SECURITY_INFO,
751                                 &pdesc_next);
752
753         if (!NT_STATUS_IS_OK(status)) {
754                 return status;
755         }
756
757         status = hash_sd_sha256(pdesc_next, hash);
758         if (!NT_STATUS_IS_OK(status)) {
759                 return status;
760         }
761
762         if (DEBUGLEVEL >= 10) {
763                 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
764                           fsp_str_dbg(fsp)));
765                 NDR_PRINT_DEBUG(security_descriptor,
766                         CONST_DISCARD(struct security_descriptor *,psd));
767         }
768         create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
769         store_acl_blob_fsp(handle, fsp, &blob);
770
771         return NT_STATUS_OK;
772 }
773
774 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
775                         const char *fname, const char *mask, uint32 attr)
776 {
777         NTSTATUS status = check_parent_acl_common(handle, fname,
778                                         SEC_DIR_LIST, NULL);
779
780         if (!NT_STATUS_IS_OK(status)) {
781                 errno = map_errno_from_nt_status(status);
782                 return NULL;
783         }
784         return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
785 }
786
787 static int acl_common_remove_object(vfs_handle_struct *handle,
788                                         const char *path,
789                                         bool is_directory)
790 {
791         connection_struct *conn = handle->conn;
792         struct file_id id;
793         files_struct *fsp = NULL;
794         int ret = 0;
795         char *parent_dir = NULL;
796         const char *final_component = NULL;
797         struct smb_filename local_fname;
798         int saved_errno = 0;
799
800         if (!parent_dirname(talloc_tos(), path,
801                         &parent_dir, &final_component)) {
802                 saved_errno = ENOMEM;
803                 goto out;
804         }
805
806         DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
807                 is_directory ? "directory" : "file",
808                 parent_dir, final_component ));
809
810         /* cd into the parent dir to pin it. */
811         ret = SMB_VFS_CHDIR(conn, parent_dir);
812         if (ret == -1) {
813                 saved_errno = errno;
814                 goto out;
815         }
816
817         ZERO_STRUCT(local_fname);
818         local_fname.base_name = CONST_DISCARD(char *,final_component);
819
820         /* Must use lstat here. */
821         ret = SMB_VFS_LSTAT(conn, &local_fname);
822         if (ret == -1) {
823                 saved_errno = errno;
824                 goto out;
825         }
826
827         /* Ensure we have this file open with DELETE access. */
828         id = vfs_file_id_from_sbuf(conn, &local_fname.st);
829         for (fsp = file_find_di_first(conn->sconn, id); fsp;
830              file_find_di_next(fsp)) {
831                 if (fsp->access_mask & DELETE_ACCESS &&
832                                 fsp->delete_on_close) {
833                         /* We did open this for delete,
834                          * allow the delete as root.
835                          */
836                         break;
837                 }
838         }
839
840         if (!fsp) {
841                 DEBUG(10,("acl_common_remove_object: %s %s/%s "
842                         "not an open file\n",
843                         is_directory ? "directory" : "file",
844                         parent_dir, final_component ));
845                 saved_errno = EACCES;
846                 goto out;
847         }
848
849         become_root();
850         if (is_directory) {
851                 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
852         } else {
853                 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
854         }
855         unbecome_root();
856
857         if (ret == -1) {
858                 saved_errno = errno;
859         }
860
861   out:
862
863         TALLOC_FREE(parent_dir);
864
865         vfs_ChDir(conn, conn->connectpath);
866         if (saved_errno) {
867                 errno = saved_errno;
868         }
869         return ret;
870 }
871
872 static int rmdir_acl_common(struct vfs_handle_struct *handle,
873                                 const char *path)
874 {
875         int ret;
876
877         ret = SMB_VFS_NEXT_RMDIR(handle, path);
878         if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
879                 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
880                         path,
881                         strerror(errno) ));
882                 return ret;
883         }
884
885         return acl_common_remove_object(handle,
886                                         path,
887                                         true);
888 }
889
890 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
891                                 struct smb_request *req,
892                                 uint16_t root_dir_fid,
893                                 struct smb_filename *smb_fname,
894                                 uint32_t access_mask,
895                                 uint32_t share_access,
896                                 uint32_t create_disposition,
897                                 uint32_t create_options,
898                                 uint32_t file_attributes,
899                                 uint32_t oplock_request,
900                                 uint64_t allocation_size,
901                                 uint32_t private_flags,
902                                 struct security_descriptor *sd,
903                                 struct ea_list *ea_list,
904                                 files_struct **result,
905                                 int *pinfo)
906 {
907         NTSTATUS status, status1;
908         files_struct *fsp = NULL;
909         int info;
910         struct security_descriptor *parent_sd = NULL;
911
912         status = SMB_VFS_NEXT_CREATE_FILE(handle,
913                                         req,
914                                         root_dir_fid,
915                                         smb_fname,
916                                         access_mask,
917                                         share_access,
918                                         create_disposition,
919                                         create_options,
920                                         file_attributes,
921                                         oplock_request,
922                                         allocation_size,
923                                         private_flags,
924                                         sd,
925                                         ea_list,
926                                         result,
927                                         &info);
928
929         if (!NT_STATUS_IS_OK(status)) {
930                 goto out;
931         }
932
933         if (info != FILE_WAS_CREATED) {
934                 /* File/directory was opened, not created. */
935                 goto out;
936         }
937
938         fsp = *result;
939
940         if (fsp == NULL) {
941                 /* Only handle success. */
942                 goto out;
943         }
944
945         if (sd) {
946                 /* Security descriptor already set. */
947                 goto out;
948         }
949
950         if (fsp->base_fsp) {
951                 /* Stream open. */
952                 goto out;
953         }
954
955
956         /* We must have a cached parent sd in this case.
957          * attached to the handle. */
958
959         SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
960                 struct security_descriptor,
961                 goto err);
962
963         if (!parent_sd) {
964                 goto err;
965         }
966
967         /* New directory - inherit from parent. */
968         status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
969
970         if (!NT_STATUS_IS_OK(status1)) {
971                 DEBUG(1,("create_file_acl_common: error setting "
972                         "sd for %s (%s)\n",
973                         fsp_str_dbg(fsp),
974                         nt_errstr(status1) ));
975         }
976
977   out:
978
979         /* Ensure we never leave attached data around. */
980         SMB_VFS_HANDLE_FREE_DATA(handle);
981
982         if (NT_STATUS_IS_OK(status) && pinfo) {
983                 *pinfo = info;
984         }
985         return status;
986
987   err:
988
989         smb_panic("create_file_acl_common: logic error.\n");
990         /* NOTREACHED */
991         return status;
992 }
993
994 static int unlink_acl_common(struct vfs_handle_struct *handle,
995                         const struct smb_filename *smb_fname)
996 {
997         int ret;
998
999         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1000         if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
1001                 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1002                         smb_fname->base_name,
1003                         strerror(errno) ));
1004                 return ret;
1005         }
1006         /* Don't do anything fancy for streams. */
1007         if (smb_fname->stream_name) {
1008                 return ret;
1009         }
1010
1011         return acl_common_remove_object(handle,
1012                                         smb_fname->base_name,
1013                                         false);
1014 }