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