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