~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/modules/vfs_acl_xattr.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
27
#undef DBGC_CLASS
 
28
#define DBGC_CLASS DBGC_VFS
 
29
 
 
30
/*******************************************************************
 
31
 Parse out a struct security_descriptor from a DATA_BLOB.
 
32
*******************************************************************/
 
33
 
 
34
static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
 
35
                                uint32 security_info,
 
36
                                struct security_descriptor **ppdesc)
 
37
{
 
38
        TALLOC_CTX *ctx = talloc_tos();
 
39
        struct xattr_NTACL xacl;
 
40
        enum ndr_err_code ndr_err;
 
41
        size_t sd_size;
 
42
 
 
43
        ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
 
44
                        (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
 
45
 
 
46
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
47
                DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
 
48
                        ndr_errstr(ndr_err)));
 
49
                return ndr_map_error2ntstatus(ndr_err);;
 
50
        }
 
51
 
 
52
        if (xacl.version != 2) {
 
53
                return NT_STATUS_REVISION_MISMATCH;
 
54
        }
 
55
 
 
56
        *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs->sd->type | SEC_DESC_SELF_RELATIVE,
 
57
                        (security_info & OWNER_SECURITY_INFORMATION)
 
58
                        ? xacl.info.sd_hs->sd->owner_sid : NULL,
 
59
                        (security_info & GROUP_SECURITY_INFORMATION)
 
60
                        ? xacl.info.sd_hs->sd->group_sid : NULL,
 
61
                        (security_info & SACL_SECURITY_INFORMATION)
 
62
                        ? xacl.info.sd_hs->sd->sacl : NULL,
 
63
                        (security_info & DACL_SECURITY_INFORMATION)
 
64
                        ? xacl.info.sd_hs->sd->dacl : NULL,
 
65
                        &sd_size);
 
66
 
 
67
        TALLOC_FREE(xacl.info.sd);
 
68
 
 
69
        return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
 
70
}
 
71
 
 
72
/*******************************************************************
 
73
 Pull a security descriptor into a DATA_BLOB from a xattr.
 
74
*******************************************************************/
 
75
 
 
76
static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
 
77
                        vfs_handle_struct *handle,
 
78
                        files_struct *fsp,
 
79
                        const char *name,
 
80
                        DATA_BLOB *pblob)
 
81
{
 
82
        size_t size = 1024;
 
83
        uint8_t *val = NULL;
 
84
        uint8_t *tmp;
 
85
        ssize_t sizeret;
 
86
        int saved_errno = 0;
 
87
 
 
88
        ZERO_STRUCTP(pblob);
 
89
 
 
90
  again:
 
91
 
 
92
        tmp = TALLOC_REALLOC_ARRAY(ctx, val, uint8_t, size);
 
93
        if (tmp == NULL) {
 
94
                TALLOC_FREE(val);
 
95
                return NT_STATUS_NO_MEMORY;
 
96
        }
 
97
        val = tmp;
 
98
 
 
99
        become_root();
 
100
        if (fsp && fsp->fh->fd != -1) {
 
101
                sizeret = SMB_VFS_FGETXATTR(fsp, XATTR_NTACL_NAME, val, size);
 
102
        } else {
 
103
                sizeret = SMB_VFS_GETXATTR(handle->conn, name,
 
104
                                        XATTR_NTACL_NAME, val, size);
 
105
        }
 
106
        if (sizeret == -1) {
 
107
                saved_errno = errno;
 
108
        }
 
109
        unbecome_root();
 
110
 
 
111
        /* Max ACL size is 65536 bytes. */
 
112
        if (sizeret == -1) {
 
113
                errno = saved_errno;
 
114
                if ((errno == ERANGE) && (size != 65536)) {
 
115
                        /* Too small, try again. */
 
116
                        size = 65536;
 
117
                        goto again;
 
118
                }
 
119
 
 
120
                /* Real error - exit here. */
 
121
                TALLOC_FREE(val);
 
122
                return map_nt_error_from_unix(errno);
 
123
        }
 
124
 
 
125
        pblob->data = val;
 
126
        pblob->length = sizeret;
 
127
        return NT_STATUS_OK;
 
128
}
 
129
 
 
130
/*******************************************************************
 
131
 Create a DATA_BLOB from a security descriptor.
 
132
*******************************************************************/
 
