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