097fd20dc04d7fa5655dc4cf0dfcc0ae11134c62
[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         create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
808         store_acl_blob_fsp(handle, fsp, &blob);
809
810         return NT_STATUS_OK;
811 }
812
813 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
814                         const char *fname, const char *mask, uint32 attr)
815 {
816         NTSTATUS status;
817         uint32_t access_granted = 0;
818         struct security_descriptor *sd = NULL;
819
820         status = get_nt_acl_internal(handle,
821                                 NULL,
822                                 fname,
823                                 (SECINFO_OWNER |
824                                  SECINFO_GROUP |
825                                  SECINFO_DACL  |
826                                  SECINFO_SACL),
827                                 &sd);
828         if (!NT_STATUS_IS_OK(status)) {
829                 DEBUG(10,("opendir_acl_common: "
830                         "get_nt_acl_internal for dir %s "
831                         "failed with error %s\n",
832                         fname,
833                         nt_errstr(status) ));
834                 errno = map_errno_from_nt_status(status);
835                 return NULL;
836         }
837
838         /* See if we can access it. */
839         status = smb1_file_se_access_check(handle->conn,
840                                 sd,
841                                 get_current_nttok(handle->conn),
842                                 SEC_DIR_LIST,
843                                 &access_granted);
844         if (!NT_STATUS_IS_OK(status)) {
845                 DEBUG(10,("opendir_acl_common: %s open "
846                         "for access SEC_DIR_LIST "
847                         "refused with error %s\n",
848                         fname,
849                         nt_errstr(status) ));
850                 errno = map_errno_from_nt_status(status);
851                 return NULL;
852         }
853
854         return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
855 }
856
857 static int acl_common_remove_object(vfs_handle_struct *handle,
858                                         const char *path,
859                                         bool is_directory)
860 {
861         connection_struct *conn = handle->conn;
862         struct file_id id;
863         files_struct *fsp = NULL;
864         int ret = 0;
865         char *parent_dir = NULL;
866         const char *final_component = NULL;
867         struct smb_filename local_fname;
868         int saved_errno = 0;
869         char *saved_dir = NULL;
870
871         saved_dir = vfs_GetWd(talloc_tos(),conn);
872         if (!saved_dir) {
873                 saved_errno = errno;
874                 goto out;
875         }
876
877         if (!parent_dirname(talloc_tos(), path,
878                         &parent_dir, &final_component)) {
879                 saved_errno = ENOMEM;
880                 goto out;
881         }
882
883         DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
884                 is_directory ? "directory" : "file",
885                 parent_dir, final_component ));
886
887         /* cd into the parent dir to pin it. */
888         ret = vfs_ChDir(conn, parent_dir);
889         if (ret == -1) {
890                 saved_errno = errno;
891                 goto out;
892         }
893
894         ZERO_STRUCT(local_fname);
895         local_fname.base_name = CONST_DISCARD(char *,final_component);
896
897         /* Must use lstat here. */
898         ret = SMB_VFS_LSTAT(conn, &local_fname);
899         if (ret == -1) {
900                 saved_errno = errno;
901                 goto out;
902         }
903
904         /* Ensure we have this file open with DELETE access. */
905         id = vfs_file_id_from_sbuf(conn, &local_fname.st);
906         for (fsp = file_find_di_first(conn->sconn, id); fsp;
907                      fsp = file_find_di_next(fsp)) {
908                 if (fsp->access_mask & DELETE_ACCESS &&
909                                 fsp->delete_on_close) {
910                         /* We did open this for delete,
911                          * allow the delete as root.
912                          */
913                         break;
914                 }
915         }
916
917         if (!fsp) {
918                 DEBUG(10,("acl_common_remove_object: %s %s/%s "
919                         "not an open file\n",
920                         is_directory ? "directory" : "file",
921                         parent_dir, final_component ));
922                 saved_errno = EACCES;
923                 goto out;
924         }
925
926         become_root();
927         if (is_directory) {
928                 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
929         } else {
930                 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
931         }
932         unbecome_root();
933
934         if (ret == -1) {
935                 saved_errno = errno;
936         }
937
938   out:
939
940         TALLOC_FREE(parent_dir);
941
942         if (saved_dir) {
943                 vfs_ChDir(conn, saved_dir);
944         }
945         if (saved_errno) {
946                 errno = saved_errno;
947         }
948         return ret;
949 }
950
951 static int rmdir_acl_common(struct vfs_handle_struct *handle,
952                                 const char *path)
953 {
954         int ret;
955
956         /* Try the normal rmdir first. */
957         ret = SMB_VFS_NEXT_RMDIR(handle, path);
958         if (ret == 0) {
959                 return 0;
960         }
961         if (errno == EACCES || errno == EPERM) {
962                 /* Failed due to access denied,
963                    see if we need to root override. */
964                 return acl_common_remove_object(handle,
965                                                 path,
966                                                 true);
967         }
968
969         DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
970                 path,
971                 strerror(errno) ));
972         return -1;
973 }
974
975 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
976                                 struct smb_request *req,
977                                 uint16_t root_dir_fid,
978                                 struct smb_filename *smb_fname,
979                                 uint32_t access_mask,
980                                 uint32_t share_access,
981                                 uint32_t create_disposition,
982                                 uint32_t create_options,
983                                 uint32_t file_attributes,
984                                 uint32_t oplock_request,
985                                 uint64_t allocation_size,
986                                 uint32_t private_flags,
987                                 struct security_descriptor *sd,
988                                 struct ea_list *ea_list,
989                                 files_struct **result,
990                                 int *pinfo)
991 {
992         NTSTATUS status, status1;
993         files_struct *fsp = NULL;
994         int info;
995         struct security_descriptor *parent_sd = NULL;
996         struct security_descriptor **pp_parent_sd = NULL;
997
998         status = SMB_VFS_NEXT_CREATE_FILE(handle,
999                                         req,
1000                                         root_dir_fid,
1001                                         smb_fname,
1002                                         access_mask,
1003                                         share_access,
1004                                         create_disposition,
1005                                         create_options,
1006                                         file_attributes,
1007                                         oplock_request,
1008                                         allocation_size,
1009                                         private_flags,
1010                                         sd,
1011                                         ea_list,
1012                                         result,
1013                                         &info);
1014
1015         if (!NT_STATUS_IS_OK(status)) {
1016                 goto out;
1017         }
1018
1019         if (info != FILE_WAS_CREATED) {
1020                 /* File/directory was opened, not created. */
1021                 goto out;
1022         }
1023
1024         fsp = *result;
1025
1026         if (fsp == NULL) {
1027                 /* Only handle success. */
1028                 goto out;
1029         }
1030
1031         if (sd) {
1032                 /* Security descriptor already set. */
1033                 goto out;
1034         }
1035
1036         if (fsp->base_fsp) {
1037                 /* Stream open. */
1038                 goto out;
1039         }
1040
1041         /* See if we have a cached parent sd, if so, use it. */
1042         pp_parent_sd = (struct security_descriptor **)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1043         if (!pp_parent_sd) {
1044                 /* Must be a directory, fetch again (sigh). */
1045                 status = get_parent_acl_common(handle,
1046                                 fsp->fsp_name->base_name,
1047                                 &parent_sd);
1048                 if (!NT_STATUS_IS_OK(status)) {
1049                         goto out;
1050                 }
1051         } else {
1052                 parent_sd = *pp_parent_sd;
1053         }
1054
1055         if (!parent_sd) {
1056                 goto err;
1057         }
1058
1059         /* New directory - inherit from parent. */
1060         status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
1061
1062         if (!NT_STATUS_IS_OK(status1)) {
1063                 DEBUG(1,("create_file_acl_common: error setting "
1064                         "sd for %s (%s)\n",
1065                         fsp_str_dbg(fsp),
1066                         nt_errstr(status1) ));
1067         }
1068
1069   out:
1070
1071         if (fsp) {
1072                 VFS_REMOVE_FSP_EXTENSION(handle, fsp);
1073         }
1074
1075         if (NT_STATUS_IS_OK(status) && pinfo) {
1076                 *pinfo = info;
1077         }
1078         return status;
1079
1080   err:
1081
1082         smb_panic("create_file_acl_common: logic error.\n");
1083         /* NOTREACHED */
1084         return status;
1085 }
1086
1087 static int unlink_acl_common(struct vfs_handle_struct *handle,
1088                         const struct smb_filename *smb_fname)
1089 {
1090         int ret;
1091
1092         /* Try the normal unlink first. */
1093         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1094         if (ret == 0) {
1095                 return 0;
1096         }
1097         if (errno == EACCES || errno == EPERM) {
1098                 /* Failed due to access denied,
1099                    see if we need to root override. */
1100
1101                 /* Don't do anything fancy for streams. */
1102                 if (smb_fname->stream_name) {
1103                         return -1;
1104                 }
1105                 return acl_common_remove_object(handle,
1106                                         smb_fname->base_name,
1107                                         false);
1108         }
1109
1110         DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1111                 smb_fname->base_name,
1112                 strerror(errno) ));
1113         return -1;
1114 }
1115
1116 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
1117                         const char *path, mode_t mode)
1118 {
1119         if (lp_posix_pathnames()) {
1120                 /* Only allow this on POSIX pathnames. */
1121                 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1122         }
1123         return 0;
1124 }
1125
1126 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1127                         struct files_struct *fsp, mode_t mode)
1128 {
1129         if (fsp->posix_open) {
1130                 /* Only allow this on POSIX opens. */
1131                 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1132         }
1133         return 0;
1134 }
1135
1136 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1137                         const char *name, mode_t mode)
1138 {
1139         if (lp_posix_pathnames()) {
1140                 /* Only allow this on POSIX pathnames. */
1141                 return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
1142         }
1143         return 0;
1144 }
1145
1146 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1147                         struct files_struct *fsp, mode_t mode)
1148 {
1149         if (fsp->posix_open) {
1150                 /* Only allow this on POSIX opens. */
1151                 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
1152         }
1153         return 0;
1154 }