133
 
 
134
static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob)
 
135
{
 
136
        struct xattr_NTACL xacl;
 
137
        struct security_descriptor_hash sd_hs;
 
138
        enum ndr_err_code ndr_err;
 
139
        TALLOC_CTX *ctx = talloc_tos();
 
140
 
 
141
        ZERO_STRUCT(xacl);
 
142
        ZERO_STRUCT(sd_hs);
 
143
 
 
144
        xacl.version = 2;
 
145
        xacl.info.sd_hs = &sd_hs;
 
146
        xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd);
 
147
        memset(&xacl.info.sd_hs->hash[0], '\0', 16);
 
148
 
 
149
        ndr_err = ndr_push_struct_blob(
 
150
                        pblob, ctx, NULL, &xacl,
 
151
                        (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
 
152
 
 
153
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
154
                DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
 
155
                        ndr_errstr(ndr_err)));
 
156
                return ndr_map_error2ntstatus(ndr_err);;
 
157
        }
 
158
 
 
159
        return NT_STATUS_OK;
 
160
}
 
161
 
 
162
/*******************************************************************
 
163
 Store a DATA_BLOB into an xattr given an fsp pointer.
 
164
*******************************************************************/
 
165
 
 
166
static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
 
167
                                files_struct *fsp,
 
168
                                DATA_BLOB *pblob)
 
169
{
 
170
        int ret;
 
171
        int saved_errno = 0;
 
172
 
 
173
        DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
 
174
                        (unsigned int)pblob->length, fsp->fsp_name));
 
175
 
 
176
        become_root();
 
177
        if (fsp->fh->fd != -1) {
 
178
                ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
 
179
                        pblob->data, pblob->length, 0);
 
180
        } else {
 
181
                ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
 
182
                                XATTR_NTACL_NAME,
 
183
                                pblob->data, pblob->length, 0);
 
184
        }
 
185
        if (ret) {
 
186
                saved_errno = errno;
 
187
        }
 
188
        unbecome_root();
 
189
        if (ret) {
 
190
                errno = saved_errno;
 
191
                DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s"
 
192
                        "with error %s\n",
 
193
                        fsp->fsp_name,
 
194
                        strerror(errno) ));
 
195
                return map_nt_error_from_unix(errno);
 
196
        }
 
197
        return NT_STATUS_OK;
 
198
}
 
199
 
 
200
/*******************************************************************
 
201
 Store a DATA_BLOB into an xattr given a pathname.
 
202
*******************************************************************/
 
203
 
 
204
static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
 
205
                                        const char *fname,
 
206
                                        DATA_BLOB *pblob)
 
207
{
 
208
        connection_struct *conn = handle->conn;
 
209
        int ret;
 
210
        int saved_errno = 0;
 
211
 
 
212
        DEBUG(10,("store_acl_blob_pathname: storing blob "
 
213
                        "length %u on file %s\n",
 
214
                        (unsigned int)pblob->length, fname));
 
215
 
 
216
        become_root();
 
217
        ret = SMB_VFS_SETXATTR(conn, fname,
 
218
                                XATTR_NTACL_NAME,
 
219
                                pblob->data, pblob->length, 0);
 
220
        if (ret) {
 
221
                saved_errno = errno;
 
222
        }
 
223
        unbecome_root();
 
224
        if (ret) {
 
225
                errno = saved_errno;
 
226
                DEBUG(5, ("store_acl_blob_pathname: setting attr failed "
 
227
                        "for file %s with error %s\n",
 
228
                        fname,
 
229
                        strerror(errno) ));
 
230
                return map_nt_error_from_unix(errno);
 
231
        }
 
232
        return NT_STATUS_OK;
 
233
}
 
234
 
 
235
/*******************************************************************
 
236
 Store a DATA_BLOB into an xattr given a pathname.
 
237
*******************************************************************/
 
238
 
 
239
static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
 
240
                                        files_struct *fsp,
 
241
                                        const char *name,
 
242
                                        uint32 security_info,
 
243
                                        struct security_descriptor **ppdesc)
 
