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