Fix hash function in acl_xattr to be SHA256, make
[samba.git] / source3 / modules / vfs_acl_xattr.c
1 /*
2  * Store Windows ACLs in xattrs.
3  *
4  * Copyright (C) Volker Lendecke, 2008
5  * Copyright (C) Jeremy Allison, 2008
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* NOTE: This is an experimental module, not yet finished. JRA. */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/xattr.h"
25 #include "librpc/gen_ndr/ndr_xattr.h"
26 #include "../lib/crypto/crypto.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_VFS
30
31 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
32                         DATA_BLOB *pblob,
33                         uint16_t hash_type,
34                         uint8_t hash[XATTR_SD_HASH_SIZE]);
35
36 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
37                                 GROUP_SECURITY_INFORMATION | \
38                                 DACL_SECURITY_INFORMATION | \
39                                 SACL_SECURITY_INFORMATION)
40
41 /*******************************************************************
42  Hash a security descriptor.
43 *******************************************************************/
44
45 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
46                         uint8_t hash[XATTR_SD_HASH_SIZE])
47 {
48         DATA_BLOB blob;
49         SHA256_CTX tctx;
50         NTSTATUS status;
51
52         memset(hash, '\0', XATTR_SD_HASH_SIZE);
53         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
54         if (!NT_STATUS_IS_OK(status)) {
55                 return status;
56         }
57
58         SHA256_Init(&tctx);
59         SHA256_Update(&tctx, blob.data, blob.length);
60         SHA256_Final(hash, &tctx);
61
62         return NT_STATUS_OK;
63 }
64
65 /*******************************************************************
66  Parse out a struct security_descriptor from a DATA_BLOB.
67 *******************************************************************/
68
69 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
70                                 struct security_descriptor **ppdesc,
71                                 uint16_t *p_hash_type,
72                                 uint8_t hash[XATTR_SD_HASH_SIZE])
73 {
74         TALLOC_CTX *ctx = talloc_tos();
75         struct xattr_NTACL xacl;
76         enum ndr_err_code ndr_err;
77         size_t sd_size;
78
79         ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
80                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
81
82         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
83                 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
84                         ndr_errstr(ndr_err)));
85                 return ndr_map_error2ntstatus(ndr_err);;
86         }
87
88         switch (xacl.version) {
89                 case 2:
90                         *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
91                                         xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
92                                         xacl.info.sd_hs2->sd->owner_sid,
93                                         xacl.info.sd_hs2->sd->group_sid,
94                                         xacl.info.sd_hs2->sd->sacl,
95                                         xacl.info.sd_hs2->sd->dacl,
96                                         &sd_size);
97                         /* No hash - null out. */
98                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
99                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
100                         break;
101                 case 3:
102                         *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
103                                         xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
104                                         xacl.info.sd_hs3->sd->owner_sid,
105                                         xacl.info.sd_hs3->sd->group_sid,
106                                         xacl.info.sd_hs3->sd->sacl,
107                                         xacl.info.sd_hs3->sd->dacl,
108                                         &sd_size);
109                         *p_hash_type = xacl.info.sd_hs3->hash_type;
110                         /* Current version 3. */
111                         memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
112                         break;
113                 default:
114                         return NT_STATUS_REVISION_MISMATCH;
115         }
116
117         TALLOC_FREE(xacl.info.sd);
118
119         return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
120 }
121
122 /*******************************************************************
123  Pull a security descriptor into a DATA_BLOB from a xattr.
124 *******************************************************************/
125
126 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
127                         vfs_handle_struct *handle,
128                         files_struct *fsp,
129                         const char *name,
130                         DATA_BLOB *pblob)
131 {
132         size_t size = 1024;
133         uint8_t *val = NULL;
134         uint8_t *tmp;
135         ssize_t sizeret;
136         int saved_errno = 0;
137
138         ZERO_STRUCTP(pblob);
139
140   again:
141
142         tmp = TALLOC_REALLOC_ARRAY(ctx, val, uint8_t, size);
143         if (tmp == NULL) {
144                 TALLOC_FREE(val);
145                 return NT_STATUS_NO_MEMORY;
146         }
147         val = tmp;
148
149         become_root();
150         if (fsp && fsp->fh->fd != -1) {
151                 sizeret = SMB_VFS_FGETXATTR(fsp, XATTR_NTACL_NAME, val, size);
152         } else {
153                 sizeret = SMB_VFS_GETXATTR(handle->conn, name,
154                                         XATTR_NTACL_NAME, val, size);
155         }
156         if (sizeret == -1) {
157                 saved_errno = errno;
158         }
159         unbecome_root();
160
161         /* Max ACL size is 65536 bytes. */
162         if (sizeret == -1) {
163                 errno = saved_errno;
164                 if ((errno == ERANGE) && (size != 65536)) {
165                         /* Too small, try again. */
166                         size = 65536;
167                         goto again;
168                 }
169
170                 /* Real error - exit here. */
171                 TALLOC_FREE(val);
172                 return map_nt_error_from_unix(errno);
173         }
174
175         pblob->data = val;
176         pblob->length = sizeret;
177         return NT_STATUS_OK;
178 }
179
180 /*******************************************************************
181  Create a DATA_BLOB from a security descriptor.
182 *******************************************************************/
183
184 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
185                         DATA_BLOB *pblob,
186                         uint16_t hash_type,
187                         uint8_t hash[XATTR_SD_HASH_SIZE])
188 {
189         struct xattr_NTACL xacl;
190         struct security_descriptor_hash_v3 sd_hs3;
191         enum ndr_err_code ndr_err;
192         TALLOC_CTX *ctx = talloc_tos();
193
194         ZERO_STRUCT(xacl);
195         ZERO_STRUCT(sd_hs3);
196
197         xacl.version = 3;
198         xacl.info.sd_hs3 = &sd_hs3;
199         xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
200         xacl.info.sd_hs3->hash_type = hash_type;
201         memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
202
203         ndr_err = ndr_push_struct_blob(
204                         pblob, ctx, NULL, &xacl,
205                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
206
207         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
208                 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
209                         ndr_errstr(ndr_err)));
210                 return ndr_map_error2ntstatus(ndr_err);;
211         }
212
213         return NT_STATUS_OK;
214 }
215
216 /*******************************************************************
217  Store a DATA_BLOB into an xattr given an fsp pointer.
218 *******************************************************************/
219
220 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
221                                 files_struct *fsp,
222                                 DATA_BLOB *pblob)
223 {
224         int ret;
225         int saved_errno = 0;
226
227         DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
228                   (unsigned int)pblob->length, fsp_str_dbg(fsp)));
229
230         become_root();
231         if (fsp->fh->fd != -1) {
232                 ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
233                         pblob->data, pblob->length, 0);
234         } else {
235                 ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
236                                 XATTR_NTACL_NAME,
237                                 pblob->data, pblob->length, 0);
238         }
239         if (ret) {
240                 saved_errno = errno;
241         }
242         unbecome_root();
243         if (ret) {
244                 errno = saved_errno;
245                 DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s"
246                         "with error %s\n",
247                         fsp_str_dbg(fsp),
248                         strerror(errno) ));
249                 return map_nt_error_from_unix(errno);
250         }
251         return NT_STATUS_OK;
252 }
253
254 /*******************************************************************
255  Store a DATA_BLOB into an xattr given a pathname.
256 *******************************************************************/
257
258 static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
259                                         const char *fname,
260                                         DATA_BLOB *pblob)
261 {
262         connection_struct *conn = handle->conn;
263         int ret;
264         int saved_errno = 0;
265
266         DEBUG(10,("store_acl_blob_pathname: storing blob "
267                         "length %u on file %s\n",
268                         (unsigned int)pblob->length, fname));
269
270         become_root();
271         ret = SMB_VFS_SETXATTR(conn, fname,
272                                 XATTR_NTACL_NAME,
273                                 pblob->data, pblob->length, 0);
274         if (ret) {
275                 saved_errno = errno;
276         }
277         unbecome_root();
278         if (ret) {
279                 errno = saved_errno;
280                 DEBUG(5, ("store_acl_blob_pathname: setting attr failed "
281                         "for file %s with error %s\n",
282                         fname,
283                         strerror(errno) ));
284                 return map_nt_error_from_unix(errno);
285         }
286         return NT_STATUS_OK;
287 }
288
289 /*******************************************************************
290  Store a DATA_BLOB into an xattr given a pathname.
291 *******************************************************************/
292
293 static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
294                                         files_struct *fsp,
295                                         const char *name,
296                                         uint32_t security_info,
297                                         struct security_descriptor **ppdesc)
298 {
299         DATA_BLOB blob;
300         NTSTATUS status;
301         uint16_t hash_type;
302         uint8_t hash[XATTR_SD_HASH_SIZE];
303         uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
304         struct security_descriptor *pdesc_next = NULL;
305
306         if (fsp && name == NULL) {
307                 name = fsp->fsp_name->base_name;
308         }
309
310         DEBUG(10, ("get_nt_acl_xattr_internal: name=%s\n", name));
311
312         status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
313         if (!NT_STATUS_IS_OK(status)) {
314                 DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status)));
315                 return status;
316         }
317
318         status = parse_acl_blob(&blob, ppdesc,
319                                 &hash_type, &hash[0]);
320         if (!NT_STATUS_IS_OK(status)) {
321                 DEBUG(10, ("parse_acl_blob returned %s\n",
322                                 nt_errstr(status)));
323                 return status;
324         }
325
326         /* Ensure the hash type is one we know. */
327         switch (hash_type) {
328                 case XATTR_SD_HASH_TYPE_NONE:
329                         /* No hash, goto return blob sd. */
330                         goto out;
331                 case XATTR_SD_HASH_TYPE_SHA256:
332                         break;
333                 default:
334                         return NT_STATUS_REVISION_MISMATCH;
335         }
336
337         /* Get the full underlying sd, then hash. */
338         if (fsp) {
339                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
340                                 fsp,
341                                 HASH_SECURITY_INFO,
342                                 &pdesc_next);
343         } else {
344                 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
345                                 name,
346                                 HASH_SECURITY_INFO,
347                                 &pdesc_next);
348         }
349
350         if (!NT_STATUS_IS_OK(status)) {
351                 goto out;
352         }
353
354         status = hash_sd_sha256(pdesc_next, hash_tmp);
355         if (!NT_STATUS_IS_OK(status)) {
356                 goto out;
357         }
358
359         if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
360                 TALLOC_FREE(pdesc_next);
361                 /* Hash matches, return blob sd. */
362                 goto out;
363         }
364
365         /* Hash doesn't match, return underlying sd. */
366
367         if (!(security_info & OWNER_SECURITY_INFORMATION)) {
368                 pdesc_next->owner_sid = NULL;
369         }
370         if (!(security_info & GROUP_SECURITY_INFORMATION)) {
371                 pdesc_next->group_sid = NULL;
372         }
373         if (!(security_info & DACL_SECURITY_INFORMATION)) {
374                 pdesc_next->dacl = NULL;
375         }
376         if (!(security_info & SACL_SECURITY_INFORMATION)) {
377                 pdesc_next->sacl = NULL;
378         }
379
380         TALLOC_FREE(*ppdesc);
381         *ppdesc = pdesc_next;
382
383   out:
384
385         if (!(security_info & OWNER_SECURITY_INFORMATION)) {
386                 (*ppdesc)->owner_sid = NULL;
387         }
388         if (!(security_info & GROUP_SECURITY_INFORMATION)) {
389                 (*ppdesc)->group_sid = NULL;
390         }
391         if (!(security_info & DACL_SECURITY_INFORMATION)) {
392                 (*ppdesc)->dacl = NULL;
393         }
394         if (!(security_info & SACL_SECURITY_INFORMATION)) {
395                 (*ppdesc)->sacl = NULL;
396         }
397
398         TALLOC_FREE(blob.data);
399         return status;
400 }
401
402 /*********************************************************************
403  Create a default security descriptor for a file in case no inheritance
404  exists. All permissions to the owner and SYSTEM.
405 *********************************************************************/
406
407 static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
408                                                 SMB_STRUCT_STAT *psbuf)
409 {
410         struct dom_sid owner_sid, group_sid;
411         size_t sd_size;
412         struct security_ace *pace = NULL;
413         struct security_acl *pacl = NULL;
414
415         uid_to_sid(&owner_sid, psbuf->st_ex_uid);
416         gid_to_sid(&group_sid, psbuf->st_ex_gid);
417
418         pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
419         if (!pace) {
420                 return NULL;
421         }
422
423         init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
424                         SEC_RIGHTS_FILE_ALL, 0);
425         init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
426                         SEC_RIGHTS_FILE_ALL, 0);
427
428         pacl = make_sec_acl(mem_ctx,
429                                 NT4_ACL_REVISION,
430                                 2,
431                                 pace);
432         if (!pacl) {
433                 return NULL;
434         }
435         return make_sec_desc(mem_ctx,
436                         SECURITY_DESCRIPTOR_REVISION_1,
437                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
438                         &owner_sid,
439                         &group_sid,
440                         NULL,
441                         pacl,
442                         &sd_size);
443 }
444
445 /*********************************************************************
446 *********************************************************************/
447
448 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
449                                         struct smb_filename *smb_fname,
450                                         files_struct *fsp,
451                                         bool container)
452 {
453         TALLOC_CTX *ctx = talloc_tos();
454         NTSTATUS status;
455         struct security_descriptor *parent_desc = NULL;
456         struct security_descriptor *psd = NULL;
457         struct security_descriptor *pdesc_next = NULL;
458         DATA_BLOB blob;
459         size_t size;
460         char *parent_name;
461         uint8_t hash[XATTR_SD_HASH_SIZE];
462
463         if (!parent_dirname(ctx, smb_fname->base_name, &parent_name, NULL)) {
464                 return NT_STATUS_NO_MEMORY;
465         }
466
467         DEBUG(10,("inherit_new_acl: check directory %s\n",
468                         parent_name));
469
470         status = get_nt_acl_xattr_internal(handle,
471                                         NULL,
472                                         parent_name,
473                                         (OWNER_SECURITY_INFORMATION |
474                                          GROUP_SECURITY_INFORMATION |
475                                          DACL_SECURITY_INFORMATION),
476                                         &parent_desc);
477         if (NT_STATUS_IS_OK(status)) {
478                 /* Create an inherited descriptor from the parent. */
479
480                 if (DEBUGLEVEL >= 10) {
481                         DEBUG(10,("inherit_new_acl: parent acl is:\n"));
482                         NDR_PRINT_DEBUG(security_descriptor, parent_desc);
483                 }
484
485                 status = se_create_child_secdesc(ctx,
486                                 &psd,
487                                 &size,
488                                 parent_desc,
489                                 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
490                                 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
491                                 container);
492                 if (!NT_STATUS_IS_OK(status)) {
493                         return status;
494                 }
495
496                 if (DEBUGLEVEL >= 10) {
497                         DEBUG(10,("inherit_new_acl: child acl is:\n"));
498                         NDR_PRINT_DEBUG(security_descriptor, psd);
499                 }
500
501         } else {
502                 DEBUG(10,("inherit_new_acl: directory %s failed "
503                         "to get acl %s\n",
504                         parent_name,
505                         nt_errstr(status) ));
506         }
507
508         if (!psd || psd->dacl == NULL) {
509                 int ret;
510
511                 TALLOC_FREE(psd);
512                 if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
513                         ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
514                 } else {
515                         if (fsp && fsp->posix_open) {
516                                 ret = SMB_VFS_LSTAT(handle->conn, smb_fname);
517                         } else {
518                                 ret = SMB_VFS_STAT(handle->conn, smb_fname);
519                         }
520                 }
521                 if (ret == -1) {
522                         return map_nt_error_from_unix(errno);
523                 }
524                 psd = default_file_sd(ctx, &smb_fname->st);
525                 if (!psd) {
526                         return NT_STATUS_NO_MEMORY;
527                 }
528
529                 if (DEBUGLEVEL >= 10) {
530                         DEBUG(10,("inherit_new_acl: default acl is:\n"));
531                         NDR_PRINT_DEBUG(security_descriptor, psd);
532                 }
533         }
534
535         /* Object exists. Read the current SD to get the hash. */
536         if (fsp) {
537                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
538                                 fsp,
539                                 HASH_SECURITY_INFO,
540                                 &pdesc_next);
541         } else {
542                 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
543                                 smb_fname->base_name,
544                                 HASH_SECURITY_INFO,
545                                 &pdesc_next);
546         }
547
548         if (!NT_STATUS_IS_OK(status)) {
549                 return status;
550         }
551
552         status = hash_sd_sha256(pdesc_next, hash);
553         if (!NT_STATUS_IS_OK(status)) {
554                 return status;
555         }
556         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
557         if (!NT_STATUS_IS_OK(status)) {
558                 return status;
559         }
560         if (fsp) {
561                 return store_acl_blob_fsp(handle, fsp, &blob);
562         } else {
563                 return store_acl_blob_pathname(handle, smb_fname->base_name,
564                                                &blob);
565         }
566 }
567
568 /*********************************************************************
569  Check ACL on open. For new files inherit from parent directory.
570 *********************************************************************/
571
572 static int open_acl_xattr(vfs_handle_struct *handle,
573                                         struct smb_filename *smb_fname,
574                                         files_struct *fsp,
575                                         int flags,
576                                         mode_t mode)
577 {
578         uint32_t access_granted = 0;
579         struct security_descriptor *pdesc = NULL;
580         bool file_existed = true;
581         char *fname = NULL;
582         NTSTATUS status;
583
584         if (fsp->base_fsp) {
585                 /* Stream open. Base filename open already did the ACL check. */
586                 DEBUG(10,("open_acl_xattr: stream open on %s\n",
587                         smb_fname_str_dbg(smb_fname) ));
588                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
589         }
590
591         status = get_full_smb_filename(talloc_tos(), smb_fname,
592                                        &fname);
593         if (!NT_STATUS_IS_OK(status)) {
594                 errno = map_errno_from_nt_status(status);
595                 return -1;
596         }
597
598         status = get_nt_acl_xattr_internal(handle,
599                                         NULL,
600                                         fname,
601                                         (OWNER_SECURITY_INFORMATION |
602                                          GROUP_SECURITY_INFORMATION |
603                                          DACL_SECURITY_INFORMATION),
604                                         &pdesc);
605         if (NT_STATUS_IS_OK(status)) {
606                 /* See if we can access it. */
607                 status = smb1_file_se_access_check(pdesc,
608                                         handle->conn->server_info->ptok,
609                                         fsp->access_mask,
610                                         &access_granted);
611                 if (!NT_STATUS_IS_OK(status)) {
612                         DEBUG(10,("open_acl_xattr: file %s open "
613                                 "refused with error %s\n",
614                                 smb_fname_str_dbg(smb_fname),
615                                 nt_errstr(status) ));
616                         errno = map_errno_from_nt_status(status);
617                         return -1;
618                 }
619         } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
620                 file_existed = false;
621         }
622
623         DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
624                 "file %s returned %s\n",
625                 smb_fname_str_dbg(smb_fname),
626                 nt_errstr(status) ));
627
628         fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
629
630         if (!file_existed && fsp->fh->fd != -1) {
631                 /* File was created. Inherit from parent directory. */
632                 status = fsp_set_smb_fname(fsp, smb_fname);
633                 if (!NT_STATUS_IS_OK(status)) {
634                         errno = map_errno_from_nt_status(status);
635                         return -1;
636                 }
637                 inherit_new_acl(handle, smb_fname, fsp, false);
638         }
639
640         return fsp->fh->fd;
641 }
642
643 static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode)
644 {
645         struct smb_filename *smb_fname = NULL;
646         int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode);
647         NTSTATUS status;
648
649         if (ret == -1) {
650                 return ret;
651         }
652
653         status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL,
654                                             &smb_fname);
655         if (!NT_STATUS_IS_OK(status)) {
656                 errno = map_errno_from_nt_status(status);
657                 return -1;
658         }
659
660         /* New directory - inherit from parent. */
661         inherit_new_acl(handle, smb_fname, NULL, true);
662         TALLOC_FREE(smb_fname);
663         return ret;
664 }
665
666 /*********************************************************************
667  Fetch a security descriptor given an fsp.
668 *********************************************************************/
669
670 static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
671         uint32_t security_info, struct security_descriptor **ppdesc)
672 {
673         return get_nt_acl_xattr_internal(handle, fsp,
674                                 NULL, security_info, ppdesc);
675 }
676
677 /*********************************************************************
678  Fetch a security descriptor given a pathname.
679 *********************************************************************/
680
681 static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
682         const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
683 {
684         return get_nt_acl_xattr_internal(handle, NULL,
685                                 name, security_info, ppdesc);
686 }
687
688 /*********************************************************************
689  Store a security descriptor given an fsp.
690 *********************************************************************/
691
692 static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
693         uint32_t security_info_sent, const struct security_descriptor *psd)
694 {
695         NTSTATUS status;
696         DATA_BLOB blob;
697         struct security_descriptor *pdesc_next = NULL;
698         uint8_t hash[XATTR_SD_HASH_SIZE];
699
700         if (DEBUGLEVEL >= 10) {
701                 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
702                           fsp_str_dbg(fsp)));
703                 NDR_PRINT_DEBUG(security_descriptor,
704                         CONST_DISCARD(struct security_descriptor *,psd));
705         }
706
707         /* Ensure owner and group are set. */
708         if (!psd->owner_sid || !psd->group_sid) {
709                 int ret;
710                 DOM_SID owner_sid, group_sid;
711                 struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd);
712
713                 if (!nc_psd) {
714                         return NT_STATUS_OK;
715                 }
716                 if (fsp->is_directory || fsp->fh->fd == -1) {
717                         if (fsp->posix_open) {
718                                 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
719                         } else {
720                                 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
721                         }
722                 } else {
723                         ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
724                 }
725                 if (ret == -1) {
726                         /* Lower level acl set succeeded,
727                          * so still return OK. */
728                         return NT_STATUS_OK;
729                 }
730                 create_file_sids(&fsp->fsp_name->st, &owner_sid, &group_sid);
731                 /* This is safe as nc_psd is discarded at fn exit. */
732                 nc_psd->owner_sid = &owner_sid;
733                 nc_psd->group_sid = &group_sid;
734                 security_info_sent |= (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION);
735                 psd = nc_psd;
736         }
737
738         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
739         if (!NT_STATUS_IS_OK(status)) {
740                 return status;
741         }
742
743         /* Get the full underlying sd, then hash. */
744         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
745                                 fsp,
746                                 HASH_SECURITY_INFO,
747                                 &pdesc_next);
748
749         if (!NT_STATUS_IS_OK(status)) {
750                 return status;
751         }
752
753         status = hash_sd_sha256(pdesc_next, hash);
754         if (!NT_STATUS_IS_OK(status)) {
755                 return status;
756         }
757
758 #if 0
759         if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
760                         psd->dacl != NULL &&
761                         (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
762                                 SE_DESC_DACL_AUTO_INHERIT_REQ))==
763                                 (SE_DESC_DACL_AUTO_INHERITED|
764                                 SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
765                 struct security_descriptor *new_psd = NULL;
766                 status = append_parent_acl(fsp, psd, &new_psd);
767                 if (!NT_STATUS_IS_OK(status)) {
768                         /* Lower level acl set succeeded,
769                          * so still return OK. */
770                         return NT_STATUS_OK;
771                 }
772                 psd = new_psd;
773         }
774 #endif
775
776         if (DEBUGLEVEL >= 10) {
777                 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
778                           fsp_str_dbg(fsp)));
779                 NDR_PRINT_DEBUG(security_descriptor,
780                         CONST_DISCARD(struct security_descriptor *,psd));
781         }
782         create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
783         store_acl_blob_fsp(handle, fsp, &blob);
784
785         return NT_STATUS_OK;
786 }
787
788 /*********************************************************************
789  Remove a Windows ACL - we're setting the underlying POSIX ACL.
790 *********************************************************************/
791
792 static int sys_acl_set_file_xattr(vfs_handle_struct *handle,
793                               const char *name,
794                               SMB_ACL_TYPE_T type,
795                               SMB_ACL_T theacl)
796 {
797         int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
798                                                 name,
799                                                 type,
800                                                 theacl);
801         if (ret == -1) {
802                 return -1;
803         }
804
805         become_root();
806         SMB_VFS_REMOVEXATTR(handle->conn, name, XATTR_NTACL_NAME);
807         unbecome_root();
808
809         return ret;
810 }
811
812 /*********************************************************************
813  Remove a Windows ACL - we're setting the underlying POSIX ACL.
814 *********************************************************************/
815
816 static int sys_acl_set_fd_xattr(vfs_handle_struct *handle,
817                             files_struct *fsp,
818                             SMB_ACL_T theacl)
819 {
820         int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
821                                                 fsp,
822                                                 theacl);
823         if (ret == -1) {
824                 return -1;
825         }
826
827         become_root();
828         SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME);
829         unbecome_root();
830
831         return ret;
832 }
833
834
835 static struct vfs_fn_pointers vfs_acl_xattr_fns = {
836         .mkdir = mkdir_acl_xattr,
837         .open = open_acl_xattr,
838         .fget_nt_acl = fget_nt_acl_xattr,
839         .get_nt_acl = get_nt_acl_xattr,
840         .fset_nt_acl = fset_nt_acl_xattr,
841         .sys_acl_set_file = sys_acl_set_file_xattr,
842         .sys_acl_set_fd = sys_acl_set_fd_xattr
843 };
844
845 NTSTATUS vfs_acl_xattr_init(void)
846 {
847         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr",
848                                 &vfs_acl_xattr_fns);
849 }