244
{
 
245
        TALLOC_CTX *ctx = talloc_tos();
 
246
        DATA_BLOB blob;
 
247
        NTSTATUS status;
 
248
 
 
249
        if (fsp && name == NULL) {
 
250
                name = fsp->fsp_name;
 
251
        }
 
252
 
 
253
        DEBUG(10, ("get_nt_acl_xattr_internal: name=%s\n", name));
 
254
 
 
255
        status = get_acl_blob(ctx, handle, fsp, name, &blob);
 
256
        if (!NT_STATUS_IS_OK(status)) {
 
257
                DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status)));
 
258
                return status;
 
259
        }
 
260
 
 
261
        status = parse_acl_blob(&blob, security_info, ppdesc);
 
262
        if (!NT_STATUS_IS_OK(status)) {
 
263
                DEBUG(10, ("parse_acl_blob returned %s\n",
 
264
                                nt_errstr(status)));
 
265
                return status;
 
266
        }
 
267
 
 
268
        TALLOC_FREE(blob.data);
 
269
        return status;
 
270
}
 
271
 
 
272
/*********************************************************************
 
273
 Create a default security descriptor for a file in case no inheritance
 
274
 exists. All permissions to the owner and SYSTEM.
 
275
*********************************************************************/
 
276
 
 
277
static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
 
278
                                                SMB_STRUCT_STAT *psbuf)
 
279
{
 
280
        struct dom_sid owner_sid, group_sid;
 
281
        size_t sd_size;
 
282
        struct security_ace *pace = NULL;
 
283
        struct security_acl *pacl = NULL;
 
284
 
 
285
        uid_to_sid(&owner_sid, psbuf->st_uid);
 
286
        gid_to_sid(&group_sid, psbuf->st_gid);
 
287
 
 
288
        pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
 
289
        if (!pace) {
 
290
                return NULL;
 
291
        }
 
292
 
 
293
        init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
 
294
                        SEC_RIGHTS_FILE_ALL, 0);
 
295
        init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
 
296
                        SEC_RIGHTS_FILE_ALL, 0);
 
297
 
 
298
        pacl = make_sec_acl(mem_ctx,
 
299
                                NT4_ACL_REVISION,
 
300
                                2,
 
301
                                pace);
 
302
        if (!pacl) {
 
303
                return NULL;
 
304
        }
 
305
        return make_sec_desc(mem_ctx,
 
306
                        SECURITY_DESCRIPTOR_REVISION_1,
 
307
                        SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
 
308
                        &owner_sid,
 
309
                        &group_sid,
 
310
                        NULL,
 
311
                        pacl,
 
312
                        &sd_size);
 
313
}
 
314
 
 
315
/*********************************************************************
 
316
*********************************************************************/
 
317
 
 
318
static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
 
319
                                        const char *fname,
 
320
                                        files_struct *fsp,
 
321
                                        bool container)
 
