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