s3:modules: Add FALL_THROUGH statements in vfs_acl_common.c
[amitay/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  * Copyright (C) Ralph Böhme, 2016
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "includes.h"
24 #include "vfs_acl_common.h"
25 #include "smbd/smbd.h"
26 #include "system/filesys.h"
27 #include "librpc/gen_ndr/ndr_xattr.h"
28 #include "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "../lib/util/bitmap.h"
31 #include "lib/crypto/sha256.h"
32 #include "passdb/lookup_sid.h"
33
34 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
35                         DATA_BLOB *pblob,
36                         uint16_t hash_type,
37                         uint8_t hash[XATTR_SD_HASH_SIZE]);
38
39 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
40                                 SECINFO_GROUP | \
41                                 SECINFO_DACL | \
42                                 SECINFO_SACL)
43
44 bool init_acl_common_config(vfs_handle_struct *handle,
45                             const char *module_name)
46 {
47         struct acl_common_config *config = NULL;
48         const struct enum_list *default_acl_style_list = NULL;
49
50         default_acl_style_list = get_default_acl_style_list();
51
52         config = talloc_zero(handle->conn, struct acl_common_config);
53         if (config == NULL) {
54                 DBG_ERR("talloc_zero() failed\n");
55                 errno = ENOMEM;
56                 return false;
57         }
58
59         config->ignore_system_acls = lp_parm_bool(SNUM(handle->conn),
60                                                   module_name,
61                                                   "ignore system acls",
62                                                   false);
63         config->default_acl_style = lp_parm_enum(SNUM(handle->conn),
64                                                  module_name,
65                                                  "default acl style",
66                                                  default_acl_style_list,
67                                                  DEFAULT_ACL_POSIX);
68
69         SMB_VFS_HANDLE_SET_DATA(handle, config, NULL,
70                                 struct acl_common_config,
71                                 return false);
72
73         return true;
74 }
75
76
77 /*******************************************************************
78  Hash a security descriptor.
79 *******************************************************************/
80
81 static NTSTATUS hash_blob_sha256(DATA_BLOB blob,
82                                  uint8_t *hash)
83 {
84         SHA256_CTX tctx;
85
86         memset(hash, '\0', XATTR_SD_HASH_SIZE);
87
88         samba_SHA256_Init(&tctx);
89         samba_SHA256_Update(&tctx, blob.data, blob.length);
90         samba_SHA256_Final(hash, &tctx);
91
92         return NT_STATUS_OK;
93 }
94
95 /*******************************************************************
96  Hash a security descriptor.
97 *******************************************************************/
98
99 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
100                         uint8_t *hash)
101 {
102         DATA_BLOB blob;
103         NTSTATUS status;
104
105         memset(hash, '\0', XATTR_SD_HASH_SIZE);
106         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
107         if (!NT_STATUS_IS_OK(status)) {
108                 return status;
109         }
110         return hash_blob_sha256(blob, hash);
111 }
112
113 /*******************************************************************
114  Parse out a struct security_descriptor from a DATA_BLOB.
115 *******************************************************************/
116
117 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
118                                TALLOC_CTX *mem_ctx,
119                                struct security_descriptor **ppdesc,
120                                uint16_t *p_hash_type,
121                                uint16_t *p_version,
122                                uint8_t hash[XATTR_SD_HASH_SIZE],
123                                uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
124 {
125         struct xattr_NTACL xacl;
126         enum ndr_err_code ndr_err;
127         size_t sd_size;
128         TALLOC_CTX *frame = talloc_stackframe();
129
130         ndr_err = ndr_pull_struct_blob(pblob, frame, &xacl,
131                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
132
133         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
134                 DBG_INFO("ndr_pull_xattr_NTACL failed: %s\n",
135                          ndr_errstr(ndr_err));
136                 TALLOC_FREE(frame);
137                 return ndr_map_error2ntstatus(ndr_err);
138         }
139
140         *p_version = xacl.version;
141
142         switch (xacl.version) {
143                 case 1:
144                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
145                                         xacl.info.sd->type | SEC_DESC_SELF_RELATIVE,
146                                         xacl.info.sd->owner_sid,
147                                         xacl.info.sd->group_sid,
148                                         xacl.info.sd->sacl,
149                                         xacl.info.sd->dacl,
150                                         &sd_size);
151                         /* No hash - null out. */
152                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
153                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
154                         break;
155                 case 2:
156                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
157                                         xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
158                                         xacl.info.sd_hs2->sd->owner_sid,
159                                         xacl.info.sd_hs2->sd->group_sid,
160                                         xacl.info.sd_hs2->sd->sacl,
161                                         xacl.info.sd_hs2->sd->dacl,
162                                         &sd_size);
163                         /* No hash - null out. */
164                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
165                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
166                         break;
167                 case 3:
168                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
169                                         xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
170                                         xacl.info.sd_hs3->sd->owner_sid,
171                                         xacl.info.sd_hs3->sd->group_sid,
172                                         xacl.info.sd_hs3->sd->sacl,
173                                         xacl.info.sd_hs3->sd->dacl,
174                                         &sd_size);
175                         *p_hash_type = xacl.info.sd_hs3->hash_type;
176                         /* Current version 3 (if no sys acl hash available). */
177                         memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
178                         break;
179                 case 4:
180                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
181                                         xacl.info.sd_hs4->sd->type | SEC_DESC_SELF_RELATIVE,
182                                         xacl.info.sd_hs4->sd->owner_sid,
183                                         xacl.info.sd_hs4->sd->group_sid,
184                                         xacl.info.sd_hs4->sd->sacl,
185                                         xacl.info.sd_hs4->sd->dacl,
186                                         &sd_size);
187                         *p_hash_type = xacl.info.sd_hs4->hash_type;
188                         /* Current version 4. */
189                         memcpy(hash, xacl.info.sd_hs4->hash, XATTR_SD_HASH_SIZE);
190                         memcpy(sys_acl_hash, xacl.info.sd_hs4->sys_acl_hash, XATTR_SD_HASH_SIZE);
191                         break;
192                 default:
193                         TALLOC_FREE(frame);
194                         return NT_STATUS_REVISION_MISMATCH;
195         }
196
197         TALLOC_FREE(frame);
198
199         return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
200 }
201
202 /*******************************************************************
203  Create a DATA_BLOB from a hash of the security descriptor storead at
204  the system layer and the NT ACL we wish to preserve
205 *******************************************************************/
206
207 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
208                         DATA_BLOB *pblob,
209                         uint16_t hash_type,
210                         uint8_t hash[XATTR_SD_HASH_SIZE])
211 {
212         struct xattr_NTACL xacl;
213         struct security_descriptor_hash_v3 sd_hs3;
214         enum ndr_err_code ndr_err;
215         TALLOC_CTX *ctx = talloc_tos();
216
217         ZERO_STRUCT(xacl);
218         ZERO_STRUCT(sd_hs3);
219
220         xacl.version = 3;
221         xacl.info.sd_hs3 = &sd_hs3;
222         xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd);
223         xacl.info.sd_hs3->hash_type = hash_type;
224         memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
225
226         ndr_err = ndr_push_struct_blob(
227                         pblob, ctx, &xacl,
228                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
229
230         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
231                 DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
232                          ndr_errstr(ndr_err));
233                 return ndr_map_error2ntstatus(ndr_err);
234         }
235
236         return NT_STATUS_OK;
237 }
238
239 /*******************************************************************
240  Create a DATA_BLOB from a hash of the security descriptors 
241  (system and NT) stored at the system layer and the NT ACL we wish 
242  to preserve.
243 *******************************************************************/
244
245 static NTSTATUS create_sys_acl_blob(const struct security_descriptor *psd,
246                                     DATA_BLOB *pblob,
247                                     uint16_t hash_type,
248                                     uint8_t hash[XATTR_SD_HASH_SIZE],
249                                     const char *description,
250                                     uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
251 {
252         struct xattr_NTACL xacl;
253         struct security_descriptor_hash_v4 sd_hs4;
254         enum ndr_err_code ndr_err;
255         TALLOC_CTX *ctx = talloc_tos();
256         NTTIME nttime_now;
257         struct timeval now = timeval_current();
258         nttime_now = timeval_to_nttime(&now);
259
260         ZERO_STRUCT(xacl);
261         ZERO_STRUCT(sd_hs4);
262
263         xacl.version = 4;
264         xacl.info.sd_hs4 = &sd_hs4;
265         xacl.info.sd_hs4->sd = discard_const_p(struct security_descriptor, psd);
266         xacl.info.sd_hs4->hash_type = hash_type;
267         memcpy(&xacl.info.sd_hs4->hash[0], hash, XATTR_SD_HASH_SIZE);
268         xacl.info.sd_hs4->description = description;
269         xacl.info.sd_hs4->time = nttime_now;
270         memcpy(&xacl.info.sd_hs4->sys_acl_hash[0], sys_acl_hash, XATTR_SD_HASH_SIZE);
271
272         ndr_err = ndr_push_struct_blob(
273                         pblob, ctx, &xacl,
274                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
275
276         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
277                 DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
278                          ndr_errstr(ndr_err));
279                 return ndr_map_error2ntstatus(ndr_err);
280         }
281
282         return NT_STATUS_OK;
283 }
284
285 /*******************************************************************
286  Add in 3 inheritable components for a non-inheritable directory ACL.
287  CREATOR_OWNER/CREATOR_GROUP/WORLD.
288 *******************************************************************/
289
290 static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
291                                 const char *name,
292                                 SMB_STRUCT_STAT *psbuf,
293                                 struct security_descriptor *psd)
294 {
295         struct connection_struct *conn = handle->conn;
296         int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
297         struct smb_filename smb_fname;
298         enum security_ace_type acltype;
299         uint32_t access_mask;
300         mode_t dir_mode;
301         mode_t file_mode;
302         mode_t mode;
303         struct security_ace *new_ace_list;
304
305         if (psd->dacl) {
306                 new_ace_list = talloc_zero_array(psd->dacl,
307                                                  struct security_ace,
308                                                  num_aces + 3);
309         } else {
310                 /*
311                  * make_sec_acl() at the bottom of this function
312                  * dupliates new_ace_list
313                  */
314                 new_ace_list = talloc_zero_array(talloc_tos(),
315                                                  struct security_ace,
316                                                  num_aces + 3);
317         }
318
319         if (new_ace_list == NULL) {
320                 return NT_STATUS_NO_MEMORY;
321         }
322
323         /* Fake a quick smb_filename. */
324         ZERO_STRUCT(smb_fname);
325         smb_fname.st = *psbuf;
326         smb_fname.base_name = discard_const_p(char, name);
327
328         dir_mode = unix_mode(conn,
329                         FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
330         file_mode = unix_mode(conn,
331                         FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
332
333         mode = dir_mode | file_mode;
334
335         DBG_DEBUG("directory %s, mode = 0%o\n", name, (unsigned int)mode);
336
337         if (num_aces) {
338                 memcpy(new_ace_list, psd->dacl->aces,
339                         num_aces * sizeof(struct security_ace));
340         }
341         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
342                                 mode & 0700, false);
343
344         init_sec_ace(&new_ace_list[num_aces],
345                         &global_sid_Creator_Owner,
346                         acltype,
347                         access_mask,
348                         SEC_ACE_FLAG_CONTAINER_INHERIT|
349                                 SEC_ACE_FLAG_OBJECT_INHERIT|
350                                 SEC_ACE_FLAG_INHERIT_ONLY);
351         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
352                                 (mode << 3) & 0700, false);
353         init_sec_ace(&new_ace_list[num_aces+1],
354                         &global_sid_Creator_Group,
355                         acltype,
356                         access_mask,
357                         SEC_ACE_FLAG_CONTAINER_INHERIT|
358                                 SEC_ACE_FLAG_OBJECT_INHERIT|
359                                 SEC_ACE_FLAG_INHERIT_ONLY);
360         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
361                                 (mode << 6) & 0700, false);
362         init_sec_ace(&new_ace_list[num_aces+2],
363                         &global_sid_World,
364                         acltype,
365                         access_mask,
366                         SEC_ACE_FLAG_CONTAINER_INHERIT|
367                                 SEC_ACE_FLAG_OBJECT_INHERIT|
368                                 SEC_ACE_FLAG_INHERIT_ONLY);
369         if (psd->dacl) {
370                 psd->dacl->aces = new_ace_list;
371                 psd->dacl->num_aces += 3;
372                 psd->dacl->size += new_ace_list[num_aces].size +
373                         new_ace_list[num_aces+1].size +
374                         new_ace_list[num_aces+2].size;
375         } else {
376                 psd->dacl = make_sec_acl(psd,
377                                 NT4_ACL_REVISION,
378                                 3,
379                                 new_ace_list);
380                 if (psd->dacl == NULL) {
381                         return NT_STATUS_NO_MEMORY;
382                 }
383         }
384         return NT_STATUS_OK;
385 }
386
387 /**
388  * Validate an ACL blob
389  *
390  * This validates an ACL blob against the underlying filesystem ACL. If this
391  * function returns NT_STATUS_OK ppsd can be
392  *
393  * 1. the ACL from the blob (psd_from_fs=false), or
394  * 2. the ACL from the fs (psd_from_fs=true), or
395  * 3. NULL (!)
396  *
397  * If the return value is anything else then NT_STATUS_OK, ppsd is set to NULL
398  * and psd_from_fs set to false.
399  *
400  * Returning the underlying filesystem ACL in case no. 2 is really just an
401  * optimisation, because some validations have to fetch the filesytem ACL as
402  * part of the validation, so we already have it available and callers might
403  * need it as well.
404  **/
405 static NTSTATUS validate_nt_acl_blob(TALLOC_CTX *mem_ctx,
406                                      vfs_handle_struct *handle,
407                                      files_struct *fsp,
408                                      const struct smb_filename *smb_fname,
409                                      const DATA_BLOB *blob,
410                                      struct security_descriptor **ppsd,
411                                      bool *psd_is_from_fs)
412 {
413         NTSTATUS status;
414         uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
415         uint16_t xattr_version = 0;
416         uint8_t hash[XATTR_SD_HASH_SIZE];
417         uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
418         uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
419         uint8_t sys_acl_hash_tmp[XATTR_SD_HASH_SIZE];
420         struct security_descriptor *psd = NULL;
421         struct security_descriptor *psd_blob = NULL;
422         struct security_descriptor *psd_fs = NULL;
423         char *sys_acl_blob_description = NULL;
424         DATA_BLOB sys_acl_blob = { 0 };
425         struct acl_common_config *config = NULL;
426
427         *ppsd = NULL;
428         *psd_is_from_fs = false;
429
430         SMB_VFS_HANDLE_GET_DATA(handle, config,
431                                 struct acl_common_config,
432                                 return NT_STATUS_UNSUCCESSFUL);
433
434         status = parse_acl_blob(blob,
435                                 mem_ctx,
436                                 &psd_blob,
437                                 &hash_type,
438                                 &xattr_version,
439                                 &hash[0],
440                                 &sys_acl_hash[0]);
441         if (!NT_STATUS_IS_OK(status)) {
442                 DBG_DEBUG("parse_acl_blob returned %s\n", nt_errstr(status));
443                 goto fail;
444         }
445
446         /* determine which type of xattr we got */
447         switch (xattr_version) {
448         case 1:
449         case 2:
450                 /* These xattr types are unilatteral, they do not
451                  * require confirmation of the hash.  In particular,
452                  * the NTVFS file server uses version 1, but
453                  * 'samba-tool ntacl' can set these as well */
454                 *ppsd = psd_blob;
455                 return NT_STATUS_OK;
456         case 3:
457         case 4:
458                 if (config->ignore_system_acls) {
459                         *ppsd = psd_blob;
460                         return NT_STATUS_OK;
461                 }
462
463                 break;
464         default:
465                 DBG_DEBUG("ACL blob revision mismatch (%u) for file %s\n",
466                           (unsigned int)hash_type, smb_fname->base_name);
467                 TALLOC_FREE(psd_blob);
468                 return NT_STATUS_OK;
469         }
470
471         /* determine which type of xattr we got */
472         if (hash_type != XATTR_SD_HASH_TYPE_SHA256) {
473                 DBG_DEBUG("ACL blob hash type (%u) unexpected for file %s\n",
474                           (unsigned int)hash_type, smb_fname->base_name);
475                 TALLOC_FREE(psd_blob);
476                 return NT_STATUS_OK;
477         }
478
479         /* determine which type of xattr we got */
480         switch (xattr_version) {
481         case 4:
482         {
483                 int ret;
484                 if (fsp) {
485                         /* Get the full underlying sd, then hash. */
486                         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
487                                                                fsp,
488                                                                mem_ctx,
489                                                                &sys_acl_blob_description,
490                                                                &sys_acl_blob);
491                 } else {
492                         /* Get the full underlying sd, then hash. */
493                         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle,
494                                                  smb_fname,
495                                                  mem_ctx,
496                                                  &sys_acl_blob_description,
497                                                  &sys_acl_blob);
498                 }
499
500                 /* If we fail to get the ACL blob (for some reason) then this
501                  * is not fatal, we just work based on the NT ACL only */
502                 if (ret == 0) {
503                         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash_tmp);
504                         if (!NT_STATUS_IS_OK(status)) {
505                                 goto fail;
506                         }
507
508                         TALLOC_FREE(sys_acl_blob_description);
509                         TALLOC_FREE(sys_acl_blob.data);
510
511                         if (memcmp(&sys_acl_hash[0], &sys_acl_hash_tmp[0], 
512                                    XATTR_SD_HASH_SIZE) == 0) {
513                                 /* Hash matches, return blob sd. */
514                                 DBG_DEBUG("blob hash matches for file %s\n",
515                                           smb_fname->base_name);
516                                 *ppsd = psd_blob;
517                                 return NT_STATUS_OK;
518                         }
519                 }
520
521                 /* Otherwise, fall though and see if the NT ACL hash matches */
522                 FALL_THROUGH;
523         }
524         case 3:
525                 /* Get the full underlying sd for the hash
526                    or to return as backup. */
527                 if (fsp) {
528                         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
529                                                           fsp,
530                                                           HASH_SECURITY_INFO,
531                                                           mem_ctx,
532                                                           &psd_fs);
533                 } else {
534                         status = SMB_VFS_NEXT_GET_NT_ACL(handle,
535                                                          smb_fname,
536                                                          HASH_SECURITY_INFO,
537                                                          mem_ctx,
538                                                          &psd_fs);
539                 }
540
541                 if (!NT_STATUS_IS_OK(status)) {
542                         DBG_DEBUG("get_next_acl for file %s returned %s\n",
543                                   smb_fname->base_name, nt_errstr(status));
544                         goto fail;
545                 }
546
547                 status = hash_sd_sha256(psd_fs, hash_tmp);
548                 if (!NT_STATUS_IS_OK(status)) {
549                         TALLOC_FREE(psd_blob);
550                         *ppsd = psd_fs;
551                         *psd_is_from_fs = true;
552                         return NT_STATUS_OK;
553                 }
554
555                 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
556                         /* Hash matches, return blob sd. */
557                         DBG_DEBUG("blob hash matches for file %s\n",
558                                   smb_fname->base_name);
559                         *ppsd = psd_blob;
560                         return NT_STATUS_OK;
561                 }
562
563                 /* Hash doesn't match, return underlying sd. */
564                 DBG_DEBUG("blob hash does not match for file %s - returning "
565                           "file system SD mapping.\n",
566                           smb_fname->base_name);
567
568                 if (DEBUGLEVEL >= 10) {
569                         DBG_DEBUG("acl for blob hash for %s is:\n",
570                                   smb_fname->base_name);
571                         NDR_PRINT_DEBUG(security_descriptor, psd_fs);
572                 }
573
574                 TALLOC_FREE(psd_blob);
575                 *ppsd = psd_fs;
576                 *psd_is_from_fs = true;
577         }
578
579         return NT_STATUS_OK;
580
581 fail:
582         TALLOC_FREE(psd);
583         TALLOC_FREE(psd_blob);
584         TALLOC_FREE(psd_fs);
585         TALLOC_FREE(sys_acl_blob_description);
586         TALLOC_FREE(sys_acl_blob.data);
587         return status;
588 }
589
590 static NTSTATUS stat_fsp_or_smb_fname(vfs_handle_struct *handle,
591                                       files_struct *fsp,
592                                       const struct smb_filename *smb_fname,
593                                       SMB_STRUCT_STAT *sbuf,
594                                       SMB_STRUCT_STAT **psbuf)
595 {
596         NTSTATUS status;
597         int ret;
598
599         if (fsp) {
600                 status = vfs_stat_fsp(fsp);
601                 if (!NT_STATUS_IS_OK(status)) {
602                         return status;
603                 }
604                 *psbuf = &fsp->fsp_name->st;
605         } else {
606                 /*
607                  * https://bugzilla.samba.org/show_bug.cgi?id=11249
608                  *
609                  * We are currently guaranteed that 'name' here is a
610                  * smb_fname->base_name, which *cannot* contain a stream name
611                  * (':'). vfs_stat_smb_fname() splits a name into a base name +
612                  * stream name, which when we get here we know we've already
613                  * done.  So we have to call the stat or lstat VFS calls
614                  * directly here. Else, a base_name that contains a ':' (from a
615                  * demangled name) will get split again.
616                  *
617                  * FIXME.
618                  * This uglyness will go away once smb_fname is fully plumbed
619                  * through the VFS.
620                  */
621                 ret = vfs_stat_smb_basename(handle->conn,
622                                             smb_fname,
623                                             sbuf);
624                 if (ret == -1) {
625                         return map_nt_error_from_unix(errno);
626                 }
627         }
628
629         return NT_STATUS_OK;
630 }
631
632 /*******************************************************************
633  Pull a DATA_BLOB from an xattr given a pathname.
634  If the hash doesn't match, or doesn't exist - return the underlying
635  filesystem sd.
636 *******************************************************************/
637
638 NTSTATUS get_nt_acl_common(
639         NTSTATUS (*get_acl_blob_fn)(TALLOC_CTX *ctx,
640                                     vfs_handle_struct *handle,
641                                     files_struct *fsp,
642                                     const struct smb_filename *smb_fname,
643                                     DATA_BLOB *pblob),
644         vfs_handle_struct *handle,
645         files_struct *fsp,
646         const struct smb_filename *smb_fname_in,
647         uint32_t security_info,
648         TALLOC_CTX *mem_ctx,
649         struct security_descriptor **ppdesc)
650 {
651         DATA_BLOB blob = data_blob_null;
652         NTSTATUS status;
653         struct security_descriptor *psd = NULL;
654         const struct smb_filename *smb_fname = NULL;
655         bool psd_is_from_fs = false;
656         struct acl_common_config *config = NULL;
657
658         SMB_VFS_HANDLE_GET_DATA(handle, config,
659                                 struct acl_common_config,
660                                 return NT_STATUS_UNSUCCESSFUL);
661
662         if (fsp && smb_fname_in == NULL) {
663                 smb_fname = fsp->fsp_name;
664         } else {
665                 smb_fname = smb_fname_in;
666         }
667
668         DBG_DEBUG("name=%s\n", smb_fname->base_name);
669
670         status = get_acl_blob_fn(mem_ctx, handle, fsp, smb_fname, &blob);
671         if (NT_STATUS_IS_OK(status)) {
672                 status = validate_nt_acl_blob(mem_ctx,
673                                               handle,
674                                               fsp,
675                                               smb_fname,
676                                               &blob,
677                                               &psd,
678                                               &psd_is_from_fs);
679                 TALLOC_FREE(blob.data);
680                 if (!NT_STATUS_IS_OK(status)) {
681                         DBG_DEBUG("ACL validation for [%s] failed\n",
682                                   smb_fname->base_name);
683                         goto fail;
684                 }
685         }
686
687         if (psd == NULL) {
688                 /* Get the full underlying sd, as we failed to get the
689                  * blob for the hash, or the revision/hash type wasn't
690                  * known */
691
692                 if (config->ignore_system_acls) {
693                         SMB_STRUCT_STAT sbuf;
694                         SMB_STRUCT_STAT *psbuf = &sbuf;
695
696                         status = stat_fsp_or_smb_fname(handle, fsp, smb_fname,
697                                                        &sbuf, &psbuf);
698                         if (!NT_STATUS_IS_OK(status)) {
699                                 goto fail;
700                         }
701
702                         status = make_default_filesystem_acl(
703                                 mem_ctx,
704                                 config->default_acl_style,
705                                 smb_fname->base_name,
706                                 psbuf,
707                                 &psd);
708                         if (!NT_STATUS_IS_OK(status)) {
709                                 goto fail;
710                         }
711                 } else {
712                         if (fsp) {
713                                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
714                                                                   fsp,
715                                                                   security_info,
716                                                                   mem_ctx,
717                                                                   &psd);
718                         } else {
719                                 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
720                                                                  smb_fname,
721                                                                  security_info,
722                                                                  mem_ctx,
723                                                                  &psd);
724                         }
725
726                         if (!NT_STATUS_IS_OK(status)) {
727                                 DBG_DEBUG("get_next_acl for file %s "
728                                           "returned %s\n",
729                                           smb_fname->base_name,
730                                           nt_errstr(status));
731                                 goto fail;
732                         }
733
734                         psd_is_from_fs = true;
735                 }
736         }
737
738         if (psd_is_from_fs) {
739                 SMB_STRUCT_STAT sbuf;
740                 SMB_STRUCT_STAT *psbuf = &sbuf;
741                 bool is_directory = false;
742
743                 /*
744                  * We're returning the underlying ACL from the
745                  * filesystem. If it's a directory, and has no
746                  * inheritable ACE entries we have to fake them.
747                  */
748
749                 status = stat_fsp_or_smb_fname(handle, fsp, smb_fname,
750                                                &sbuf, &psbuf);
751                 if (!NT_STATUS_IS_OK(status)) {
752                         goto fail;
753                 }
754
755                 is_directory = S_ISDIR(psbuf->st_ex_mode);
756
757                 if (is_directory && !sd_has_inheritable_components(psd, true)) {
758                         status = add_directory_inheritable_components(
759                                 handle,
760                                 smb_fname->base_name,
761                                 psbuf,
762                                 psd);
763                         if (!NT_STATUS_IS_OK(status)) {
764                                 goto fail;
765                         }
766                 }
767
768                 /*
769                  * The underlying POSIX module always sets the
770                  * ~SEC_DESC_DACL_PROTECTED bit, as ACLs can't be inherited in
771                  * this way under POSIX. Remove it for Windows-style ACLs.
772                  */
773                 psd->type &= ~SEC_DESC_DACL_PROTECTED;
774         }
775
776         if (!(security_info & SECINFO_OWNER)) {
777                 psd->owner_sid = NULL;
778         }
779         if (!(security_info & SECINFO_GROUP)) {
780                 psd->group_sid = NULL;
781         }
782         if (!(security_info & SECINFO_DACL)) {
783                 psd->type &= ~SEC_DESC_DACL_PRESENT;
784                 psd->dacl = NULL;
785         }
786         if (!(security_info & SECINFO_SACL)) {
787                 psd->type &= ~SEC_DESC_SACL_PRESENT;
788                 psd->sacl = NULL;
789         }
790
791         if (DEBUGLEVEL >= 10) {
792                 DBG_DEBUG("returning acl for %s is:\n",
793                           smb_fname->base_name);
794                 NDR_PRINT_DEBUG(security_descriptor, psd);
795         }
796
797         *ppdesc = psd;
798
799         return NT_STATUS_OK;
800
801 fail:
802         TALLOC_FREE(psd);
803         return status;
804 }
805
806 /*********************************************************************
807  Set the underlying ACL (e.g. POSIX ACLS, POSIX owner, etc)
808 *********************************************************************/
809 static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
810                                    struct security_descriptor *psd,
811                                    uint32_t security_info_sent,
812                                    bool chown_needed)
813 {
814         NTSTATUS status;
815         const struct security_token *token = NULL;
816
817         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
818         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
819                 return status;
820         }
821
822         /* We got access denied here. If we're already root,
823            or we didn't need to do a chown, or the fsp isn't
824            open with WRITE_OWNER access, just return. */
825         if (get_current_uid(handle->conn) == 0 || chown_needed == false ||
826             !(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
827                 return NT_STATUS_ACCESS_DENIED;
828         }
829
830         /*
831          * Only allow take-ownership, not give-ownership. That's the way Windows
832          * implements SEC_STD_WRITE_OWNER. MS-FSA 2.1.5.16 just states: If
833          * InputBuffer.OwnerSid is not a valid owner SID for a file in the
834          * objectstore, as determined in an implementation specific manner, the
835          * object store MUST return STATUS_INVALID_OWNER.
836          */
837         token = get_current_nttok(fsp->conn);
838         if (!security_token_is_sid(token, psd->owner_sid)) {
839                 return NT_STATUS_INVALID_OWNER;
840         }
841
842         DBG_DEBUG("overriding chown on file %s for sid %s\n",
843                    fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid));
844
845         /* Ok, we failed to chown and we have
846            SEC_STD_WRITE_OWNER access - override. */
847         become_root();
848         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
849         unbecome_root();
850
851         return status;
852 }
853
854 /*********************************************************************
855  Store a v3 security descriptor
856 *********************************************************************/
857 static NTSTATUS store_v3_blob(
858         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
859                                           files_struct *fsp,
860                                           DATA_BLOB *pblob),
861         vfs_handle_struct *handle, files_struct *fsp,
862         struct security_descriptor *psd,
863         struct security_descriptor *pdesc_next,
864         uint8_t hash[XATTR_SD_HASH_SIZE])
865 {
866         NTSTATUS status;
867         DATA_BLOB blob;
868
869         if (DEBUGLEVEL >= 10) {
870                 DBG_DEBUG("storing xattr sd for file %s\n",
871                           fsp_str_dbg(fsp));
872                 NDR_PRINT_DEBUG(
873                     security_descriptor,
874                     discard_const_p(struct security_descriptor, psd));
875
876                 if (pdesc_next != NULL) {
877                         DBG_DEBUG("storing xattr sd based on \n");
878                         NDR_PRINT_DEBUG(
879                             security_descriptor,
880                             discard_const_p(struct security_descriptor,
881                                             pdesc_next));
882                 } else {
883                         DBG_DEBUG("ignoring underlying sd\n");
884                 }
885         }
886         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
887         if (!NT_STATUS_IS_OK(status)) {
888                 DBG_DEBUG("create_acl_blob failed\n");
889                 return status;
890         }
891
892         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
893         return status;
894 }
895
896 /*********************************************************************
897  Store a security descriptor given an fsp.
898 *********************************************************************/
899
900 NTSTATUS fset_nt_acl_common(
901         NTSTATUS (*get_acl_blob_fn)(TALLOC_CTX *ctx,
902                                     vfs_handle_struct *handle,
903                                     files_struct *fsp,
904                                     const struct smb_filename *smb_fname,
905                                     DATA_BLOB *pblob),
906         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
907                                           files_struct *fsp,
908                                           DATA_BLOB *pblob),
909         const char *module_name,
910         vfs_handle_struct *handle, files_struct *fsp,
911         uint32_t security_info_sent,
912         const struct security_descriptor *orig_psd)
913 {
914         NTSTATUS status;
915         int ret;
916         DATA_BLOB blob, sys_acl_blob;
917         struct security_descriptor *pdesc_next = NULL;
918         struct security_descriptor *psd = NULL;
919         uint8_t hash[XATTR_SD_HASH_SIZE];
920         uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
921         bool chown_needed = false;
922         char *sys_acl_description;
923         TALLOC_CTX *frame = talloc_stackframe();
924         bool ignore_file_system_acl = lp_parm_bool(
925             SNUM(handle->conn), module_name, "ignore system acls", false);
926
927         if (DEBUGLEVEL >= 10) {
928                 DBG_DEBUG("incoming sd for file %s\n", fsp_str_dbg(fsp));
929                 NDR_PRINT_DEBUG(security_descriptor,
930                         discard_const_p(struct security_descriptor, orig_psd));
931         }
932
933         status = get_nt_acl_common(get_acl_blob_fn, handle, fsp,
934                         NULL,
935                         SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
936                                      frame,
937                         &psd);
938
939         if (!NT_STATUS_IS_OK(status)) {
940                 TALLOC_FREE(frame);
941                 return status;
942         }
943
944         psd->revision = orig_psd->revision;
945         /* All our SD's are self relative. */
946         psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
947
948         if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
949                 if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) {
950                         /* We're changing the owner. */
951                         chown_needed = true;
952                 }
953                 psd->owner_sid = orig_psd->owner_sid;
954         }
955         if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
956                 if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) {
957                         /* We're changing the group. */
958                         chown_needed = true;
959                 }
960                 psd->group_sid = orig_psd->group_sid;
961         }
962         if (security_info_sent & SECINFO_DACL) {
963                 if (security_descriptor_with_ms_nfs(orig_psd)) {
964                         /*
965                          * If the sd contains a MS NFS SID, do
966                          * nothing, it's a chmod() request from OS X
967                          * with AAPL context.
968                          */
969                         TALLOC_FREE(frame);
970                         return NT_STATUS_OK;
971                 }
972                 psd->dacl = orig_psd->dacl;
973                 psd->type |= SEC_DESC_DACL_PRESENT;
974         }
975         if (security_info_sent & SECINFO_SACL) {
976                 psd->sacl = orig_psd->sacl;
977                 psd->type |= SEC_DESC_SACL_PRESENT;
978         }
979
980         if (ignore_file_system_acl) {
981                 if (chown_needed) {
982                         /* send only ownership stuff to lower layer */
983                         security_info_sent &= (SECINFO_OWNER | SECINFO_GROUP);
984                         status = set_underlying_acl(handle, fsp, psd,
985                                                     security_info_sent, true);
986                         if (!NT_STATUS_IS_OK(status)) {
987                                 TALLOC_FREE(frame);
988                                 return status;
989                         }
990                 }
991                 ZERO_ARRAY(hash);
992                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
993                                        NULL, hash);
994
995                 TALLOC_FREE(frame);
996                 return status;
997         }
998
999         status = set_underlying_acl(handle, fsp, psd, security_info_sent,
1000                                     chown_needed);
1001         if (!NT_STATUS_IS_OK(status)) {
1002                 TALLOC_FREE(frame);
1003                 return status;
1004         }
1005
1006         /* Get the full underlying sd, then hash. */
1007         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
1008                                           fsp,
1009                                           HASH_SECURITY_INFO,
1010                                           frame,
1011                                           &pdesc_next);
1012
1013         if (!NT_STATUS_IS_OK(status)) {
1014                 TALLOC_FREE(frame);
1015                 return status;
1016         }
1017
1018         status = hash_sd_sha256(pdesc_next, hash);
1019         if (!NT_STATUS_IS_OK(status)) {
1020                 TALLOC_FREE(frame);
1021                 return status;
1022         }
1023
1024         /* Get the full underlying sd, then hash. */
1025         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
1026                                                fsp,
1027                                                frame,
1028                                                &sys_acl_description,
1029                                                &sys_acl_blob);
1030
1031         /* If we fail to get the ACL blob (for some reason) then this
1032          * is not fatal, we just work based on the NT ACL only */
1033         if (ret != 0) {
1034                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
1035                                        pdesc_next, hash);
1036
1037                 TALLOC_FREE(frame);
1038                 return status;
1039         }
1040
1041         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash);
1042         if (!NT_STATUS_IS_OK(status)) {
1043                 TALLOC_FREE(frame);
1044                 return status;
1045         }
1046
1047         if (DEBUGLEVEL >= 10) {
1048                 DBG_DEBUG("storing xattr sd for file %s based on system ACL\n",
1049                           fsp_str_dbg(fsp));
1050                 NDR_PRINT_DEBUG(security_descriptor,
1051                                 discard_const_p(struct security_descriptor, psd));
1052
1053                 DBG_DEBUG("storing hash in xattr sd based on system ACL and:\n");
1054                 NDR_PRINT_DEBUG(security_descriptor,
1055                                 discard_const_p(struct security_descriptor, pdesc_next));
1056         }
1057
1058         /* We store hashes of both the sys ACL blob and the NT
1059          * security desciptor mapped from that ACL so as to improve
1060          * our chances against some inadvertant change breaking the
1061          * hash used */
1062         status = create_sys_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash, 
1063                                      sys_acl_description, sys_acl_hash);
1064         if (!NT_STATUS_IS_OK(status)) {
1065                 DBG_DEBUG("create_sys_acl_blob failed\n");
1066                 TALLOC_FREE(frame);
1067                 return status;
1068         }
1069
1070         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
1071
1072         TALLOC_FREE(frame);
1073         return status;
1074 }
1075
1076 static int acl_common_remove_object(vfs_handle_struct *handle,
1077                                         const struct smb_filename *smb_fname,
1078                                         bool is_directory)
1079 {
1080         connection_struct *conn = handle->conn;
1081         struct file_id id;
1082         files_struct *fsp = NULL;
1083         int ret = 0;
1084         char *parent_dir = NULL;
1085         const char *final_component = NULL;
1086         struct smb_filename local_fname = {0};
1087         struct smb_filename parent_dir_fname = {0};
1088         int saved_errno = 0;
1089         struct smb_filename *saved_dir_fname = NULL;
1090
1091         saved_dir_fname = vfs_GetWd(talloc_tos(),conn);
1092         if (saved_dir_fname == NULL) {
1093                 saved_errno = errno;
1094                 goto out;
1095         }
1096
1097         if (!parent_dirname(talloc_tos(), smb_fname->base_name,
1098                         &parent_dir, &final_component)) {
1099                 saved_errno = ENOMEM;
1100                 goto out;
1101         }
1102
1103         DBG_DEBUG("removing %s %s/%s\n", is_directory ? "directory" : "file",
1104                   parent_dir, final_component);
1105
1106         parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
1107
1108         /* cd into the parent dir to pin it. */
1109         ret = vfs_ChDir(conn, &parent_dir_fname);
1110         if (ret == -1) {
1111                 saved_errno = errno;
1112                 goto out;
1113         }
1114
1115         local_fname.base_name = discard_const_p(char, final_component);
1116
1117         /* Must use lstat here. */
1118         ret = SMB_VFS_LSTAT(conn, &local_fname);
1119         if (ret == -1) {
1120                 saved_errno = errno;
1121                 goto out;
1122         }
1123
1124         /* Ensure we have this file open with DELETE access. */
1125         id = vfs_file_id_from_sbuf(conn, &local_fname.st);
1126         for (fsp = file_find_di_first(conn->sconn, id); fsp;
1127                      fsp = file_find_di_next(fsp)) {
1128                 if (fsp->access_mask & DELETE_ACCESS &&
1129                                 fsp->delete_on_close) {
1130                         /* We did open this for delete,
1131                          * allow the delete as root.
1132                          */
1133                         break;
1134                 }
1135         }
1136
1137         if (!fsp) {
1138                 DBG_DEBUG("%s %s/%s not an open file\n",
1139                           is_directory ? "directory" : "file",
1140                           parent_dir, final_component);
1141                 saved_errno = EACCES;
1142                 goto out;
1143         }
1144
1145         become_root();
1146         if (is_directory) {
1147                 ret = SMB_VFS_NEXT_RMDIR(handle, &local_fname);
1148         } else {
1149                 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
1150         }
1151         unbecome_root();
1152
1153         if (ret == -1) {
1154                 saved_errno = errno;
1155         }
1156
1157   out:
1158
1159         TALLOC_FREE(parent_dir);
1160
1161         if (saved_dir_fname) {
1162                 vfs_ChDir(conn, saved_dir_fname);
1163                 TALLOC_FREE(saved_dir_fname);
1164         }
1165         if (saved_errno) {
1166                 errno = saved_errno;
1167         }
1168         return ret;
1169 }
1170
1171 int rmdir_acl_common(struct vfs_handle_struct *handle,
1172                      const struct smb_filename *smb_fname)
1173 {
1174         int ret;
1175
1176         /* Try the normal rmdir first. */
1177         ret = SMB_VFS_NEXT_RMDIR(handle, smb_fname);
1178         if (ret == 0) {
1179                 return 0;
1180         }
1181         if (errno == EACCES || errno == EPERM) {
1182                 /* Failed due to access denied,
1183                    see if we need to root override. */
1184                 return acl_common_remove_object(handle,
1185                                                 smb_fname,
1186                                                 true);
1187         }
1188
1189         DBG_DEBUG("unlink of %s failed %s\n",
1190                   smb_fname->base_name,
1191                   strerror(errno));
1192         return -1;
1193 }
1194
1195 int unlink_acl_common(struct vfs_handle_struct *handle,
1196                         const struct smb_filename *smb_fname)
1197 {
1198         int ret;
1199
1200         /* Try the normal unlink first. */
1201         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1202         if (ret == 0) {
1203                 return 0;
1204         }
1205         if (errno == EACCES || errno == EPERM) {
1206                 /* Failed due to access denied,
1207                    see if we need to root override. */
1208
1209                 /* Don't do anything fancy for streams. */
1210                 if (smb_fname->stream_name) {
1211                         return -1;
1212                 }
1213                 return acl_common_remove_object(handle,
1214                                         smb_fname,
1215                                         false);
1216         }
1217
1218         DBG_DEBUG("unlink of %s failed %s\n",
1219                   smb_fname->base_name,
1220                   strerror(errno));
1221         return -1;
1222 }
1223
1224 int chmod_acl_module_common(struct vfs_handle_struct *handle,
1225                             const struct smb_filename *smb_fname,
1226                             mode_t mode)
1227 {
1228         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1229                 /* Only allow this on POSIX pathnames. */
1230                 return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1231         }
1232         return 0;
1233 }
1234
1235 int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1236                              struct files_struct *fsp, mode_t mode)
1237 {
1238         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1239                 /* Only allow this on POSIX opens. */
1240                 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1241         }
1242         return 0;
1243 }
1244
1245 int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1246                                 const struct smb_filename *smb_fname,
1247                                 mode_t mode)
1248 {
1249         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1250                 /* Only allow this on POSIX pathnames. */
1251                 return SMB_VFS_NEXT_CHMOD_ACL(handle, smb_fname, mode);
1252         }
1253         return 0;
1254 }
1255
1256 int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1257                                  struct files_struct *fsp, mode_t mode)
1258 {
1259         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1260                 /* Only allow this on POSIX opens. */
1261                 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
1262         }
1263         return 0;
1264 }