322
{
 
323
        TALLOC_CTX *ctx = talloc_tos();
 
324
        NTSTATUS status;
 
325
        struct security_descriptor *parent_desc = NULL;
 
326
        struct security_descriptor *psd = NULL;
 
327
        DATA_BLOB blob;
 
328
        size_t size;
 
329
        char *parent_name;
 
330
 
 
331
        if (!parent_dirname(ctx, fname, &parent_name, NULL)) {
 
332
                return NT_STATUS_NO_MEMORY;
 
333
        }
 
334
 
 
335
        DEBUG(10,("inherit_new_acl: check directory %s\n",
 
336
                        parent_name));
 
337
 
 
338
        status = get_nt_acl_xattr_internal(handle,
 
339
                                        NULL,
 
340
                                        parent_name,
 
341
                                        (OWNER_SECURITY_INFORMATION |
 
342
                                         GROUP_SECURITY_INFORMATION |
 
343
                                         DACL_SECURITY_INFORMATION),
 
344
                                        &parent_desc);
 
345
        if (NT_STATUS_IS_OK(status)) {
 
346
                /* Create an inherited descriptor from the parent. */
 
347
 
 
348
                if (DEBUGLEVEL >= 10) {
 
349
                        DEBUG(10,("inherit_new_acl: parent acl is:\n"));
 
350
                        NDR_PRINT_DEBUG(security_descriptor, parent_desc);
 
351
                }
 
352
 
 
353
                status = se_create_child_secdesc(ctx,
 
354
                                &psd,
 
355
                                &size,
 
356
                                parent_desc,
 
357
                                &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
 
358
                                &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
 
359
                                container);
 
360
                if (!NT_STATUS_IS_OK(status)) {
 
361
                        return status;
 
362
                }
 
363
 
 
364
                if (DEBUGLEVEL >= 10) {
 
365
                        DEBUG(10,("inherit_new_acl: child acl is:\n"));
 
366
                        NDR_PRINT_DEBUG(security_descriptor, psd);
 
367
                }
 
368
 
 
369
        } else {
 
370
                DEBUG(10,("inherit_new_acl: directory %s failed "
 
371
                        "to get acl %s\n",
 
372
                        parent_name,
 
373
                        nt_errstr(status) ));
 
374
        }
 
375
 
 
376
        if (!psd || psd->dacl == NULL) {
 
377
                SMB_STRUCT_STAT sbuf;
 
378
                int ret;
 
379
 
 
380
                TALLOC_FREE(psd);
 
381
                if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
 
382
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
 
383
                } else {
 
384
                        if (fsp && fsp->posix_open) {
 
385
                                ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
 
386
                        } else {
 
387
                                ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
 
388
                        }
 
389
                }
 
390
                if (ret == -1) {
 
391
                        return map_nt_error_from_unix(errno);
 
392
                }
 
393
                psd = default_file_sd(ctx, &sbuf);
 
394
                if (!psd) {
 
395
                        return NT_STATUS_NO_MEMORY;
 
396
                }
 
397
 
 
398
                if (DEBUGLEVEL >= 10) {
 
399
                        DEBUG(10,("inherit_new_acl: default acl is:\n"));
 
400
                        NDR_PRINT_DEBUG(security_descriptor, psd);
 
401
                }
 
402
        }
 
403
 
 
404
        status = create_acl_blob(psd, &blob);
 
405
        if (!NT_STATUS_IS_OK(status)) {
 
406
                return status;
 
407
        }
 
408
        if (fsp) {
 
409
                return store_acl_blob_fsp(handle, fsp, &blob);
 
410
        } else {
 
411
                return store_acl_blob_pathname(handle, fname, &blob);
 
412
        }
 
413
}
 
414
 
 
415
/*********************************************************************
 
416
 Check ACL on open. For new files inherit from parent directory.
 
417
*********************************************************************/
 
418
 
 
419
static int open_acl_xattr(vfs_handle_struct *handle,
 
420
                                        const char *fname,
 
421
                                        files_struct *fsp,
 
422
                                        int flags,
 
423
                                        mode_t mode)
 
424
{
 
425
        uint32_t access_granted = 0;
 
426
        struct security_descriptor *pdesc = NULL;
 
427
        bool file_existed = true;
 
428
        NTSTATUS status = get_nt_acl_xattr_internal(handle,
 
429
                                        NULL,
 
430
                                        fname,
 
431
                                        (OWNER_SECURITY_INFORMATION |
 
432
                                         GROUP_SECURITY_INFORMATION |
 
433
                                         DACL_SECURITY_INFORMATION),
 
434
                                        &pdesc);
 
435
        if (NT_STATUS_IS_OK(status)) {
 
436
                /* See if we can access it. */
 
437
                status = smb1_file_se_access_check(pdesc,
 
438
                                        handle->conn->server_info->ptok,
 
439
                                        fsp->access_mask,
 
440
                                        &access_granted);
 
441
                if (!NT_STATUS_IS_OK(status)) {
 
442
                        DEBUG(10,("open_acl_xattr: file %s open "
 
443
                                "refused with error %s\n",
 
444
                                fname,
 
445
                                nt_errstr(status) ));
 
446
                        errno = map_errno_from_nt_status(status);
 
447
                        return -1;
 
448
                }
 
449
        } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
 
450
                file_existed = false;
 
451
        }
 
452
 
 
453
        DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
 
454
                "file %s returned %s\n",
 
455
                fname,
 
456
                nt_errstr(status) ));
 
457
 
 
458
        fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
 
459
 
 
460
        if (!file_existed && fsp->fh->fd != -1) {
 
461
                /* File was created. Inherit from parent directory. */
 
462
                string_set(&fsp->fsp_name, fname);
 
463
                inherit_new_acl(handle, fname, fsp, false);
 
464
        }
 
465
 
 
466
        return fsp->fh->fd;
 
