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