467
}
 
468
 
 
469
static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode)
 
470
{
 
471
        int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode);
 
472
 
 
473
        if (ret == -1) {
 
474
                return ret;
 
475
        }
 
476
        /* New directory - inherit from parent. */
 
477
        inherit_new_acl(handle, path, NULL, true);
 
478
        return ret;
 
479
}
 
480
 
 
481
/*********************************************************************
 
482
 Fetch a security descriptor given an fsp.
 
483
*********************************************************************/
 
484
 
 
485
static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
 
486
        uint32 security_info, struct security_descriptor **ppdesc)
 
487
{
 
488
        NTSTATUS status = get_nt_acl_xattr_internal(handle, fsp,
 
489
                                NULL, security_info, ppdesc);
 
490
        if (NT_STATUS_IS_OK(status)) {
 
491
                if (DEBUGLEVEL >= 10) {
 
492
                        DEBUG(10,("fget_nt_acl_xattr: returning xattr sd for file %s\n",
 
493
                                fsp->fsp_name));
 
494
                        NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
 
495
                }
 
496
                return NT_STATUS_OK;
 
497
        }
 
498
 
 
499
        DEBUG(10,("fget_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
 
500
                        fsp->fsp_name,
 
501
                        nt_errstr(status) ));
 
502
 
 
503
        return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp,
 
504
                        security_info, ppdesc);
 
505
}
 
506
 
 
507
/*********************************************************************
 
508
 Fetch a security descriptor given a pathname.
 
509
*********************************************************************/
 
510
 
 
511
static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
 
512
        const char *name, uint32 security_info, struct security_descriptor **ppdesc)
 
513
{
 
514
        NTSTATUS status = get_nt_acl_xattr_internal(handle, NULL,
 
515
                                name, security_info, ppdesc);
 
516
        if (NT_STATUS_IS_OK(status)) {
 
517
                if (DEBUGLEVEL >= 10) {
 
518
                        DEBUG(10,("get_nt_acl_xattr: returning xattr sd for file %s\n",
 
519
                                name));
 
520
                        NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
 
521
                }
 
522
                return NT_STATUS_OK;
 
523
        }
 
524
 
 
525
        DEBUG(10,("get_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
 
526
                        name,
 
527
                        nt_errstr(status) ));
 
528
 
 
529
        return SMB_VFS_NEXT_GET_NT_ACL(handle, name,
 
530
                        security_info, ppdesc);
 
531
}
 
532
 
 
533
/*********************************************************************
 
534
 Store a security descriptor given an fsp.
 
535
*********************************************************************/
 
536
 
 
537
static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
 
538
        uint32 security_info_sent, const struct security_descriptor *psd)
 
539
{
 
540
        NTSTATUS status;
 
541
        DATA_BLOB blob;
 
542
 
 
543
        if (DEBUGLEVEL >= 10) {
 
544
                DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
 
545
                        fsp->fsp_name));
 
546
                NDR_PRINT_DEBUG(security_descriptor,
 
547
                        CONST_DISCARD(struct security_descriptor *,psd));
 
548
        }
 
549
 
 
550
        status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
 
551
        if (!NT_STATUS_IS_OK(status)) {
 
552
                return status;
 
553
        }
 
554
 
 
555
        /* Ensure owner and group are set. */
 
556
        if (!psd->owner_sid || !psd->group_sid) {
 
557
                int ret;
 
558
                SMB_STRUCT_STAT sbuf;
 
559
                DOM_SID owner_sid, group_sid;
 
560
                struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd);
 
561
 
 
562
                if (!nc_psd) {
 
563
                        return NT_STATUS_OK;
 
564
                }
 
565
                if (fsp->is_directory || fsp->fh->fd == -1) {
 
566
                        if (fsp->posix_open) {
 
567
                                ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
 
568
                        } else {
 
569
                                ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
 
570
                        }
 
571
                } else {
 
572
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
 
573
                }
 
574
                if (ret == -1) {
 
575
                        /* Lower level acl set succeeded,
 
576
                         * so still return OK. */
 
577
                        return NT_STATUS_OK;
 
578
                }
 
579
                create_file_sids(&sbuf, &owner_sid, &group_sid);
 
580
                /* This is safe as nc_psd is discarded at fn exit. */
 
581
                nc_psd->owner_sid = &owner_sid;
 
582
                nc_psd->group_sid = &group_sid;
 
583
                security_info_sent |= (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION);
 
584
                psd = nc_psd;
 
585
        }
 
586
 
 
587
#if 0
 
588
        if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
 
589
                        psd->dacl != NULL &&
 
590
                        (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
 
591
                                SE_DESC_DACL_AUTO_INHERIT_REQ))==
 
592
                                (SE_DESC_DACL_AUTO_INHERITED|
 
593
                                SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
 
594
                struct security_descriptor *new_psd = NULL;
 
595
                status = append_parent_acl(fsp, psd, &new_psd);
 
596
                if (!NT_STATUS_IS_OK(status)) {
 
597
                        /* Lower level acl set succeeded,
 
598
                         * so still return OK. */
 
599
                        return NT_STATUS_OK;
 
600
                }
 
601
                psd = new_psd;
 
602
        }
 
603
#endif
 
604
 
 
605
        if (DEBUGLEVEL >= 10) {
 
606
                DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
 
607
                        fsp->fsp_name));
 
608
                NDR_PRINT_DEBUG(security_descriptor,
 
609
                        CONST_DISCARD(struct security_descriptor *,psd));
 
610
        }
 
611
        create_acl_blob(psd, &blob);
 
612
        store_acl_blob_fsp(handle, fsp, &blob);
 
613
 
 
614
        return NT_STATUS_OK;
 
615
}
 
616
 
 
617
/*********************************************************************
 
618
 Remove a Windows ACL - we're setting the underlying POSIX ACL.
 
619
*********************************************************************/
 
620
 
 
621
static int sys_acl_set_file_xattr(vfs_handle_struct *handle,
 
622
                              const char *name,
 
623
                              SMB_ACL_TYPE_T type,
 
624
                              SMB_ACL_T theacl)
 
625
{
 
626
        int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
 
627
                                                name,
 
628
                                                type,
 
629
                                                theacl);
 
630
        if (ret == -1) {
 
631
                return -1;
 
632
        }
 
633
 
 
634
        become_root();
 
635
        SMB_VFS_REMOVEXATTR(handle->conn, name, XATTR_NTACL_NAME);
 
636
        unbecome_root();
 
637
 
 
638
        return ret;
 
639
}
 
640
 
 
641
/*********************************************************************
 
642
 Remove a Windows ACL - we're setting the underlying POSIX ACL.
 
643
*********************************************************************/
 
644
 
 
645
static int sys_acl_set_fd_xattr(vfs_handle_struct *handle,
 
646
                            files_struct *fsp,
 
647
                            SMB_ACL_T theacl)
 
648
{
 
649
        int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
 
650
                                                fsp,
 
651
                                                theacl);
 
652
        if (ret == -1) {
 
653
                return -1;
 
654
        }
 
655
 
 
656
        become_root();
 
657
        SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME);
 
658
        unbecome_root();
 
659
 
 
660
        return ret;
 
661
}
 
662
 
 
663
/* VFS operations structure */
 
664
 
 
665
static vfs_op_tuple skel_op_tuples[] =
 
666
{
 
667
        {SMB_VFS_OP(mkdir_acl_xattr), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
 
668
        {SMB_VFS_OP(open_acl_xattr),  SMB_VFS_OP_OPEN,  SMB_VFS_LAYER_TRANSPARENT},
 
669
 
 
670
        /* NT File ACL operations */
 
671
 
 
672
        {SMB_VFS_OP(fget_nt_acl_xattr),SMB_VFS_OP_FGET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
 
673
        {SMB_VFS_OP(get_nt_acl_xattr), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
 
674
        {SMB_VFS_OP(fset_nt_acl_xattr),SMB_VFS_OP_FSET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
 
675
 
 
676
        /* POSIX ACL operations. */
 
677
        {SMB_VFS_OP(sys_acl_set_file_xattr), SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT},
 
678
        {SMB_VFS_OP(sys_acl_set_fd_xattr), SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_TRANSPARENT},
 
679
 
 
680
        {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
 
681
};
 
682
 
 
683
NTSTATUS vfs_acl_xattr_init(void)
 
684
{
 
685
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr", skel_op_tuples);
 
686
}