~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/posix_acls.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
   Unix SMB/CIFS implementation.
 
3
   SMB NT Security Descriptor / Unix permission conversion.
 
4
   Copyright (C) Jeremy Allison 1994-2009.
 
5
   Copyright (C) Andreas Gruenbacher 2002.
 
6
   Copyright (C) Simo Sorce <idra@samba.org> 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 "includes.h"
 
23
 
 
24
extern struct current_user current_user;
 
25
extern const struct generic_mapping file_generic_mapping;
 
26
 
 
27
#undef  DBGC_CLASS
 
28
#define DBGC_CLASS DBGC_ACLS
 
29
 
 
30
/****************************************************************************
 
31
 Data structures representing the internal ACE format.
 
32
****************************************************************************/
 
33
 
 
34
enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
 
35
enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */
 
36
 
 
37
typedef union posix_id {
 
38
                uid_t uid;
 
39
                gid_t gid;
 
40
                int world;
 
41
} posix_id;
 
42
 
 
43
typedef struct canon_ace {
 
44
        struct canon_ace *next, *prev;
 
45
        SMB_ACL_TAG_T type;
 
46
        mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
 
47
        DOM_SID trustee;
 
48
        enum ace_owner owner_type;
 
49
        enum ace_attribute attr;
 
50
        posix_id unix_ug;
 
51
        uint8_t ace_flags; /* From windows ACE entry. */
 
52
} canon_ace;
 
53
 
 
54
#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
 
55
 
 
56
/*
 
57
 * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance)
 
58
 * attribute on disk - version 1.
 
59
 * All values are little endian.
 
60
 *
 
61
 * |  1   |  1   |   2         |         2           |  ....
 
62
 * +------+------+-------------+---------------------+-------------+--------------------+
 
63
 * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... |
 
64
 * +------+------+-------------+---------------------+-------------+--------------------+
 
65
 *
 
66
 * Entry format is :
 
67
 *
 
68
 * |  1   |       4           |
 
69
 * +------+-------------------+
 
70
 * | value|  uid/gid or world |
 
71
 * | type |  value            |
 
72
 * +------+-------------------+
 
73
 *
 
74
 * Version 2 format. Stores extra Windows metadata about an ACL.
 
75
 *
 
76
 * |  1   |  2       |   2         |         2           |  ....
 
77
 * +------+----------+-------------+---------------------+-------------+--------------------+
 
78
 * | vers | ace      | num_entries | num_default_entries | ..entries.. | default_entries... |
 
79
 * |   2  |  type    |             |                     |             |                    |
 
80
 * +------+----------+-------------+---------------------+-------------+--------------------+
 
81
 *
 
82
 * Entry format is :
 
83
 *
 
84
 * |  1   |  1   |       4           |
 
85
 * +------+------+-------------------+
 
86
 * | ace  | value|  uid/gid or world |
 
87
 * | flag | type |  value            |
 
88
 * +------+-------------------+------+
 
89
 *
 
90
 */
 
91
 
 
92
#define PAI_VERSION_OFFSET                      0
 
93
 
 
94
#define PAI_V1_FLAG_OFFSET                      1
 
95
#define PAI_V1_NUM_ENTRIES_OFFSET               2
 
96
#define PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET       4
 
97
#define PAI_V1_ENTRIES_BASE                     6
 
98
#define PAI_V1_ACL_FLAG_PROTECTED               0x1
 
99
#define PAI_V1_ENTRY_LENGTH                     5
 
100
 
 
101
#define PAI_V1_VERSION                          1
 
102
 
 
103
#define PAI_V2_TYPE_OFFSET                      1
 
104
#define PAI_V2_NUM_ENTRIES_OFFSET               3
 
105
#define PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET       5
 
106
#define PAI_V2_ENTRIES_BASE                     7
 
107
#define PAI_V2_ENTRY_LENGTH                     6
 
108
 
 
109
#define PAI_V2_VERSION                          2
 
110
 
 
111
/*
 
112
 * In memory format of user.SAMBA_PAI attribute.
 
113
 */
 
114
 
 
115
struct pai_entry {
 
116
        struct pai_entry *next, *prev;
 
117
        uint8_t ace_flags;
 
118
        enum ace_owner owner_type;
 
119
        posix_id unix_ug;
 
120
};
 
121
 
 
122
struct pai_val {
 
123
        uint16_t sd_type;
 
124
        unsigned int num_entries;
 
125
        struct pai_entry *entry_list;
 
126
        unsigned int num_def_entries;
 
127
        struct pai_entry *def_entry_list;
 
128
};
 
129
 
 
130
/************************************************************************
 
131
 Return a uint32 of the pai_entry principal.
 
132
************************************************************************/
 
133
 
 
134
static uint32_t get_pai_entry_val(struct pai_entry *paie)
 
135
{
 
136
        switch (paie->owner_type) {
 
137
                case UID_ACE:
 
138
                        DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
 
139
                        return (uint32_t)paie->unix_ug.uid;
 
140
                case GID_ACE:
 
141
                        DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
 
142
                        return (uint32_t)paie->unix_ug.gid;
 
143
                case WORLD_ACE:
 
144
                default:
 
145
                        DEBUG(10,("get_pai_entry_val: world ace\n"));
 
146
                        return (uint32_t)-1;
 
147
        }
 
148
}
 
149
 
 
150
/************************************************************************
 
151
 Return a uint32 of the entry principal.
 
152
************************************************************************/
 
153
 
 
154
static uint32_t get_entry_val(canon_ace *ace_entry)
 
155
{
 
156
        switch (ace_entry->owner_type) {
 
157
                case UID_ACE:
 
158
                        DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid ));
 
159
                        return (uint32_t)ace_entry->unix_ug.uid;
 
160
                case GID_ACE:
 
161
                        DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid ));
 
162
                        return (uint32_t)ace_entry->unix_ug.gid;
 
163
                case WORLD_ACE:
 
164
                default:
 
165
                        DEBUG(10,("get_entry_val: world ace\n"));
 
166
                        return (uint32_t)-1;
 
167
        }
 
168
}
 
169
 
 
170
/************************************************************************
 
171
 Create the on-disk format (always v2 now). Caller must free.
 
172
************************************************************************/
 
173
 
 
174
static char *create_pai_buf_v2(canon_ace *file_ace_list,
 
175
                                canon_ace *dir_ace_list,
 
176
                                uint16_t sd_type,
 
177
                                size_t *store_size)
 
178
{
 
179
        char *pai_buf = NULL;
 
180
        canon_ace *ace_list = NULL;
 
181
        char *entry_offset = NULL;
 
182
        unsigned int num_entries = 0;
 
183
        unsigned int num_def_entries = 0;
 
184
        unsigned int i;
 
185
 
 
186
        for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
 
187
                num_entries++;
 
188
        }
 
189
 
 
190
        for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
 
191
                num_def_entries++;
 
192
        }
 
193
 
 
194
        DEBUG(10,("create_pai_buf_v2: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
 
195
 
 
196
        *store_size = PAI_V2_ENTRIES_BASE +
 
197
                ((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH);
 
198
 
 
199
        pai_buf = (char *)SMB_MALLOC(*store_size);
 
200
        if (!pai_buf) {
 
201
                return NULL;
 
202
        }
 
203
 
 
204
        /* Set up the header. */
 
205
        memset(pai_buf, '\0', PAI_V2_ENTRIES_BASE);
 
206
        SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_V2_VERSION);
 
207
        SSVAL(pai_buf,PAI_V2_TYPE_OFFSET, sd_type);
 
208
        SSVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET,num_entries);
 
209
        SSVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
 
210
 
 
211
        DEBUG(10,("create_pai_buf_v2: sd_type = 0x%x\n",
 
212
                        (unsigned int)sd_type ));
 
213
 
 
214
        entry_offset = pai_buf + PAI_V2_ENTRIES_BASE;
 
215
 
 
216
        i = 0;
 
217
        for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
 
218
                uint8_t type_val = (uint8_t)ace_list->owner_type;
 
219
                uint32_t entry_val = get_entry_val(ace_list);
 
220
 
 
221
                SCVAL(entry_offset,0,ace_list->ace_flags);
 
222
                SCVAL(entry_offset,1,type_val);
 
223
                SIVAL(entry_offset,2,entry_val);
 
224
                DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
 
225
                        i,
 
226
                        (unsigned int)ace_list->ace_flags,
 
227
                        (unsigned int)type_val,
 
228
                        (unsigned int)entry_val ));
 
229
                i++;
 
230
                entry_offset += PAI_V2_ENTRY_LENGTH;
 
231
        }
 
232
 
 
233
        for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
 
234
                uint8_t type_val = (uint8_t)ace_list->owner_type;
 
235
                uint32_t entry_val = get_entry_val(ace_list);
 
236
 
 
237
                SCVAL(entry_offset,0,ace_list->ace_flags);
 
238
                SCVAL(entry_offset,1,type_val);
 
239
                SIVAL(entry_offset,2,entry_val);
 
240
                DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
 
241
                        i,
 
242
                        (unsigned int)ace_list->ace_flags,
 
243
                        (unsigned int)type_val,
 
244
                        (unsigned int)entry_val ));
 
245
                i++;
 
246
                entry_offset += PAI_V2_ENTRY_LENGTH;
 
247
        }
 
248
 
 
249
        return pai_buf;
 
250
}
 
251
 
 
252
/************************************************************************
 
253
 Store the user.SAMBA_PAI attribute on disk.
 
254
************************************************************************/
 
255
 
 
256
static void store_inheritance_attributes(files_struct *fsp,
 
257
                                        canon_ace *file_ace_list,
 
258
                                        canon_ace *dir_ace_list,
 
259
                                        uint16_t sd_type)
 
260
{
 
261
        int ret;
 
262
        size_t store_size;
 
263
        char *pai_buf;
 
264
 
 
265
        if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
 
266
                return;
 
267
        }
 
268
 
 
269
        pai_buf = create_pai_buf_v2(file_ace_list, dir_ace_list,
 
270
                                sd_type, &store_size);
 
271
 
 
272
        if (fsp->fh->fd != -1) {
 
273
                ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
 
274
                                pai_buf, store_size, 0);
 
275
        } else {
 
276
                ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,
 
277
                                pai_buf, store_size, 0);
 
278
        }
 
279
 
 
280
        SAFE_FREE(pai_buf);
 
281
 
 
282
        DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n",
 
283
                (unsigned int)sd_type,
 
284
                fsp->fsp_name));
 
285
 
 
286
        if (ret == -1 && !no_acl_syscall_error(errno)) {
 
287
                DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
 
288
        }
 
289
}
 
290
 
 
291
/************************************************************************
 
292
 Delete the in memory inheritance info.
 
293
************************************************************************/
 
294
 
 
295
static void free_inherited_info(struct pai_val *pal)
 
296
{
 
297
        if (pal) {
 
298
                struct pai_entry *paie, *paie_next;
 
299
                for (paie = pal->entry_list; paie; paie = paie_next) {
 
300
                        paie_next = paie->next;
 
301
                        SAFE_FREE(paie);
 
302
                }
 
303
                for (paie = pal->def_entry_list; paie; paie = paie_next) {
 
304
                        paie_next = paie->next;
 
305
                        SAFE_FREE(paie);
 
306
                }
 
307
                SAFE_FREE(pal);
 
308
        }
 
309
}
 
310
 
 
311
/************************************************************************
 
312
 Get any stored ACE flags.
 
313
************************************************************************/
 
314
 
 
315
static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool default_ace)
 
316
{
 
317
        struct pai_entry *paie;
 
318
 
 
319
        if (!pal) {
 
320
                return 0;
 
321
        }
 
322
 
 
323
        /* If the entry exists it is inherited. */
 
324
        for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
 
325
                if (ace_entry->owner_type == paie->owner_type &&
 
326
                                get_entry_val(ace_entry) == get_pai_entry_val(paie))
 
327
                        return paie->ace_flags;
 
328
        }
 
329
        return 0;
 
330
}
 
331
 
 
332
/************************************************************************
 
333
 Ensure an attribute just read is valid - v1.
 
334
************************************************************************/
 
335
 
 
336
static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
 
337
{
 
338
        uint16 num_entries;
 
339
        uint16 num_def_entries;
 
340
 
 
341
        if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
 
342
                /* Corrupted - too small. */
 
343
                return false;
 
344
        }
 
345
 
 
346
        if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V1_VERSION) {
 
347
                return false;
 
348
        }
 
349
 
 
350
        num_entries = SVAL(pai_buf,PAI_V1_NUM_ENTRIES_OFFSET);
 
351
        num_def_entries = SVAL(pai_buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
 
352
 
 
353
        /* Check the entry lists match. */
 
354
        /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */
 
355
 
 
356
        if (((num_entries + num_def_entries)*PAI_V1_ENTRY_LENGTH) +
 
357
                        PAI_V1_ENTRIES_BASE != pai_buf_data_size) {
 
358
                return false;
 
359
        }
 
360
 
 
361
        return true;
 
362
}
 
363
 
 
364
/************************************************************************
 
365
 Ensure an attribute just read is valid - v2.
 
366
************************************************************************/
 
367
 
 
368
static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
 
369
{
 
370
        uint16 num_entries;
 
371
        uint16 num_def_entries;
 
372
 
 
373
        if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
 
374
                /* Corrupted - too small. */
 
375
                return false;
 
376
        }
 
377
 
 
378
        if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V2_VERSION) {
 
379
                return false;
 
380
        }
 
381
 
 
382
        num_entries = SVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET);
 
383
        num_def_entries = SVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
 
384
 
 
385
        /* Check the entry lists match. */
 
386
        /* Each entry is 6 bytes (flags + type + 4 bytes of uid or gid). */
 
387
 
 
388
        if (((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH) +
 
389
                        PAI_V2_ENTRIES_BASE != pai_buf_data_size) {
 
390
                return false;
 
391
        }
 
392
 
 
393
        return true;
 
394
}
 
395
 
 
396
/************************************************************************
 
397
 Decode the owner.
 
398
************************************************************************/
 
399
 
 
400
static bool get_pai_owner_type(struct pai_entry *paie, const char *entry_offset)
 
401
{
 
402
        paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
 
403
        switch( paie->owner_type) {
 
404
                case UID_ACE:
 
405
                        paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
 
406
                        DEBUG(10,("get_pai_owner_type: uid = %u\n",
 
407
                                (unsigned int)paie->unix_ug.uid ));
 
408
                        break;
 
409
                case GID_ACE:
 
410
                        paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
 
411
                        DEBUG(10,("get_pai_owner_type: gid = %u\n",
 
412
                                (unsigned int)paie->unix_ug.gid ));
 
413
                        break;
 
414
                case WORLD_ACE:
 
415
                        paie->unix_ug.world = -1;
 
416
                        DEBUG(10,("get_pai_owner_type: world ace\n"));
 
417
                        break;
 
418
                default:
 
419
                        DEBUG(10,("get_pai_owner_type: unknown type %u\n",
 
420
                                (unsigned int)paie->owner_type ));
 
421
                        return false;
 
422
        }
 
423
        return true;
 
424
}
 
425
 
 
426
/************************************************************************
 
427
 Process v2 entries.
 
428
************************************************************************/
 
429
 
 
430
static const char *create_pai_v1_entries(struct pai_val *paiv,
 
431
                                const char *entry_offset,
 
432
                                bool def_entry)
 
433
{
 
434
        int i;
 
435
 
 
436
        for (i = 0; i < paiv->num_entries; i++) {
 
437
                struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry);
 
438
                if (!paie) {
 
439
                        return NULL;
 
440
                }
 
441
 
 
442
                paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE;
 
443
                if (!get_pai_owner_type(paie, entry_offset)) {
 
444
                        return NULL;
 
445
                }
 
446
 
 
447
                if (!def_entry) {
 
448
                        DLIST_ADD(paiv->entry_list, paie);
 
449
                } else {
 
450
                        DLIST_ADD(paiv->def_entry_list, paie);
 
451
                }
 
452
                entry_offset += PAI_V1_ENTRY_LENGTH;
 
453
        }
 
454
        return entry_offset;
 
455
}
 
456
 
 
457
/************************************************************************
 
458
 Convert to in-memory format from version 1.
 
459
************************************************************************/
 
460
 
 
461
static struct pai_val *create_pai_val_v1(const char *buf, size_t size)
 
462
{
 
463
        const char *entry_offset;
 
464
        struct pai_val *paiv = NULL;
 
465
 
 
466
        if (!check_pai_ok_v1(buf, size)) {
 
467
                return NULL;
 
468
        }
 
469
 
 
470
        paiv = SMB_MALLOC_P(struct pai_val);
 
471
        if (!paiv) {
 
472
                return NULL;
 
473
        }
 
474
 
 
475
        memset(paiv, '\0', sizeof(struct pai_val));
 
476
 
 
477
        paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ?
 
478
                        SE_DESC_DACL_PROTECTED : 0;
 
479
 
 
480
        paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET);
 
481
        paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
 
482
 
 
483
        entry_offset = buf + PAI_V1_ENTRIES_BASE;
 
484
 
 
485
        DEBUG(10,("create_pai_val: num_entries = %u, num_def_entries = %u\n",
 
486
                        paiv->num_entries, paiv->num_def_entries ));
 
487
 
 
488
        entry_offset = create_pai_v1_entries(paiv, entry_offset, false);
 
489
        if (entry_offset == NULL) {
 
490
                free_inherited_info(paiv);
 
491
                return NULL;
 
492
        }
 
493
        entry_offset = create_pai_v1_entries(paiv, entry_offset, true);
 
494
        if (entry_offset == NULL) {
 
495
                free_inherited_info(paiv);
 
496
                return NULL;
 
497
        }
 
498
 
 
499
        return paiv;
 
500
}
 
501
 
 
502
/************************************************************************
 
503
 Process v2 entries.
 
504
************************************************************************/
 
505
 
 
506
static const char *create_pai_v2_entries(struct pai_val *paiv,
 
507
                                unsigned int num_entries,
 
508
                                const char *entry_offset,
 
509
                                bool def_entry)
 
510
{
 
511
        unsigned int i;
 
512
 
 
513
        for (i = 0; i < num_entries; i++) {
 
514
                struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry);
 
515
                if (!paie) {
 
516
                        return NULL;
 
517
                }
 
518
 
 
519
                paie->ace_flags = CVAL(entry_offset,0);
 
520
 
 
521
                if (!get_pai_owner_type(paie, entry_offset+1)) {
 
522
                        return NULL;
 
523
                }
 
524
                if (!def_entry) {
 
525
                        DLIST_ADD(paiv->entry_list, paie);
 
526
                } else {
 
527
                        DLIST_ADD(paiv->def_entry_list, paie);
 
528
                }
 
529
                entry_offset += PAI_V2_ENTRY_LENGTH;
 
530
        }
 
531
        return entry_offset;
 
532
}
 
533
 
 
534
/************************************************************************
 
535
 Convert to in-memory format from version 2.
 
536
************************************************************************/
 
537
 
 
538
static struct pai_val *create_pai_val_v2(const char *buf, size_t size)
 
539
{
 
540
        const char *entry_offset;
 
541
        struct pai_val *paiv = NULL;
 
542
 
 
543
        if (!check_pai_ok_v2(buf, size)) {
 
544
                return NULL;
 
545
        }
 
546
 
 
547
        paiv = SMB_MALLOC_P(struct pai_val);
 
548
        if (!paiv) {
 
549
                return NULL;
 
550
        }
 
551
 
 
552
        memset(paiv, '\0', sizeof(struct pai_val));
 
553
 
 
554
        paiv->sd_type = SVAL(buf,PAI_V2_TYPE_OFFSET);
 
555
 
 
556
        paiv->num_entries = SVAL(buf,PAI_V2_NUM_ENTRIES_OFFSET);
 
557
        paiv->num_def_entries = SVAL(buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
 
558
 
 
559
        entry_offset = buf + PAI_V2_ENTRIES_BASE;
 
560
 
 
561
        DEBUG(10,("create_pai_val_v2: sd_type = 0x%x num_entries = %u, num_def_entries = %u\n",
 
562
                        (unsigned int)paiv->sd_type,
 
563
                        paiv->num_entries, paiv->num_def_entries ));
 
564
 
 
565
        entry_offset = create_pai_v2_entries(paiv, paiv->num_entries,
 
566
                                entry_offset, false);
 
567
        if (entry_offset == NULL) {
 
568
                free_inherited_info(paiv);
 
569
                return NULL;
 
570
        }
 
571
        entry_offset = create_pai_v2_entries(paiv, paiv->num_def_entries,
 
572
                                entry_offset, true);
 
573
        if (entry_offset == NULL) {
 
574
                free_inherited_info(paiv);
 
575
                return NULL;
 
576
        }
 
577
 
 
578
        return paiv;
 
579
}
 
580
 
 
581
/************************************************************************
 
582
 Convert to in-memory format - from either version 1 or 2.
 
583
************************************************************************/
 
584
 
 
585
static struct pai_val *create_pai_val(const char *buf, size_t size)
 
586
{
 
587
        if (size < 1) {
 
588
                return NULL;
 
589
        }
 
590
        if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V1_VERSION) {
 
591
                return create_pai_val_v1(buf, size);
 
592
        } else if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V2_VERSION) {
 
593
                return create_pai_val_v2(buf, size);
 
594
        } else {
 
595
                return NULL;
 
596
        }
 
597
}
 
598
 
 
599
/************************************************************************
 
600
 Load the user.SAMBA_PAI attribute.
 
601
************************************************************************/
 
602
 
 
603
static struct pai_val *fload_inherited_info(files_struct *fsp)
 
604
{
 
605
        char *pai_buf;
 
606
        size_t pai_buf_size = 1024;
 
607
        struct pai_val *paiv = NULL;
 
608
        ssize_t ret;
 
609
 
 
610
        if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
 
611
                return NULL;
 
612
        }
 
613
 
 
614
        if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) {
 
615
                return NULL;
 
616
        }
 
617
 
 
618
        do {
 
619
                if (fsp->fh->fd != -1) {
 
620
                        ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
 
621
                                        pai_buf, pai_buf_size);
 
622
                } else {
 
623
                        ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,
 
624
                                        pai_buf, pai_buf_size);
 
625
                }
 
626
 
 
627
                if (ret == -1) {
 
628
                        if (errno != ERANGE) {
 
629
                                break;
 
630
                        }
 
631
                        /* Buffer too small - enlarge it. */
 
632
                        pai_buf_size *= 2;
 
633
                        SAFE_FREE(pai_buf);
 
634
                        if (pai_buf_size > 1024*1024) {
 
635
                                return NULL; /* Limit malloc to 1mb. */
 
636
                        }
 
637
                        if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
 
638
                                return NULL;
 
639
                }
 
640
        } while (ret == -1);
 
641
 
 
642
        DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name));
 
643
 
 
644
        if (ret == -1) {
 
645
                /* No attribute or not supported. */
 
646
#if defined(ENOATTR)
 
647
                if (errno != ENOATTR)
 
648
                        DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
 
649
#else
 
650
                if (errno != ENOSYS)
 
651
                        DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
 
652
#endif
 
653
                SAFE_FREE(pai_buf);
 
654
                return NULL;
 
655
        }
 
656
 
 
657
        paiv = create_pai_val(pai_buf, ret);
 
658
 
 
659
        if (paiv) {
 
660
                DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n",
 
661
                        (unsigned int)paiv->sd_type,
 
662
                        fsp->fsp_name));
 
663
        }
 
664
 
 
665
        SAFE_FREE(pai_buf);
 
666
        return paiv;
 
667
}
 
668
 
 
669
/************************************************************************
 
670
 Load the user.SAMBA_PAI attribute.
 
671
************************************************************************/
 
672
 
 
673
static struct pai_val *load_inherited_info(const struct connection_struct *conn,
 
674
                                           const char *fname)
 
675
{
 
676
        char *pai_buf;
 
677
        size_t pai_buf_size = 1024;
 
678
        struct pai_val *paiv = NULL;
 
679
        ssize_t ret;
 
680
 
 
681
        if (!lp_map_acl_inherit(SNUM(conn))) {
 
682
                return NULL;
 
683
        }
 
684
 
 
685
        if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) {
 
686
                return NULL;
 
687
        }
 
688
 
 
689
        do {
 
690
                ret = SMB_VFS_GETXATTR(conn, fname,
 
691
                                       SAMBA_POSIX_INHERITANCE_EA_NAME,
 
692
                                       pai_buf, pai_buf_size);
 
693
 
 
694
                if (ret == -1) {
 
695
                        if (errno != ERANGE) {
 
696
                                break;
 
697
                        }
 
698
                        /* Buffer too small - enlarge it. */
 
699
                        pai_buf_size *= 2;
 
700
                        SAFE_FREE(pai_buf);
 
701
                        if (pai_buf_size > 1024*1024) {
 
702
                                return NULL; /* Limit malloc to 1mb. */
 
703
                        }
 
704
                        if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
 
705
                                return NULL;
 
706
                }
 
707
        } while (ret == -1);
 
708
 
 
709
        DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname));
 
710
 
 
711
        if (ret == -1) {
 
712
                /* No attribute or not supported. */
 
713
#if defined(ENOATTR)
 
714
                if (errno != ENOATTR)
 
715
                        DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
 
716
#else
 
717
                if (errno != ENOSYS)
 
718
                        DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
 
719
#endif
 
720
                SAFE_FREE(pai_buf);
 
721
                return NULL;
 
722
        }
 
723
 
 
724
        paiv = create_pai_val(pai_buf, ret);
 
725
 
 
726
        if (paiv) {
 
727
                DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n",
 
728
                        (unsigned int)paiv->sd_type,
 
729
                        fname));
 
730
        }
 
731
 
 
732
        SAFE_FREE(pai_buf);
 
733
        return paiv;
 
734
}
 
735
 
 
736
/****************************************************************************
 
737
 Functions to manipulate the internal ACE format.
 
738
****************************************************************************/
 
739
 
 
740
/****************************************************************************
 
741
 Count a linked list of canonical ACE entries.
 
742
****************************************************************************/
 
743
 
 
744
static size_t count_canon_ace_list( canon_ace *l_head )
 
745
{
 
746
        size_t count = 0;
 
747
        canon_ace *ace;
 
748
 
 
749
        for (ace = l_head; ace; ace = ace->next)
 
750
                count++;
 
751
 
 
752
        return count;
 
753
}
 
754
 
 
755
/****************************************************************************
 
756
 Free a linked list of canonical ACE entries.
 
757
****************************************************************************/
 
758
 
 
759
static void free_canon_ace_list( canon_ace *l_head )
 
760
{
 
761
        canon_ace *list, *next;
 
762
 
 
763
        for (list = l_head; list; list = next) {
 
764
                next = list->next;
 
765
                DLIST_REMOVE(l_head, list);
 
766
                SAFE_FREE(list);
 
767
        }
 
768
}
 
769
 
 
770
/****************************************************************************
 
771
 Function to duplicate a canon_ace entry.
 
772
****************************************************************************/
 
773
 
 
774
static canon_ace *dup_canon_ace( canon_ace *src_ace)
 
775
{
 
776
        canon_ace *dst_ace = SMB_MALLOC_P(canon_ace);
 
777
 
 
778
        if (dst_ace == NULL)
 
779
                return NULL;
 
780
 
 
781
        *dst_ace = *src_ace;
 
782
        dst_ace->prev = dst_ace->next = NULL;
 
783
        return dst_ace;
 
784
}
 
785
 
 
786
/****************************************************************************
 
787
 Print out a canon ace.
 
788
****************************************************************************/
 
789
 
 
790
static void print_canon_ace(canon_ace *pace, int num)
 
791
{
 
792
        dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
 
793
        dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee));
 
794
        if (pace->owner_type == UID_ACE) {
 
795
                const char *u_name = uidtoname(pace->unix_ug.uid);
 
796
                dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name );
 
797
        } else if (pace->owner_type == GID_ACE) {
 
798
                char *g_name = gidtoname(pace->unix_ug.gid);
 
799
                dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name );
 
800
        } else
 
801
                dbgtext( "other ");
 
802
        switch (pace->type) {
 
803
                case SMB_ACL_USER:
 
804
                        dbgtext( "SMB_ACL_USER ");
 
805
                        break;
 
806
                case SMB_ACL_USER_OBJ:
 
807
                        dbgtext( "SMB_ACL_USER_OBJ ");
 
808
                        break;
 
809
                case SMB_ACL_GROUP:
 
810
                        dbgtext( "SMB_ACL_GROUP ");
 
811
                        break;
 
812
                case SMB_ACL_GROUP_OBJ:
 
813
                        dbgtext( "SMB_ACL_GROUP_OBJ ");
 
814
                        break;
 
815
                case SMB_ACL_OTHER:
 
816
                        dbgtext( "SMB_ACL_OTHER ");
 
817
                        break;
 
818
                default:
 
819
                        dbgtext( "MASK " );
 
820
                        break;
 
821
        }
 
822
 
 
823
        dbgtext( "ace_flags = 0x%x ", (unsigned int)pace->ace_flags);
 
824
        dbgtext( "perms ");
 
825
        dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
 
826
        dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
 
827
        dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
 
828
}
 
829
 
 
830
/****************************************************************************
 
831
 Print out a canon ace list.
 
832
****************************************************************************/
 
833
 
 
834
static void print_canon_ace_list(const char *name, canon_ace *ace_list)
 
835
{
 
836
        int count = 0;
 
837
 
 
838
        if( DEBUGLVL( 10 )) {
 
839
                dbgtext( "print_canon_ace_list: %s\n", name );
 
840
                for (;ace_list; ace_list = ace_list->next, count++)
 
841
                        print_canon_ace(ace_list, count );
 
842
        }
 
843
}
 
844
 
 
845
/****************************************************************************
 
846
 Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
 
847
****************************************************************************/
 
848
 
 
849
static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset)
 
850
{
 
851
        mode_t ret = 0;
 
852
 
 
853
        ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);
 
854
        ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
 
855
        ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
 
856
 
 
857
        return ret;
 
858
}
 
859
 
 
860
/****************************************************************************
 
861
 Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
 
862
****************************************************************************/
 
863
 
 
864
static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
 
865
{
 
866
        mode_t ret = 0;
 
867
 
 
868
        if (mode & r_mask)
 
869
                ret |= S_IRUSR;
 
870
        if (mode & w_mask)
 
871
                ret |= S_IWUSR;
 
872
        if (mode & x_mask)
 
873
                ret |= S_IXUSR;
 
874
 
 
875
        return ret;
 
876
}
 
877
 
 
878
/****************************************************************************
 
879
 Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to
 
880
 an SMB_ACL_PERMSET_T.
 
881
****************************************************************************/
 
882
 
 
883
static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
 
884
{
 
885
        if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1)
 
886
                return -1;
 
887
        if (mode & S_IRUSR) {
 
888
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)
 
889
                        return -1;
 
890
        }
 
891
        if (mode & S_IWUSR) {
 
892
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)
 
893
                        return -1;
 
894
        }
 
895
        if (mode & S_IXUSR) {
 
896
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)
 
897
                        return -1;
 
898
        }
 
899
        return 0;
 
900
}
 
901
 
 
902
/****************************************************************************
 
903
 Function to create owner and group SIDs from a SMB_STRUCT_STAT.
 
904
****************************************************************************/
 
905
 
 
906
void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
 
907
{
 
908
        uid_to_sid( powner_sid, psbuf->st_uid );
 
909
        gid_to_sid( pgroup_sid, psbuf->st_gid );
 
910
}
 
911
 
 
912
/****************************************************************************
 
913
 Is the identity in two ACEs equal ? Check both SID and uid/gid.
 
914
****************************************************************************/
 
915
 
 
916
static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
 
917
{
 
918
        if (sid_equal(&ace1->trustee, &ace2->trustee)) {
 
919
                return True;
 
920
        }
 
921
        if (ace1->owner_type == ace2->owner_type) {
 
922
                if (ace1->owner_type == UID_ACE &&
 
923
                                ace1->unix_ug.uid == ace2->unix_ug.uid) {
 
924
                        return True;
 
925
                } else if (ace1->owner_type == GID_ACE &&
 
926
                                ace1->unix_ug.gid == ace2->unix_ug.gid) {
 
927
                        return True;
 
928
                }
 
929
        }
 
930
        return False;
 
931
}
 
932
 
 
933
/****************************************************************************
 
934
 Merge aces with a common sid - if both are allow or deny, OR the permissions together and
 
935
 delete the second one. If the first is deny, mask the permissions off and delete the allow
 
936
 if the permissions become zero, delete the deny if the permissions are non zero.
 
937
****************************************************************************/
 
938
 
 
939
static void merge_aces( canon_ace **pp_list_head )
 
940
{
 
941
        canon_ace *l_head = *pp_list_head;
 
942
        canon_ace *curr_ace_outer;
 
943
        canon_ace *curr_ace_outer_next;
 
944
 
 
945
        /*
 
946
         * First, merge allow entries with identical SIDs, and deny entries
 
947
         * with identical SIDs.
 
948
         */
 
949
 
 
950
        for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
 
951
                canon_ace *curr_ace;
 
952
                canon_ace *curr_ace_next;
 
953
 
 
954
                curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
 
955
 
 
956
                for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
 
957
 
 
958
                        curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
 
959
 
 
960
                        if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
 
961
                                (curr_ace->attr == curr_ace_outer->attr)) {
 
962
 
 
963
                                if( DEBUGLVL( 10 )) {
 
964
                                        dbgtext("merge_aces: Merging ACE's\n");
 
965
                                        print_canon_ace( curr_ace_outer, 0);
 
966
                                        print_canon_ace( curr_ace, 0);
 
967
                                }
 
968
 
 
969
                                /* Merge two allow or two deny ACE's. */
 
970
 
 
971
                                curr_ace_outer->perms |= curr_ace->perms;
 
972
                                DLIST_REMOVE(l_head, curr_ace);
 
973
                                SAFE_FREE(curr_ace);
 
974
                                curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
 
975
                        }
 
976
                }
 
977
        }
 
978
 
 
979
        /*
 
980
         * Now go through and mask off allow permissions with deny permissions.
 
981
         * We can delete either the allow or deny here as we know that each SID
 
982
         * appears only once in the list.
 
983
         */
 
984
 
 
985
        for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
 
986
                canon_ace *curr_ace;
 
987
                canon_ace *curr_ace_next;
 
988
 
 
989
                curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
 
990
 
 
991
                for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
 
992
 
 
993
                        curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
 
994
 
 
995
                        /*
 
996
                         * Subtract ACE's with different entries. Due to the ordering constraints
 
997
                         * we've put on the ACL, we know the deny must be the first one.
 
998
                         */
 
999
 
 
1000
                        if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
 
1001
                                (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
 
1002
 
 
1003
                                if( DEBUGLVL( 10 )) {
 
1004
                                        dbgtext("merge_aces: Masking ACE's\n");
 
1005
                                        print_canon_ace( curr_ace_outer, 0);
 
1006
                                        print_canon_ace( curr_ace, 0);
 
1007
                                }
 
1008
 
 
1009
                                curr_ace->perms &= ~curr_ace_outer->perms;
 
1010
 
 
1011
                                if (curr_ace->perms == 0) {
 
1012
 
 
1013
                                        /*
 
1014
                                         * The deny overrides the allow. Remove the allow.
 
1015
                                         */
 
1016
 
 
1017
                                        DLIST_REMOVE(l_head, curr_ace);
 
1018
                                        SAFE_FREE(curr_ace);
 
1019
                                        curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
 
1020
 
 
1021
                                } else {
 
1022
 
 
1023
                                        /*
 
1024
                                         * Even after removing permissions, there
 
1025
                                         * are still allow permissions - delete the deny.
 
1026
                                         * It is safe to delete the deny here,
 
1027
                                         * as we are guarenteed by the deny first
 
1028
                                         * ordering that all the deny entries for
 
1029
                                         * this SID have already been merged into one
 
1030
                                         * before we can get to an allow ace.
 
1031
                                         */
 
1032
 
 
1033
                                        DLIST_REMOVE(l_head, curr_ace_outer);
 
1034
                                        SAFE_FREE(curr_ace_outer);
 
1035
                                        break;
 
1036
                                }
 
1037
                        }
 
1038
 
 
1039
                } /* end for curr_ace */
 
1040
        } /* end for curr_ace_outer */
 
1041
 
 
1042
        /* We may have modified the list. */
 
1043
 
 
1044
        *pp_list_head = l_head;
 
1045
}
 
1046
 
 
1047
/****************************************************************************
 
1048
 Check if we need to return NT4.x compatible ACL entries.
 
1049
****************************************************************************/
 
1050
 
 
1051
bool nt4_compatible_acls(void)
 
1052
{
 
1053
        int compat = lp_acl_compatibility();
 
1054
 
 
1055
        if (compat == ACL_COMPAT_AUTO) {
 
1056
                enum remote_arch_types ra_type = get_remote_arch();
 
1057
 
 
1058
                /* Automatically adapt to client */
 
1059
                return (ra_type <= RA_WINNT);
 
1060
        } else
 
1061
                return (compat == ACL_COMPAT_WINNT);
 
1062
}
 
1063
 
 
1064
 
 
1065
/****************************************************************************
 
1066
 Map canon_ace perms to permission bits NT.
 
1067
 The attr element is not used here - we only process deny entries on set,
 
1068
 not get. Deny entries are implicit on get with ace->perms = 0.
 
1069
****************************************************************************/
 
1070
 
 
1071
static uint32_t map_canon_ace_perms(int snum,
 
1072
                                enum security_ace_type *pacl_type,
 
1073
                                mode_t perms,
 
1074
                                bool directory_ace)
 
1075
{
 
1076
        uint32_t nt_mask = 0;
 
1077
 
 
1078
        *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
 
1079
 
 
1080
        if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
 
1081
                if (directory_ace) {
 
1082
                        nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
 
1083
                } else {
 
1084
                        nt_mask = (UNIX_ACCESS_RWX & ~DELETE_ACCESS);
 
1085
                }
 
1086
        } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
 
1087
                /*
 
1088
                 * Windows NT refuses to display ACEs with no permissions in them (but
 
1089
                 * they are perfectly legal with Windows 2000). If the ACE has empty
 
1090
                 * permissions we cannot use 0, so we use the otherwise unused
 
1091
                 * WRITE_OWNER permission, which we ignore when we set an ACL.
 
1092
                 * We abstract this into a #define of UNIX_ACCESS_NONE to allow this
 
1093
                 * to be changed in the future.
 
1094
                 */
 
1095
 
 
1096
                if (nt4_compatible_acls())
 
1097
                        nt_mask = UNIX_ACCESS_NONE;
 
1098
                else
 
1099
                        nt_mask = 0;
 
1100
        } else {
 
1101
                if (directory_ace) {
 
1102
                        nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
 
1103
                        nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
 
1104
                        nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
 
1105
                } else {
 
1106
                        nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
 
1107
                        nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
 
1108
                        nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
 
1109
                }
 
1110
                if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
 
1111
                        nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER);
 
1112
                }
 
1113
        }
 
1114
 
 
1115
        DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
 
1116
                        (unsigned int)perms, (unsigned int)nt_mask ));
 
1117
 
 
1118
        return nt_mask;
 
1119
}
 
1120
 
 
1121
/****************************************************************************
 
1122
 Map NT perms to a UNIX mode_t.
 
1123
****************************************************************************/
 
1124
 
 
1125
#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
 
1126
#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
 
1127
#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
 
1128
 
 
1129
static mode_t map_nt_perms( uint32 *mask, int type)
 
1130
{
 
1131
        mode_t mode = 0;
 
1132
 
 
1133
        switch(type) {
 
1134
        case S_IRUSR:
 
1135
                if((*mask) & GENERIC_ALL_ACCESS)
 
1136
                        mode = S_IRUSR|S_IWUSR|S_IXUSR;
 
1137
                else {
 
1138
                        mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
 
1139
                        mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
 
1140
                        mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
 
1141
                }
 
1142
                break;
 
1143
        case S_IRGRP:
 
1144
                if((*mask) & GENERIC_ALL_ACCESS)
 
1145
                        mode = S_IRGRP|S_IWGRP|S_IXGRP;
 
1146
                else {
 
1147
                        mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
 
1148
                        mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
 
1149
                        mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
 
1150
                }
 
1151
                break;
 
1152
        case S_IROTH:
 
1153
                if((*mask) & GENERIC_ALL_ACCESS)
 
1154
                        mode = S_IROTH|S_IWOTH|S_IXOTH;
 
1155
                else {
 
1156
                        mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
 
1157
                        mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
 
1158
                        mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
 
1159
                }
 
1160
                break;
 
1161
        }
 
1162
 
 
1163
        return mode;
 
1164
}
 
1165
 
 
1166
/****************************************************************************
 
1167
 Unpack a SEC_DESC into a UNIX owner and group.
 
1168
****************************************************************************/
 
1169
 
 
1170
NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, const SEC_DESC *psd)
 
1171
{
 
1172
        DOM_SID owner_sid;
 
1173
        DOM_SID grp_sid;
 
1174
 
 
1175
        *puser = (uid_t)-1;
 
1176
        *pgrp = (gid_t)-1;
 
1177
 
 
1178
        if(security_info_sent == 0) {
 
1179
                DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
 
1180
                return NT_STATUS_OK;
 
1181
        }
 
1182
 
 
1183
        /*
 
1184
         * Validate the owner and group SID's.
 
1185
         */
 
1186
 
 
1187
        memset(&owner_sid, '\0', sizeof(owner_sid));
 
1188
        memset(&grp_sid, '\0', sizeof(grp_sid));
 
1189
 
 
1190
        DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
 
1191
 
 
1192
        /*
 
1193
         * Don't immediately fail if the owner sid cannot be validated.
 
1194
         * This may be a group chown only set.
 
1195
         */
 
1196
 
 
1197
        if (security_info_sent & OWNER_SECURITY_INFORMATION) {
 
1198
                sid_copy(&owner_sid, psd->owner_sid);
 
1199
                if (!sid_to_uid(&owner_sid, puser)) {
 
1200
                        if (lp_force_unknown_acl_user(snum)) {
 
1201
                                /* this allows take ownership to work
 
1202
                                 * reasonably */
 
1203
                                *puser = current_user.ut.uid;
 
1204
                        } else {
 
1205
                                DEBUG(3,("unpack_nt_owners: unable to validate"
 
1206
                                         " owner sid for %s\n",
 
1207
                                         sid_string_dbg(&owner_sid)));
 
1208
                                return NT_STATUS_INVALID_OWNER;
 
1209
                        }
 
1210
                }
 
1211
                DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
 
1212
                         (unsigned int)*puser ));
 
1213
        }
 
1214
 
 
1215
        /*
 
1216
         * Don't immediately fail if the group sid cannot be validated.
 
1217
         * This may be an owner chown only set.
 
1218
         */
 
1219
 
 
1220
        if (security_info_sent & GROUP_SECURITY_INFORMATION) {
 
1221
                sid_copy(&grp_sid, psd->group_sid);
 
1222
                if (!sid_to_gid( &grp_sid, pgrp)) {
 
1223
                        if (lp_force_unknown_acl_user(snum)) {
 
1224
                                /* this allows take group ownership to work
 
1225
                                 * reasonably */
 
1226
                                *pgrp = current_user.ut.gid;
 
1227
                        } else {
 
1228
                                DEBUG(3,("unpack_nt_owners: unable to validate"
 
1229
                                         " group sid.\n"));
 
1230
                                return NT_STATUS_INVALID_OWNER;
 
1231
                        }
 
1232
                }
 
1233
                DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n",
 
1234
                         (unsigned int)*pgrp));
 
1235
        }
 
1236
 
 
1237
        DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
 
1238
 
 
1239
        return NT_STATUS_OK;
 
1240
}
 
1241
 
 
1242
/****************************************************************************
 
1243
 Ensure the enforced permissions for this share apply.
 
1244
****************************************************************************/
 
1245
 
 
1246
static void apply_default_perms(const struct share_params *params,
 
1247
                                const bool is_directory, canon_ace *pace,
 
1248
                                mode_t type)
 
1249
{
 
1250
        mode_t and_bits = (mode_t)0;
 
1251
        mode_t or_bits = (mode_t)0;
 
1252
 
 
1253
        /* Get the initial bits to apply. */
 
1254
 
 
1255
        if (is_directory) {
 
1256
                and_bits = lp_dir_security_mask(params->service);
 
1257
                or_bits = lp_force_dir_security_mode(params->service);
 
1258
        } else {
 
1259
                and_bits = lp_security_mask(params->service);
 
1260
                or_bits = lp_force_security_mode(params->service);
 
1261
        }
 
1262
 
 
1263
        /* Now bounce them into the S_USR space. */     
 
1264
        switch(type) {
 
1265
        case S_IRUSR:
 
1266
                /* Ensure owner has read access. */
 
1267
                pace->perms |= S_IRUSR;
 
1268
                if (is_directory)
 
1269
                        pace->perms |= (S_IWUSR|S_IXUSR);
 
1270
                and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
 
1271
                or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
 
1272
                break;
 
1273
        case S_IRGRP:
 
1274
                and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
 
1275
                or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
 
1276
                break;
 
1277
        case S_IROTH:
 
1278
                and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
 
1279
                or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
 
1280
                break;
 
1281
        }
 
1282
 
 
1283
        pace->perms = ((pace->perms & and_bits)|or_bits);
 
1284
}
 
1285
 
 
1286
/****************************************************************************
 
1287
 Check if a given uid/SID is in a group gid/SID. This is probably very
 
1288
 expensive and will need optimisation. A *lot* of optimisation :-). JRA.
 
1289
****************************************************************************/
 
1290
 
 
1291
static bool uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
 
1292
{
 
1293
        const char *u_name = NULL;
 
1294
 
 
1295
        /* "Everyone" always matches every uid. */
 
1296
 
 
1297
        if (sid_equal(&group_ace->trustee, &global_sid_World))
 
1298
                return True;
 
1299
 
 
1300
        /*
 
1301
         * if it's the current user, we already have the unix token
 
1302
         * and don't need to do the complex user_in_group_sid() call
 
1303
         */
 
1304
        if (uid_ace->unix_ug.uid == current_user.ut.uid) {
 
1305
                size_t i;
 
1306
 
 
1307
                if (group_ace->unix_ug.gid == current_user.ut.gid) {
 
1308
                        return True;
 
1309
                }
 
1310
 
 
1311
                for (i=0; i < current_user.ut.ngroups; i++) {
 
1312
                        if (group_ace->unix_ug.gid == current_user.ut.groups[i]) {
 
1313
                                return True;
 
1314
                        }
 
1315
                }
 
1316
        }
 
1317
 
 
1318
        /* u_name talloc'ed off tos. */
 
1319
        u_name = uidtoname(uid_ace->unix_ug.uid);
 
1320
        if (!u_name) {
 
1321
                return False;
 
1322
        }
 
1323
 
 
1324
        /*
 
1325
         * user_in_group_sid() uses create_token_from_username()
 
1326
         * which creates an artificial NT token given just a username,
 
1327
         * so this is not reliable for users from foreign domains
 
1328
         * exported by winbindd!
 
1329
         */
 
1330
        return user_in_group_sid(u_name, &group_ace->trustee);
 
1331
}
 
1332
 
 
1333
/****************************************************************************
 
1334
 A well formed POSIX file or default ACL has at least 3 entries, a 
 
1335
 SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
 
1336
 In addition, the owner must always have at least read access.
 
1337
 When using this call on get_acl, the pst struct is valid and contains
 
1338
 the mode of the file. When using this call on set_acl, the pst struct has
 
1339
 been modified to have a mode containing the default for this file or directory
 
1340
 type.
 
1341
****************************************************************************/
 
1342
 
 
1343
static bool ensure_canon_entry_valid(canon_ace **pp_ace,
 
1344
                                     const struct share_params *params,
 
1345
                                     const bool is_directory,
 
1346
                                                        const DOM_SID *pfile_owner_sid,
 
1347
                                                        const DOM_SID *pfile_grp_sid,
 
1348
                                                        const SMB_STRUCT_STAT *pst,
 
1349
                                                        bool setting_acl)
 
1350
{
 
1351
        canon_ace *pace;
 
1352
        bool got_user = False;
 
1353
        bool got_grp = False;
 
1354
        bool got_other = False;
 
1355
        canon_ace *pace_other = NULL;
 
1356
 
 
1357
        for (pace = *pp_ace; pace; pace = pace->next) {
 
1358
                if (pace->type == SMB_ACL_USER_OBJ) {
 
1359
 
 
1360
                        if (setting_acl)
 
1361
                                apply_default_perms(params, is_directory, pace, S_IRUSR);
 
1362
                        got_user = True;
 
1363
 
 
1364
                } else if (pace->type == SMB_ACL_GROUP_OBJ) {
 
1365
 
 
1366
                        /*
 
1367
                         * Ensure create mask/force create mode is respected on set.
 
1368
                         */
 
1369
 
 
1370
                        if (setting_acl)
 
1371
                                apply_default_perms(params, is_directory, pace, S_IRGRP);
 
1372
                        got_grp = True;
 
1373
 
 
1374
                } else if (pace->type == SMB_ACL_OTHER) {
 
1375
 
 
1376
                        /*
 
1377
                         * Ensure create mask/force create mode is respected on set.
 
1378
                         */
 
1379
 
 
1380
                        if (setting_acl)
 
1381
                                apply_default_perms(params, is_directory, pace, S_IROTH);
 
1382
                        got_other = True;
 
1383
                        pace_other = pace;
 
1384
                }
 
1385
        }
 
1386
 
 
1387
        if (!got_user) {
 
1388
                if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
 
1389
                        DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
 
1390
                        return False;
 
1391
                }
 
1392
 
 
1393
                ZERO_STRUCTP(pace);
 
1394
                pace->type = SMB_ACL_USER_OBJ;
 
1395
                pace->owner_type = UID_ACE;
 
1396
                pace->unix_ug.uid = pst->st_uid;
 
1397
                pace->trustee = *pfile_owner_sid;
 
1398
                pace->attr = ALLOW_ACE;
 
1399
 
 
1400
                if (setting_acl) {
 
1401
                        /* See if the owning user is in any of the other groups in
 
1402
                           the ACE. If so, OR in the permissions from that group. */
 
1403
 
 
1404
                        bool group_matched = False;
 
1405
                        canon_ace *pace_iter;
 
1406
 
 
1407
                        for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
 
1408
                                if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
 
1409
                                        if (uid_entry_in_group(pace, pace_iter)) {
 
1410
                                                pace->perms |= pace_iter->perms;
 
1411
                                                group_matched = True;
 
1412
                                        }
 
1413
                                }
 
1414
                        }
 
1415
 
 
1416
                        /* If we only got an "everyone" perm, just use that. */
 
1417
                        if (!group_matched) {
 
1418
                                if (got_other)
 
1419
                                        pace->perms = pace_other->perms;
 
1420
                                else
 
1421
                                        pace->perms = 0;
 
1422
                        }
 
1423
 
 
1424
                        apply_default_perms(params, is_directory, pace, S_IRUSR);
 
1425
                } else {
 
1426
                        pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
 
1427
                }
 
1428
 
 
1429
                DLIST_ADD(*pp_ace, pace);
 
1430
        }
 
1431
 
 
1432
        if (!got_grp) {
 
1433
                if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
 
1434
                        DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
 
1435
                        return False;
 
1436
                }
 
1437
 
 
1438
                ZERO_STRUCTP(pace);
 
1439
                pace->type = SMB_ACL_GROUP_OBJ;
 
1440
                pace->owner_type = GID_ACE;
 
1441
                pace->unix_ug.uid = pst->st_gid;
 
1442
                pace->trustee = *pfile_grp_sid;
 
1443
                pace->attr = ALLOW_ACE;
 
1444
                if (setting_acl) {
 
1445
                        /* If we only got an "everyone" perm, just use that. */
 
1446
                        if (got_other)
 
1447
                                pace->perms = pace_other->perms;
 
1448
                        else
 
1449
                                pace->perms = 0;
 
1450
                        apply_default_perms(params, is_directory, pace, S_IRGRP);
 
1451
                } else {
 
1452
                        pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
 
1453
                }
 
1454
 
 
1455
                DLIST_ADD(*pp_ace, pace);
 
1456
        }
 
1457
 
 
1458
        if (!got_other) {
 
1459
                if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
 
1460
                        DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
 
1461
                        return False;
 
1462
                }
 
1463
 
 
1464
                ZERO_STRUCTP(pace);
 
1465
                pace->type = SMB_ACL_OTHER;
 
1466
                pace->owner_type = WORLD_ACE;
 
1467
                pace->unix_ug.world = -1;
 
1468
                pace->trustee = global_sid_World;
 
1469
                pace->attr = ALLOW_ACE;
 
1470
                if (setting_acl) {
 
1471
                        pace->perms = 0;
 
1472
                        apply_default_perms(params, is_directory, pace, S_IROTH);
 
1473
                } else
 
1474
                        pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
 
1475
 
 
1476
                DLIST_ADD(*pp_ace, pace);
 
1477
        }
 
1478
 
 
1479
        return True;
 
1480
}
 
1481
 
 
1482
/****************************************************************************
 
1483
 Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries.
 
1484
 If it does not have them, check if there are any entries where the trustee is the
 
1485
 file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.
 
1486
****************************************************************************/
 
1487
 
 
1488
static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid)
 
1489
{
 
1490
        bool got_user_obj, got_group_obj;
 
1491
        canon_ace *current_ace;
 
1492
        int i, entries;
 
1493
 
 
1494
        entries = count_canon_ace_list(ace);
 
1495
        got_user_obj = False;
 
1496
        got_group_obj = False;
 
1497
 
 
1498
        for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
 
1499
                if (current_ace->type == SMB_ACL_USER_OBJ)
 
1500
                        got_user_obj = True;
 
1501
                else if (current_ace->type == SMB_ACL_GROUP_OBJ)
 
1502
                        got_group_obj = True;
 
1503
        }
 
1504
        if (got_user_obj && got_group_obj) {
 
1505
                DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));
 
1506
                return;
 
1507
        }
 
1508
 
 
1509
        for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
 
1510
                if (!got_user_obj && current_ace->owner_type == UID_ACE &&
 
1511
                                sid_equal(&current_ace->trustee, pfile_owner_sid)) {
 
1512
                        current_ace->type = SMB_ACL_USER_OBJ;
 
1513
                        got_user_obj = True;
 
1514
                }
 
1515
                if (!got_group_obj && current_ace->owner_type == GID_ACE &&
 
1516
                                sid_equal(&current_ace->trustee, pfile_grp_sid)) {
 
1517
                        current_ace->type = SMB_ACL_GROUP_OBJ;
 
1518
                        got_group_obj = True;
 
1519
                }
 
1520
        }
 
1521
        if (!got_user_obj)
 
1522
                DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));
 
1523
        if (!got_group_obj)
 
1524
                DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));
 
1525
}
 
1526
 
 
1527
/****************************************************************************
 
1528
 Unpack a SEC_DESC into two canonical ace lists.
 
1529
****************************************************************************/
 
1530
 
 
1531
static bool create_canon_ace_lists(files_struct *fsp,
 
1532
                                        SMB_STRUCT_STAT *pst,
 
1533
                                        DOM_SID *pfile_owner_sid,
 
1534
                                        DOM_SID *pfile_grp_sid,
 
1535
                                        canon_ace **ppfile_ace,
 
1536
                                        canon_ace **ppdir_ace,
 
1537
                                        const SEC_ACL *dacl)
 
1538
{
 
1539
        bool all_aces_are_inherit_only = (fsp->is_directory ? True : False);
 
1540
        canon_ace *file_ace = NULL;
 
1541
        canon_ace *dir_ace = NULL;
 
1542
        canon_ace *current_ace = NULL;
 
1543
        bool got_dir_allow = False;
 
1544
        bool got_file_allow = False;
 
1545
        int i, j;
 
1546
 
 
1547
        *ppfile_ace = NULL;
 
1548
        *ppdir_ace = NULL;
 
1549
 
 
1550
        /*
 
1551
         * Convert the incoming ACL into a more regular form.
 
1552
         */
 
1553
 
 
1554
        for(i = 0; i < dacl->num_aces; i++) {
 
1555
                SEC_ACE *psa = &dacl->aces[i];
 
1556
 
 
1557
                if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
 
1558
                        DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
 
1559
                        return False;
 
1560
                }
 
1561
 
 
1562
                if (nt4_compatible_acls()) {
 
1563
                        /*
 
1564
                         * The security mask may be UNIX_ACCESS_NONE which should map into
 
1565
                         * no permissions (we overload the WRITE_OWNER bit for this) or it
 
1566
                         * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
 
1567
                         * to be so. Any other bits override the UNIX_ACCESS_NONE bit.
 
1568
                         */
 
1569
 
 
1570
                        /*
 
1571
                         * Convert GENERIC bits to specific bits.
 
1572
                         */
 
1573
 
 
1574
                        se_map_generic(&psa->access_mask, &file_generic_mapping);
 
1575
 
 
1576
                        psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
 
1577
 
 
1578
                        if(psa->access_mask != UNIX_ACCESS_NONE)
 
1579
                                psa->access_mask &= ~UNIX_ACCESS_NONE;
 
1580
                }
 
1581
        }
 
1582
 
 
1583
        /*
 
1584
         * Deal with the fact that NT 4.x re-writes the canonical format
 
1585
         * that we return for default ACLs. If a directory ACE is identical
 
1586
         * to a inherited directory ACE then NT changes the bits so that the
 
1587
         * first ACE is set to OI|IO and the second ACE for this SID is set
 
1588
         * to CI. We need to repair this. JRA.
 
1589
         */
 
1590
 
 
1591
        for(i = 0; i < dacl->num_aces; i++) {
 
1592
                SEC_ACE *psa1 = &dacl->aces[i];
 
1593
 
 
1594
                for (j = i + 1; j < dacl->num_aces; j++) {
 
1595
                        SEC_ACE *psa2 = &dacl->aces[j];
 
1596
 
 
1597
                        if (psa1->access_mask != psa2->access_mask)
 
1598
                                continue;
 
1599
 
 
1600
                        if (!sid_equal(&psa1->trustee, &psa2->trustee))
 
1601
                                continue;
 
1602
 
 
1603
                        /*
 
1604
                         * Ok - permission bits and SIDs are equal.
 
1605
                         * Check if flags were re-written.
 
1606
                         */
 
1607
 
 
1608
                        if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
 
1609
 
 
1610
                                psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
 
1611
                                psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
 
1612
 
 
1613
                        } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
 
1614
 
 
1615
                                psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
 
1616
                                psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
 
1617
 
 
1618
                        }
 
1619
                }
 
1620
        }
 
1621
 
 
1622
        for(i = 0; i < dacl->num_aces; i++) {
 
1623
                SEC_ACE *psa = &dacl->aces[i];
 
1624
 
 
1625
                /*
 
1626
                 * Create a cannon_ace entry representing this NT DACL ACE.
 
1627
                 */
 
1628
 
 
1629
                if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) {
 
1630
                        free_canon_ace_list(file_ace);
 
1631
                        free_canon_ace_list(dir_ace);
 
1632
                        DEBUG(0,("create_canon_ace_lists: malloc fail.\n"));
 
1633
                        return False;
 
1634
                }
 
1635
 
 
1636
                ZERO_STRUCTP(current_ace);
 
1637
 
 
1638
                sid_copy(&current_ace->trustee, &psa->trustee);
 
1639
 
 
1640
                /*
 
1641
                 * Try and work out if the SID is a user or group
 
1642
                 * as we need to flag these differently for POSIX.
 
1643
                 * Note what kind of a POSIX ACL this should map to.
 
1644
                 */
 
1645
 
 
1646
                if( sid_equal(&current_ace->trustee, &global_sid_World)) {
 
1647
                        current_ace->owner_type = WORLD_ACE;
 
1648
                        current_ace->unix_ug.world = -1;
 
1649
                        current_ace->type = SMB_ACL_OTHER;
 
1650
                } else if (sid_equal(&current_ace->trustee, &global_sid_Creator_Owner)) {
 
1651
                        current_ace->owner_type = UID_ACE;
 
1652
                        current_ace->unix_ug.uid = pst->st_uid;
 
1653
                        current_ace->type = SMB_ACL_USER_OBJ;
 
1654
 
 
1655
                        /*
 
1656
                         * The Creator Owner entry only specifies inheritable permissions,
 
1657
                         * never access permissions. WinNT doesn't always set the ACE to
 
1658
                         *INHERIT_ONLY, though.
 
1659
                         */
 
1660
 
 
1661
                        if (nt4_compatible_acls())
 
1662
                                psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
 
1663
                } else if (sid_equal(&current_ace->trustee, &global_sid_Creator_Group)) {
 
1664
                        current_ace->owner_type = GID_ACE;
 
1665
                        current_ace->unix_ug.gid = pst->st_gid;
 
1666
                        current_ace->type = SMB_ACL_GROUP_OBJ;
 
1667
 
 
1668
                        /*
 
1669
                         * The Creator Group entry only specifies inheritable permissions,
 
1670
                         * never access permissions. WinNT doesn't always set the ACE to
 
1671
                         *INHERIT_ONLY, though.
 
1672
                         */
 
1673
                        if (nt4_compatible_acls())
 
1674
                                psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
 
1675
 
 
1676
                } else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid)) {
 
1677
                        current_ace->owner_type = UID_ACE;
 
1678
                        /* If it's the owning user, this is a user_obj, not
 
1679
                         * a user. */
 
1680
                        if (current_ace->unix_ug.uid == pst->st_uid) {
 
1681
                                current_ace->type = SMB_ACL_USER_OBJ;
 
1682
                        } else {
 
1683
                                current_ace->type = SMB_ACL_USER;
 
1684
                        }
 
1685
                } else if (sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid)) {
 
1686
                        current_ace->owner_type = GID_ACE;
 
1687
                        /* If it's the primary group, this is a group_obj, not
 
1688
                         * a group. */
 
1689
                        if (current_ace->unix_ug.gid == pst->st_gid) {
 
1690
                                current_ace->type = SMB_ACL_GROUP_OBJ;
 
1691
                        } else {
 
1692
                                current_ace->type = SMB_ACL_GROUP;
 
1693
                        }
 
1694
                } else {
 
1695
                        /*
 
1696
                         * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc).
 
1697
                         */
 
1698
 
 
1699
                        if (non_mappable_sid(&psa->trustee)) {
 
1700
                                DEBUG(10, ("create_canon_ace_lists: ignoring "
 
1701
                                           "non-mappable SID %s\n",
 
1702
                                           sid_string_dbg(&psa->trustee)));
 
1703
                                SAFE_FREE(current_ace);
 
1704
                                continue;
 
1705
                        }
 
1706
 
 
1707
                        free_canon_ace_list(file_ace);
 
1708
                        free_canon_ace_list(dir_ace);
 
1709
                        DEBUG(0, ("create_canon_ace_lists: unable to map SID "
 
1710
                                  "%s to uid or gid.\n",
 
1711
                                  sid_string_dbg(&current_ace->trustee)));
 
1712
                        SAFE_FREE(current_ace);
 
1713
                        return False;
 
1714
                }
 
1715
 
 
1716
                /*
 
1717
                 * Map the given NT permissions into a UNIX mode_t containing only
 
1718
                 * S_I(R|W|X)USR bits.
 
1719
                 */
 
1720
 
 
1721
                current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR);
 
1722
                current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
 
1723
 
 
1724
                /* Store the ace_flag. */
 
1725
                current_ace->ace_flags = psa->flags;
 
1726
 
 
1727
                /*
 
1728
                 * Now add the created ace to either the file list, the directory
 
1729
                 * list, or both. We *MUST* preserve the order here (hence we use
 
1730
                 * DLIST_ADD_END) as NT ACLs are order dependent.
 
1731
                 */
 
1732
 
 
1733
                if (fsp->is_directory) {
 
1734
 
 
1735
                        /*
 
1736
                         * We can only add to the default POSIX ACE list if the ACE is
 
1737
                         * designed to be inherited by both files and directories.
 
1738
                         */
 
1739
 
 
1740
                        if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
 
1741
                                (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 
1742
 
 
1743
                                DLIST_ADD_END(dir_ace, current_ace, canon_ace *);
 
1744
 
 
1745
                                /*
 
1746
                                 * Note if this was an allow ace. We can't process
 
1747
                                 * any further deny ace's after this.
 
1748
                                 */
 
1749
 
 
1750
                                if (current_ace->attr == ALLOW_ACE)
 
1751
                                        got_dir_allow = True;
 
1752
 
 
1753
                                if ((current_ace->attr == DENY_ACE) && got_dir_allow) {
 
1754
                                        DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \
 
1755
Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
 
1756
                                        free_canon_ace_list(file_ace);
 
1757
                                        free_canon_ace_list(dir_ace);
 
1758
                                        return False;
 
1759
                                }       
 
1760
 
 
1761
                                if( DEBUGLVL( 10 )) {
 
1762
                                        dbgtext("create_canon_ace_lists: adding dir ACL:\n");
 
1763
                                        print_canon_ace( current_ace, 0);
 
1764
                                }
 
1765
 
 
1766
                                /*
 
1767
                                 * If this is not an inherit only ACE we need to add a duplicate
 
1768
                                 * to the file acl.
 
1769
                                 */
 
1770
 
 
1771
                                if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
 
1772
                                        canon_ace *dup_ace = dup_canon_ace(current_ace);
 
1773
 
 
1774
                                        if (!dup_ace) {
 
1775
                                                DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
 
1776
                                                free_canon_ace_list(file_ace);
 
1777
                                                free_canon_ace_list(dir_ace);
 
1778
                                                return False;
 
1779
                                        }
 
1780
 
 
1781
                                        /*
 
1782
                                         * We must not free current_ace here as its
 
1783
                                         * pointer is now owned by the dir_ace list.
 
1784
                                         */
 
1785
                                        current_ace = dup_ace;
 
1786
                                } else {
 
1787
                                        /*
 
1788
                                         * We must not free current_ace here as its
 
1789
                                         * pointer is now owned by the dir_ace list.
 
1790
                                         */
 
1791
                                        current_ace = NULL;
 
1792
                                }
 
1793
                        }
 
1794
                }
 
1795
 
 
1796
                /*
 
1797
                 * Only add to the file ACL if not inherit only.
 
1798
                 */
 
1799
 
 
1800
                if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
 
1801
                        DLIST_ADD_END(file_ace, current_ace, canon_ace *);
 
1802
 
 
1803
                        /*
 
1804
                         * Note if this was an allow ace. We can't process
 
1805
                         * any further deny ace's after this.
 
1806
                         */
 
1807
 
 
1808
                        if (current_ace->attr == ALLOW_ACE)
 
1809
                                got_file_allow = True;
 
1810
 
 
1811
                        if ((current_ace->attr == DENY_ACE) && got_file_allow) {
 
1812
                                DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \
 
1813
Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
 
1814
                                free_canon_ace_list(file_ace);
 
1815
                                free_canon_ace_list(dir_ace);
 
1816
                                return False;
 
1817
                        }       
 
1818
 
 
1819
                        if( DEBUGLVL( 10 )) {
 
1820
                                dbgtext("create_canon_ace_lists: adding file ACL:\n");
 
1821
                                print_canon_ace( current_ace, 0);
 
1822
                        }
 
1823
                        all_aces_are_inherit_only = False;
 
1824
                        /*
 
1825
                         * We must not free current_ace here as its
 
1826
                         * pointer is now owned by the file_ace list.
 
1827
                         */
 
1828
                        current_ace = NULL;
 
1829
                }
 
1830
 
 
1831
                /*
 
1832
                 * Free if ACE was not added.
 
1833
                 */
 
1834
 
 
1835
                SAFE_FREE(current_ace);
 
1836
        }
 
1837
 
 
1838
        if (fsp->is_directory && all_aces_are_inherit_only) {
 
1839
                /*
 
1840
                 * Windows 2000 is doing one of these weird 'inherit acl'
 
1841
                 * traverses to conserve NTFS ACL resources. Just pretend
 
1842
                 * there was no DACL sent. JRA.
 
1843
                 */
 
1844
 
 
1845
                DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n"));
 
1846
                free_canon_ace_list(file_ace);
 
1847
                free_canon_ace_list(dir_ace);
 
1848
                file_ace = NULL;
 
1849
                dir_ace = NULL;
 
1850
        } else {
 
1851
                /*
 
1852
                 * Check if we have SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries in each
 
1853
                 * ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP
 
1854
                 * entries can be converted to *_OBJ. Usually we will already have these
 
1855
                 * entries in the Default ACL, and the Access ACL will not have them.
 
1856
                 */
 
1857
                if (file_ace) {
 
1858
                        check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
 
1859
                }
 
1860
                if (dir_ace) {
 
1861
                        check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid);
 
1862
                }
 
1863
        }
 
1864
 
 
1865
        *ppfile_ace = file_ace;
 
1866
        *ppdir_ace = dir_ace;
 
1867
 
 
1868
        return True;
 
1869
}
 
1870
 
 
1871
/****************************************************************************
 
1872
 ASCII art time again... JRA :-).
 
1873
 
 
1874
 We have 4 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
 
1875
 we insist the ACL is in canonical form (ie. all DENY entries preceede ALLOW
 
1876
 entries). Secondly, the merge code has ensured that all duplicate SID entries for
 
1877
 allow or deny have been merged, so the same SID can only appear once in the deny
 
1878
 list or once in the allow list.
 
1879
 
 
1880
 We then process as follows :
 
1881
 
 
1882
 ---------------------------------------------------------------------------
 
1883
 First pass - look for a Everyone DENY entry.
 
1884
 
 
1885
 If it is deny all (rwx) trunate the list at this point.
 
1886
 Else, walk the list from this point and use the deny permissions of this
 
1887
 entry as a mask on all following allow entries. Finally, delete
 
1888
 the Everyone DENY entry (we have applied it to everything possible).
 
1889
 
 
1890
 In addition, in this pass we remove any DENY entries that have 
 
1891
 no permissions (ie. they are a DENY nothing).
 
1892
 ---------------------------------------------------------------------------
 
1893
 Second pass - only deal with deny user entries.
 
1894
 
 
1895
 DENY user1 (perms XXX)
 
1896
 
 
1897
 new_perms = 0
 
1898
 for all following allow group entries where user1 is in group
 
1899
        new_perms |= group_perms;
 
1900
 
 
1901
 user1 entry perms = new_perms & ~ XXX;
 
1902
 
 
1903
 Convert the deny entry to an allow entry with the new perms and
 
1904
 push to the end of the list. Note if the user was in no groups
 
1905
 this maps to a specific allow nothing entry for this user.
 
1906
 
 
1907
 The common case from the NT ACL choser (userX deny all) is
 
1908
 optimised so we don't do the group lookup - we just map to
 
1909
 an allow nothing entry.
 
1910
 
 
1911
 What we're doing here is inferring the allow permissions the
 
1912
 person setting the ACE on user1 wanted by looking at the allow
 
1913
 permissions on the groups the user is currently in. This will
 
1914
 be a snapshot, depending on group membership but is the best
 
1915
 we can do and has the advantage of failing closed rather than
 
1916
 open.
 
1917
 ---------------------------------------------------------------------------
 
1918
 Third pass - only deal with deny group entries.
 
1919
 
 
1920
 DENY group1 (perms XXX)
 
1921
 
 
1922
 for all following allow user entries where user is in group1
 
1923
   user entry perms = user entry perms & ~ XXX;
 
1924
 
 
1925
 If there is a group Everyone allow entry with permissions YYY,
 
1926
 convert the group1 entry to an allow entry and modify its
 
1927
 permissions to be :
 
1928
 
 
1929
 new_perms = YYY & ~ XXX
 
1930
 
 
1931
 and push to the end of the list.
 
1932
 
 
1933
 If there is no group Everyone allow entry then convert the
 
1934
 group1 entry to a allow nothing entry and push to the end of the list.
 
1935
 
 
1936
 Note that the common case from the NT ACL choser (groupX deny all)
 
1937
 cannot be optimised here as we need to modify user entries who are
 
1938
 in the group to change them to a deny all also.
 
1939
 
 
1940
 What we're doing here is modifying the allow permissions of
 
1941
 user entries (which are more specific in POSIX ACLs) to mask
 
1942
 out the explicit deny set on the group they are in. This will
 
1943
 be a snapshot depending on current group membership but is the
 
1944
 best we can do and has the advantage of failing closed rather
 
1945
 than open.
 
1946
 ---------------------------------------------------------------------------
 
1947
 Fourth pass - cope with cumulative permissions.
 
1948
 
 
1949
 for all allow user entries, if there exists an allow group entry with
 
1950
 more permissive permissions, and the user is in that group, rewrite the
 
1951
 allow user permissions to contain both sets of permissions.
 
1952
 
 
1953
 Currently the code for this is #ifdef'ed out as these semantics make
 
1954
 no sense to me. JRA.
 
1955
 ---------------------------------------------------------------------------
 
1956
 
 
1957
 Note we *MUST* do the deny user pass first as this will convert deny user
 
1958
 entries into allow user entries which can then be processed by the deny
 
1959
 group pass.
 
1960
 
 
1961
 The above algorithm took a *lot* of thinking about - hence this
 
1962
 explaination :-). JRA.
 
1963
****************************************************************************/
 
1964
 
 
1965
/****************************************************************************
 
1966
 Process a canon_ace list entries. This is very complex code. We need
 
1967
 to go through and remove the "deny" permissions from any allow entry that matches
 
1968
 the id of this entry. We have already refused any NT ACL that wasn't in correct
 
1969
 order (DENY followed by ALLOW). If any allow entry ends up with zero permissions,
 
1970
 we just remove it (to fail safe). We have already removed any duplicate ace
 
1971
 entries. Treat an "Everyone" DENY_ACE as a special case - use it to mask all
 
1972
 allow entries.
 
1973
****************************************************************************/
 
1974
 
 
1975
static void process_deny_list( canon_ace **pp_ace_list )
 
1976
{
 
1977
        canon_ace *ace_list = *pp_ace_list;
 
1978
        canon_ace *curr_ace = NULL;
 
1979
        canon_ace *curr_ace_next = NULL;
 
1980
 
 
1981
        /* Pass 1 above - look for an Everyone, deny entry. */
 
1982
 
 
1983
        for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
 
1984
                canon_ace *allow_ace_p;
 
1985
 
 
1986
                curr_ace_next = curr_ace->next; /* So we can't lose the link. */
 
1987
 
 
1988
                if (curr_ace->attr != DENY_ACE)
 
1989
                        continue;
 
1990
 
 
1991
                if (curr_ace->perms == (mode_t)0) {
 
1992
 
 
1993
                        /* Deny nothing entry - delete. */
 
1994
 
 
1995
                        DLIST_REMOVE(ace_list, curr_ace);
 
1996
                        continue;
 
1997
                }
 
1998
 
 
1999
                if (!sid_equal(&curr_ace->trustee, &global_sid_World))
 
2000
                        continue;
 
2001
 
 
2002
                /* JRATEST - assert. */
 
2003
                SMB_ASSERT(curr_ace->owner_type == WORLD_ACE);
 
2004
 
 
2005
                if (curr_ace->perms == ALL_ACE_PERMS) {
 
2006
 
 
2007
                        /*
 
2008
                         * Optimisation. This is a DENY_ALL to Everyone. Truncate the
 
2009
                         * list at this point including this entry.
 
2010
                         */
 
2011
 
 
2012
                        canon_ace *prev_entry = curr_ace->prev;
 
2013
 
 
2014
                        free_canon_ace_list( curr_ace );
 
2015
                        if (prev_entry)
 
2016
                                prev_entry->next = NULL;
 
2017
                        else {
 
2018
                                /* We deleted the entire list. */
 
2019
                                ace_list = NULL;
 
2020
                        }
 
2021
                        break;
 
2022
                }
 
2023
 
 
2024
                for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
 
2025
 
 
2026
                        /* 
 
2027
                         * Only mask off allow entries.
 
2028
                         */
 
2029
 
 
2030
                        if (allow_ace_p->attr != ALLOW_ACE)
 
2031
                                continue;
 
2032
 
 
2033
                        allow_ace_p->perms &= ~curr_ace->perms;
 
2034
                }
 
2035
 
 
2036
                /*
 
2037
                 * Now it's been applied, remove it.
 
2038
                 */
 
2039
 
 
2040
                DLIST_REMOVE(ace_list, curr_ace);
 
2041
        }
 
2042
 
 
2043
        /* Pass 2 above - deal with deny user entries. */
 
2044
 
 
2045
        for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
 
2046
                mode_t new_perms = (mode_t)0;
 
2047
                canon_ace *allow_ace_p;
 
2048
 
 
2049
                curr_ace_next = curr_ace->next; /* So we can't lose the link. */
 
2050
 
 
2051
                if (curr_ace->attr != DENY_ACE)
 
2052
                        continue;
 
2053
 
 
2054
                if (curr_ace->owner_type != UID_ACE)
 
2055
                        continue;
 
2056
 
 
2057
                if (curr_ace->perms == ALL_ACE_PERMS) {
 
2058
 
 
2059
                        /*
 
2060
                         * Optimisation - this is a deny everything to this user.
 
2061
                         * Convert to an allow nothing and push to the end of the list.
 
2062
                         */
 
2063
 
 
2064
                        curr_ace->attr = ALLOW_ACE;
 
2065
                        curr_ace->perms = (mode_t)0;
 
2066
                        DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
 
2067
                        continue;
 
2068
                }
 
2069
 
 
2070
                for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
 
2071
 
 
2072
                        if (allow_ace_p->attr != ALLOW_ACE)
 
2073
                                continue;
 
2074
 
 
2075
                        /* We process GID_ACE and WORLD_ACE entries only. */
 
2076
 
 
2077
                        if (allow_ace_p->owner_type == UID_ACE)
 
2078
                                continue;
 
2079
 
 
2080
                        if (uid_entry_in_group( curr_ace, allow_ace_p))
 
2081
                                new_perms |= allow_ace_p->perms;
 
2082
                }
 
2083
 
 
2084
                /*
 
2085
                 * Convert to a allow entry, modify the perms and push to the end
 
2086
                 * of the list.
 
2087
                 */
 
2088
 
 
2089
                curr_ace->attr = ALLOW_ACE;
 
2090
                curr_ace->perms = (new_perms & ~curr_ace->perms);
 
2091
                DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
 
2092
        }
 
2093
 
 
2094
        /* Pass 3 above - deal with deny group entries. */
 
2095
 
 
2096
        for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
 
2097
                canon_ace *allow_ace_p;
 
2098
                canon_ace *allow_everyone_p = NULL;
 
2099
 
 
2100
                curr_ace_next = curr_ace->next; /* So we can't lose the link. */
 
2101
 
 
2102
                if (curr_ace->attr != DENY_ACE)
 
2103
                        continue;
 
2104
 
 
2105
                if (curr_ace->owner_type != GID_ACE)
 
2106
                        continue;
 
2107
 
 
2108
                for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
 
2109
 
 
2110
                        if (allow_ace_p->attr != ALLOW_ACE)
 
2111
                                continue;
 
2112
 
 
2113
                        /* Store a pointer to the Everyone allow, if it exists. */
 
2114
                        if (allow_ace_p->owner_type == WORLD_ACE)
 
2115
                                allow_everyone_p = allow_ace_p;
 
2116
 
 
2117
                        /* We process UID_ACE entries only. */
 
2118
 
 
2119
                        if (allow_ace_p->owner_type != UID_ACE)
 
2120
                                continue;
 
2121
 
 
2122
                        /* Mask off the deny group perms. */
 
2123
 
 
2124
                        if (uid_entry_in_group( allow_ace_p, curr_ace))
 
2125
                                allow_ace_p->perms &= ~curr_ace->perms;
 
2126
                }
 
2127
 
 
2128
                /*
 
2129
                 * Convert the deny to an allow with the correct perms and
 
2130
                 * push to the end of the list.
 
2131
                 */
 
2132
 
 
2133
                curr_ace->attr = ALLOW_ACE;
 
2134
                if (allow_everyone_p)
 
2135
                        curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
 
2136
                else
 
2137
                        curr_ace->perms = (mode_t)0;
 
2138
                DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
 
2139
        }
 
2140
 
 
2141
        /* Doing this fourth pass allows Windows semantics to be layered
 
2142
         * on top of POSIX semantics. I'm not sure if this is desirable.
 
2143
         * For example, in W2K ACLs there is no way to say, "Group X no
 
2144
         * access, user Y full access" if user Y is a member of group X.
 
2145
         * This seems completely broken semantics to me.... JRA.
 
2146
         */
 
2147
 
 
2148
#if 0
 
2149
        /* Pass 4 above - deal with allow entries. */
 
2150
 
 
2151
        for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
 
2152
                canon_ace *allow_ace_p;
 
2153
 
 
2154
                curr_ace_next = curr_ace->next; /* So we can't lose the link. */
 
2155
 
 
2156
                if (curr_ace->attr != ALLOW_ACE)
 
2157
                        continue;
 
2158
 
 
2159
                if (curr_ace->owner_type != UID_ACE)
 
2160
                        continue;
 
2161
 
 
2162
                for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {
 
2163
 
 
2164
                        if (allow_ace_p->attr != ALLOW_ACE)
 
2165
                                continue;
 
2166
 
 
2167
                        /* We process GID_ACE entries only. */
 
2168
 
 
2169
                        if (allow_ace_p->owner_type != GID_ACE)
 
2170
                                continue;
 
2171
 
 
2172
                        /* OR in the group perms. */
 
2173
 
 
2174
                        if (uid_entry_in_group( curr_ace, allow_ace_p))
 
2175
                                curr_ace->perms |= allow_ace_p->perms;
 
2176
                }
 
2177
        }
 
2178
#endif
 
2179
 
 
2180
        *pp_ace_list = ace_list;
 
2181
}
 
2182
 
 
2183
/****************************************************************************
 
2184
 Create a default mode that will be used if a security descriptor entry has
 
2185
 no user/group/world entries.
 
2186
****************************************************************************/
 
2187
 
 
2188
static mode_t create_default_mode(files_struct *fsp, bool interitable_mode)
 
2189
{
 
2190
        int snum = SNUM(fsp->conn);
 
2191
        mode_t and_bits = (mode_t)0;
 
2192
        mode_t or_bits = (mode_t)0;
 
2193
        mode_t mode = interitable_mode
 
2194
                ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name,
 
2195
                             NULL )
 
2196
                : S_IRUSR;
 
2197
 
 
2198
        if (fsp->is_directory)
 
2199
                mode |= (S_IWUSR|S_IXUSR);
 
2200
 
 
2201
        /*
 
2202
         * Now AND with the create mode/directory mode bits then OR with the
 
2203
         * force create mode/force directory mode bits.
 
2204
         */
 
2205
 
 
2206
        if (fsp->is_directory) {
 
2207
                and_bits = lp_dir_security_mask(snum);
 
2208
                or_bits = lp_force_dir_security_mode(snum);
 
2209
        } else {
 
2210
                and_bits = lp_security_mask(snum);
 
2211
                or_bits = lp_force_security_mode(snum);
 
2212
        }
 
2213
 
 
2214
        return ((mode & and_bits)|or_bits);
 
2215
}
 
2216
 
 
2217
/****************************************************************************
 
2218
 Unpack a SEC_DESC into two canonical ace lists. We don't depend on this
 
2219
 succeeding.
 
2220
****************************************************************************/
 
2221
 
 
2222
static bool unpack_canon_ace(files_struct *fsp,
 
2223
                                SMB_STRUCT_STAT *pst,
 
2224
                                DOM_SID *pfile_owner_sid,
 
2225
                                DOM_SID *pfile_grp_sid,
 
2226
                                canon_ace **ppfile_ace,
 
2227
                                canon_ace **ppdir_ace,
 
2228
                                uint32 security_info_sent,
 
2229
                                const SEC_DESC *psd)
 
2230
{
 
2231
        canon_ace *file_ace = NULL;
 
2232
        canon_ace *dir_ace = NULL;
 
2233
 
 
2234
        *ppfile_ace = NULL;
 
2235
        *ppdir_ace = NULL;
 
2236
 
 
2237
        if(security_info_sent == 0) {
 
2238
                DEBUG(0,("unpack_canon_ace: no security info sent !\n"));
 
2239
                return False;
 
2240
        }
 
2241
 
 
2242
        /*
 
2243
         * If no DACL then this is a chown only security descriptor.
 
2244
         */
 
2245
 
 
2246
        if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl)
 
2247
                return True;
 
2248
 
 
2249
        /*
 
2250
         * Now go through the DACL and create the canon_ace lists.
 
2251
         */
 
2252
 
 
2253
        if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
 
2254
                                                                &file_ace, &dir_ace, psd->dacl))
 
2255
                return False;
 
2256
 
 
2257
        if ((file_ace == NULL) && (dir_ace == NULL)) {
 
2258
                /* W2K traverse DACL set - ignore. */
 
2259
                return True;
 
2260
        }
 
2261
 
 
2262
        /*
 
2263
         * Go through the canon_ace list and merge entries
 
2264
         * belonging to identical users of identical allow or deny type.
 
2265
         * We can do this as all deny entries come first, followed by
 
2266
         * all allow entries (we have mandated this before accepting this acl).
 
2267
         */
 
2268
 
 
2269
        print_canon_ace_list( "file ace - before merge", file_ace);
 
2270
        merge_aces( &file_ace );
 
2271
 
 
2272
        print_canon_ace_list( "dir ace - before merge", dir_ace);
 
2273
        merge_aces( &dir_ace );
 
2274
 
 
2275
        /*
 
2276
         * NT ACLs are order dependent. Go through the acl lists and
 
2277
         * process DENY entries by masking the allow entries.
 
2278
         */
 
2279
 
 
2280
        print_canon_ace_list( "file ace - before deny", file_ace);
 
2281
        process_deny_list( &file_ace);
 
2282
 
 
2283
        print_canon_ace_list( "dir ace - before deny", dir_ace);
 
2284
        process_deny_list( &dir_ace);
 
2285
 
 
2286
        /*
 
2287
         * A well formed POSIX file or default ACL has at least 3 entries, a 
 
2288
         * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ
 
2289
         * and optionally a mask entry. Ensure this is the case.
 
2290
         */
 
2291
 
 
2292
        print_canon_ace_list( "file ace - before valid", file_ace);
 
2293
 
 
2294
        /*
 
2295
         * A default 3 element mode entry for a file should be r-- --- ---.
 
2296
         * A default 3 element mode entry for a directory should be rwx --- ---.
 
2297
         */
 
2298
 
 
2299
        pst->st_mode = create_default_mode(fsp, False);
 
2300
 
 
2301
        if (!ensure_canon_entry_valid(&file_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
 
2302
                free_canon_ace_list(file_ace);
 
2303
                free_canon_ace_list(dir_ace);
 
2304
                return False;
 
2305
        }
 
2306
 
 
2307
        print_canon_ace_list( "dir ace - before valid", dir_ace);
 
2308
 
 
2309
        /*
 
2310
         * A default inheritable 3 element mode entry for a directory should be the
 
2311
         * mode Samba will use to create a file within. Ensure user rwx bits are set if
 
2312
         * it's a directory.
 
2313
         */
 
2314
 
 
2315
        pst->st_mode = create_default_mode(fsp, True);
 
2316
 
 
2317
        if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
 
2318
                free_canon_ace_list(file_ace);
 
2319
                free_canon_ace_list(dir_ace);
 
2320
                return False;
 
2321
        }
 
2322
 
 
2323
        print_canon_ace_list( "file ace - return", file_ace);
 
2324
        print_canon_ace_list( "dir ace - return", dir_ace);
 
2325
 
 
2326
        *ppfile_ace = file_ace;
 
2327
        *ppdir_ace = dir_ace;
 
2328
        return True;
 
2329
 
 
2330
}
 
2331
 
 
2332
/******************************************************************************
 
2333
 When returning permissions, try and fit NT display
 
2334
 semantics if possible. Note the the canon_entries here must have been malloced.
 
2335
 The list format should be - first entry = owner, followed by group and other user
 
2336
 entries, last entry = other.
 
2337
 
 
2338
 Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries
 
2339
 are not ordered, and match on the most specific entry rather than walking a list,
 
2340
 then a simple POSIX permission of rw-r--r-- should really map to 5 entries,
 
2341
 
 
2342
 Entry 0: owner : deny all except read and write.
 
2343
 Entry 1: owner : allow read and write.
 
2344
 Entry 2: group : deny all except read.
 
2345
 Entry 3: group : allow read.
 
2346
 Entry 4: Everyone : allow read.
 
2347
 
 
2348
 But NT cannot display this in their ACL editor !
 
2349
********************************************************************************/
 
2350
 
 
2351
static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
 
2352
{
 
2353
        canon_ace *l_head = *pp_list_head;
 
2354
        canon_ace *owner_ace = NULL;
 
2355
        canon_ace *other_ace = NULL;
 
2356
        canon_ace *ace = NULL;
 
2357
 
 
2358
        for (ace = l_head; ace; ace = ace->next) {
 
2359
                if (ace->type == SMB_ACL_USER_OBJ)
 
2360
                        owner_ace = ace;
 
2361
                else if (ace->type == SMB_ACL_OTHER) {
 
2362
                        /* Last ace - this is "other" */
 
2363
                        other_ace = ace;
 
2364
                }
 
2365
        }
 
2366
 
 
2367
        if (!owner_ace || !other_ace) {
 
2368
                DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",
 
2369
                        filename ));
 
2370
                return;
 
2371
        }
 
2372
 
 
2373
        /*
 
2374
         * The POSIX algorithm applies to owner first, and other last,
 
2375
         * so ensure they are arranged in this order.
 
2376
         */
 
2377
 
 
2378
        if (owner_ace) {
 
2379
                DLIST_PROMOTE(l_head, owner_ace);
 
2380
        }
 
2381
 
 
2382
        if (other_ace) {
 
2383
                DLIST_DEMOTE(l_head, other_ace, canon_ace *);
 
2384
        }
 
2385
 
 
2386
        /* We have probably changed the head of the list. */
 
2387
 
 
2388
        *pp_list_head = l_head;
 
2389
}
 
2390
 
 
2391
/****************************************************************************
 
2392
 Create a linked list of canonical ACE entries.
 
2393
****************************************************************************/
 
2394
 
 
2395
static canon_ace *canonicalise_acl(struct connection_struct *conn,
 
2396
                                   const char *fname, SMB_ACL_T posix_acl,
 
2397
                                   const SMB_STRUCT_STAT *psbuf,
 
2398
                                   const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
 
2399
{
 
2400
        mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
 
2401
        canon_ace *l_head = NULL;
 
2402
        canon_ace *ace = NULL;
 
2403
        canon_ace *next_ace = NULL;
 
2404
        int entry_id = SMB_ACL_FIRST_ENTRY;
 
2405
        SMB_ACL_ENTRY_T entry;
 
2406
        size_t ace_count;
 
2407
 
 
2408
        while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
 
2409
                SMB_ACL_TAG_T tagtype;
 
2410
                SMB_ACL_PERMSET_T permset;
 
2411
                DOM_SID sid;
 
2412
                posix_id unix_ug;
 
2413
                enum ace_owner owner_type;
 
2414
 
 
2415
                entry_id = SMB_ACL_NEXT_ENTRY;
 
2416
 
 
2417
                /* Is this a MASK entry ? */
 
2418
                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
 
2419
                        continue;
 
2420
 
 
2421
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
 
2422
                        continue;
 
2423
 
 
2424
                /* Decide which SID to use based on the ACL type. */
 
2425
                switch(tagtype) {
 
2426
                        case SMB_ACL_USER_OBJ:
 
2427
                                /* Get the SID from the owner. */
 
2428
                                sid_copy(&sid, powner);
 
2429
                                unix_ug.uid = psbuf->st_uid;
 
2430
                                owner_type = UID_ACE;
 
2431
                                break;
 
2432
                        case SMB_ACL_USER:
 
2433
                                {
 
2434
                                        uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
 
2435
                                        if (puid == NULL) {
 
2436
                                                DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
 
2437
                                                continue;
 
2438
                                        }
 
2439
                                        /*
 
2440
                                         * A SMB_ACL_USER entry for the owner is shadowed by the
 
2441
                                         * SMB_ACL_USER_OBJ entry and Windows also cannot represent
 
2442
                                         * that entry, so we ignore it. We also don't create such
 
2443
                                         * entries out of the blue when setting ACLs, so a get/set
 
2444
                                         * cycle will drop them.
 
2445
                                         */
 
2446
                                        if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) {
 
2447
                                                SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
 
2448
                                                continue;
 
2449
                                        }
 
2450
                                        uid_to_sid( &sid, *puid);
 
2451
                                        unix_ug.uid = *puid;
 
2452
                                        owner_type = UID_ACE;
 
2453
                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
 
2454
                                        break;
 
2455
                                }
 
2456
                        case SMB_ACL_GROUP_OBJ:
 
2457
                                /* Get the SID from the owning group. */
 
2458
                                sid_copy(&sid, pgroup);
 
2459
                                unix_ug.gid = psbuf->st_gid;
 
2460
                                owner_type = GID_ACE;
 
2461
                                break;
 
2462
                        case SMB_ACL_GROUP:
 
2463
                                {
 
2464
                                        gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
 
2465
                                        if (pgid == NULL) {
 
2466
                                                DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
 
2467
                                                continue;
 
2468
                                        }
 
2469
                                        gid_to_sid( &sid, *pgid);
 
2470
                                        unix_ug.gid = *pgid;
 
2471
                                        owner_type = GID_ACE;
 
2472
                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
 
2473
                                        break;
 
2474
                                }
 
2475
                        case SMB_ACL_MASK:
 
2476
                                acl_mask = convert_permset_to_mode_t(conn, permset);
 
2477
                                continue; /* Don't count the mask as an entry. */
 
2478
                        case SMB_ACL_OTHER:
 
2479
                                /* Use the Everyone SID */
 
2480
                                sid = global_sid_World;
 
2481
                                unix_ug.world = -1;
 
2482
                                owner_type = WORLD_ACE;
 
2483
                                break;
 
2484
                        default:
 
2485
                                DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype));
 
2486
                                continue;
 
2487
                }
 
2488
 
 
2489
                /*
 
2490
                 * Add this entry to the list.
 
2491
                 */
 
2492
 
 
2493
                if ((ace = SMB_MALLOC_P(canon_ace)) == NULL)
 
2494
                        goto fail;
 
2495
 
 
2496
                ZERO_STRUCTP(ace);
 
2497
                ace->type = tagtype;
 
2498
                ace->perms = convert_permset_to_mode_t(conn, permset);
 
2499
                ace->attr = ALLOW_ACE;
 
2500
                ace->trustee = sid;
 
2501
                ace->unix_ug = unix_ug;
 
2502
                ace->owner_type = owner_type;
 
2503
                ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
 
2504
 
 
2505
                DLIST_ADD(l_head, ace);
 
2506
        }
 
2507
 
 
2508
        /*
 
2509
         * This next call will ensure we have at least a user/group/world set.
 
2510
         */
 
2511
 
 
2512
        if (!ensure_canon_entry_valid(&l_head, conn->params,
 
2513
                                      S_ISDIR(psbuf->st_mode), powner, pgroup,
 
2514
                                      psbuf, False))
 
2515
                goto fail;
 
2516
 
 
2517
        /*
 
2518
         * Now go through the list, masking the permissions with the
 
2519
         * acl_mask. Ensure all DENY Entries are at the start of the list.
 
2520
         */
 
2521
 
 
2522
        DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
 
2523
 
 
2524
        for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
 
2525
                next_ace = ace->next;
 
2526
 
 
2527
                /* Masks are only applied to entries other than USER_OBJ and OTHER. */
 
2528
                if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ)
 
2529
                        ace->perms &= acl_mask;
 
2530
 
 
2531
                if (ace->perms == 0) {
 
2532
                        DLIST_PROMOTE(l_head, ace);
 
2533
                }
 
2534
 
 
2535
                if( DEBUGLVL( 10 ) ) {
 
2536
                        print_canon_ace(ace, ace_count);
 
2537
                }
 
2538
        }
 
2539
 
 
2540
        arrange_posix_perms(fname,&l_head );
 
2541
 
 
2542
        print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head );
 
2543
 
 
2544
        return l_head;
 
2545
 
 
2546
  fail:
 
2547
 
 
2548
        free_canon_ace_list(l_head);
 
2549
        return NULL;
 
2550
}
 
2551
 
 
2552
/****************************************************************************
 
2553
 Check if the current user group list contains a given group.
 
2554
****************************************************************************/
 
2555
 
 
2556
static bool current_user_in_group(gid_t gid)
 
2557
{
 
2558
        int i;
 
2559
 
 
2560
        for (i = 0; i < current_user.ut.ngroups; i++) {
 
2561
                if (current_user.ut.groups[i] == gid) {
 
2562
                        return True;
 
2563
                }
 
2564
        }
 
2565
 
 
2566
        return False;
 
2567
}
 
2568
 
 
2569
/****************************************************************************
 
2570
 Should we override a deny ? Check 'acl group control' and 'dos filemode'.
 
2571
****************************************************************************/
 
2572
 
 
2573
static bool acl_group_override(connection_struct *conn,
 
2574
                                SMB_STRUCT_STAT *psbuf,
 
2575
                                const char *fname)
 
2576
{
 
2577
        if ((errno != EPERM) && (errno != EACCES)) {
 
2578
                return false;
 
2579
        }
 
2580
 
 
2581
        /* file primary group == user primary or supplementary group */
 
2582
        if (lp_acl_group_control(SNUM(conn)) &&
 
2583
                        current_user_in_group(psbuf->st_gid)) {
 
2584
                return true;
 
2585
        }
 
2586
 
 
2587
        /* user has writeable permission */
 
2588
        if (lp_dos_filemode(SNUM(conn)) &&
 
2589
                        can_write_to_file(conn, fname, psbuf)) {
 
2590
                return true;
 
2591
        }
 
2592
 
 
2593
        return false;
 
2594
}
 
2595
 
 
2596
/****************************************************************************
 
2597
 Attempt to apply an ACL to a file or directory.
 
2598
****************************************************************************/
 
2599
 
 
2600
static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool default_ace, SMB_STRUCT_STAT *psbuf, bool *pacl_set_support)
 
2601
{
 
2602
        connection_struct *conn = fsp->conn;
 
2603
        bool ret = False;
 
2604
        SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
 
2605
        canon_ace *p_ace;
 
2606
        int i;
 
2607
        SMB_ACL_ENTRY_T mask_entry;
 
2608
        bool got_mask_entry = False;
 
2609
        SMB_ACL_PERMSET_T mask_permset;
 
2610
        SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
 
2611
        bool needs_mask = False;
 
2612
        mode_t mask_perms = 0;
 
2613
 
 
2614
#if defined(POSIX_ACL_NEEDS_MASK)
 
2615
        /* HP-UX always wants to have a mask (called "class" there). */
 
2616
        needs_mask = True;
 
2617
#endif
 
2618
 
 
2619
        if (the_acl == NULL) {
 
2620
 
 
2621
                if (!no_acl_syscall_error(errno)) {
 
2622
                        /*
 
2623
                         * Only print this error message if we have some kind of ACL
 
2624
                         * support that's not working. Otherwise we would always get this.
 
2625
                         */
 
2626
                        DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n",
 
2627
                                default_ace ? "default" : "file", strerror(errno) ));
 
2628
                }
 
2629
                *pacl_set_support = False;
 
2630
                return False;
 
2631
        }
 
2632
 
 
2633
        if( DEBUGLVL( 10 )) {
 
2634
                dbgtext("set_canon_ace_list: setting ACL:\n");
 
2635
                for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
 
2636
                        print_canon_ace( p_ace, i);
 
2637
                }
 
2638
        }
 
2639
 
 
2640
        for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
 
2641
                SMB_ACL_ENTRY_T the_entry;
 
2642
                SMB_ACL_PERMSET_T the_permset;
 
2643
 
 
2644
                /*
 
2645
                 * ACLs only "need" an ACL_MASK entry if there are any named user or
 
2646
                 * named group entries. But if there is an ACL_MASK entry, it applies
 
2647
                 * to ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. Set the mask
 
2648
                 * so that it doesn't deny (i.e., mask off) any permissions.
 
2649
                 */
 
2650
 
 
2651
                if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) {
 
2652
                        needs_mask = True;
 
2653
                        mask_perms |= p_ace->perms;
 
2654
                } else if (p_ace->type == SMB_ACL_GROUP_OBJ) {
 
2655
                        mask_perms |= p_ace->perms;
 
2656
                }
 
2657
 
 
2658
                /*
 
2659
                 * Get the entry for this ACE.
 
2660
                 */
 
2661
 
 
2662
                if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
 
2663
                        DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
 
2664
                                i, strerror(errno) ));
 
2665
                        goto fail;
 
2666
                }
 
2667
 
 
2668
                if (p_ace->type == SMB_ACL_MASK) {
 
2669
                        mask_entry = the_entry;
 
2670
                        got_mask_entry = True;
 
2671
                }
 
2672
 
 
2673
                /*
 
2674
                 * Ok - we now know the ACL calls should be working, don't
 
2675
                 * allow fallback to chmod.
 
2676
                 */
 
2677
 
 
2678
                *pacl_set_support = True;
 
2679
 
 
2680
                /*
 
2681
                 * Initialise the entry from the canon_ace.
 
2682
                 */
 
2683
 
 
2684
                /*
 
2685
                 * First tell the entry what type of ACE this is.
 
2686
                 */
 
2687
 
 
2688
                if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) {
 
2689
                        DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
 
2690
                                i, strerror(errno) ));
 
2691
                        goto fail;
 
2692
                }
 
2693
 
 
2694
                /*
 
2695
                 * Only set the qualifier (user or group id) if the entry is a user
 
2696
                 * or group id ACE.
 
2697
                 */
 
2698
 
 
2699
                if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
 
2700
                        if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) {
 
2701
                                DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
 
2702
                                        i, strerror(errno) ));
 
2703
                                goto fail;
 
2704
                        }
 
2705
                }
 
2706
 
 
2707
                /*
 
2708
                 * Convert the mode_t perms in the canon_ace to a POSIX permset.
 
2709
                 */
 
2710
 
 
2711
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
 
2712
                        DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
 
2713
                                i, strerror(errno) ));
 
2714
                        goto fail;
 
2715
                }
 
2716
 
 
2717
                if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) {
 
2718
                        DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n",
 
2719
                                (unsigned int)p_ace->perms, i, strerror(errno) ));
 
2720
                        goto fail;
 
2721
                }
 
2722
 
 
2723
                /*
 
2724
                 * ..and apply them to the entry.
 
2725
                 */
 
2726
 
 
2727
                if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
 
2728
                        DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
 
2729
                                i, strerror(errno) ));
 
2730
                        goto fail;
 
2731
                }
 
2732
 
 
2733
                if( DEBUGLVL( 10 ))
 
2734
                        print_canon_ace( p_ace, i);
 
2735
 
 
2736
        }
 
2737
 
 
2738
        if (needs_mask && !got_mask_entry) {
 
2739
                if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) {
 
2740
                        DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
 
2741
                        goto fail;
 
2742
                }
 
2743
 
 
2744
                if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) {
 
2745
                        DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
 
2746
                        goto fail;
 
2747
                }
 
2748
 
 
2749
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) {
 
2750
                        DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
 
2751
                        goto fail;
 
2752
                }
 
2753
 
 
2754
                if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) {
 
2755
                        DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) ));
 
2756
                        goto fail;
 
2757
                }
 
2758
 
 
2759
                if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) {
 
2760
                        DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
 
2761
                        goto fail;
 
2762
                }
 
2763
        }
 
2764
 
 
2765
        /*
 
2766
         * Finally apply it to the file or directory.
 
2767
         */
 
2768
 
 
2769
        if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
 
2770
                if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
 
2771
                        /*
 
2772
                         * Some systems allow all the above calls and only fail with no ACL support
 
2773
                         * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
 
2774
                         */
 
2775
                        if (no_acl_syscall_error(errno)) {
 
2776
                                *pacl_set_support = False;
 
2777
                        }
 
2778
 
 
2779
                        if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
 
2780
                                int sret;
 
2781
 
 
2782
                                DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
 
2783
                                        fsp->fsp_name ));
 
2784
 
 
2785
                                become_root();
 
2786
                                sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
 
2787
                                unbecome_root();
 
2788
                                if (sret == 0) {
 
2789
                                        ret = True;     
 
2790
                                }
 
2791
                        }
 
2792
 
 
2793
                        if (ret == False) {
 
2794
                                DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
 
2795
                                                the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
 
2796
                                                fsp->fsp_name, strerror(errno) ));
 
2797
                                goto fail;
 
2798
                        }
 
2799
                }
 
2800
        } else {
 
2801
                if (SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl) == -1) {
 
2802
                        /*
 
2803
                         * Some systems allow all the above calls and only fail with no ACL support
 
2804
                         * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
 
2805
                         */
 
2806
                        if (no_acl_syscall_error(errno)) {
 
2807
                                *pacl_set_support = False;
 
2808
                        }
 
2809
 
 
2810
                        if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
 
2811
                                int sret;
 
2812
 
 
2813
                                DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
 
2814
                                        fsp->fsp_name ));
 
2815
 
 
2816
                                become_root();
 
2817
                                sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl);
 
2818
                                unbecome_root();
 
2819
                                if (sret == 0) {
 
2820
                                        ret = True;
 
2821
                                }
 
2822
                        }
 
2823
 
 
2824
                        if (ret == False) {
 
2825
                                DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
 
2826
                                                fsp->fsp_name, strerror(errno) ));
 
2827
                                goto fail;
 
2828
                        }
 
2829
                }
 
2830
        }
 
2831
 
 
2832
        ret = True;
 
2833
 
 
2834
  fail:
 
2835
 
 
2836
        if (the_acl != NULL) {
 
2837
                SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
 
2838
        }
 
2839
 
 
2840
        return ret;
 
2841
}
 
2842
 
 
2843
/****************************************************************************
 
2844
 Find a particular canon_ace entry.
 
2845
****************************************************************************/
 
2846
 
 
2847
static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, posix_id *id)
 
2848
{
 
2849
        while (list) {
 
2850
                if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) ||
 
2851
                                (type == SMB_ACL_USER  && id && id->uid == list->unix_ug.uid) ||
 
2852
                                (type == SMB_ACL_GROUP && id && id->gid == list->unix_ug.gid)))
 
2853
                        break;
 
2854
                list = list->next;
 
2855
        }
 
2856
        return list;
 
2857
}
 
2858
 
 
2859
/****************************************************************************
 
2860
 
 
2861
****************************************************************************/
 
2862
 
 
2863
SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
 
2864
{
 
2865
        SMB_ACL_ENTRY_T entry;
 
2866
 
 
2867
        if (!the_acl)
 
2868
                return NULL;
 
2869
        if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
 
2870
                SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
 
2871
                return NULL;
 
2872
        }
 
2873
        return the_acl;
 
2874
}
 
2875
 
 
2876
/****************************************************************************
 
2877
 Convert a canon_ace to a generic 3 element permission - if possible.
 
2878
****************************************************************************/
 
2879
 
 
2880
#define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 )
 
2881
 
 
2882
static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
 
2883
{
 
2884
        int snum = SNUM(fsp->conn);
 
2885
        size_t ace_count = count_canon_ace_list(file_ace_list);
 
2886
        canon_ace *ace_p;
 
2887
        canon_ace *owner_ace = NULL;
 
2888
        canon_ace *group_ace = NULL;
 
2889
        canon_ace *other_ace = NULL;
 
2890
        mode_t and_bits;
 
2891
        mode_t or_bits;
 
2892
 
 
2893
        if (ace_count != 3) {
 
2894
                DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \
 
2895
posix perms.\n", fsp->fsp_name ));
 
2896
                return False;
 
2897
        }
 
2898
 
 
2899
        for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
 
2900
                if (ace_p->owner_type == UID_ACE)
 
2901
                        owner_ace = ace_p;
 
2902
                else if (ace_p->owner_type == GID_ACE)
 
2903
                        group_ace = ace_p;
 
2904
                else if (ace_p->owner_type == WORLD_ACE)
 
2905
                        other_ace = ace_p;
 
2906
        }
 
2907
 
 
2908
        if (!owner_ace || !group_ace || !other_ace) {
 
2909
                DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n",
 
2910
                                fsp->fsp_name ));
 
2911
                return False;
 
2912
        }
 
2913
 
 
2914
        *posix_perms = (mode_t)0;
 
2915
 
 
2916
        *posix_perms |= owner_ace->perms;
 
2917
        *posix_perms |= MAP_PERM(group_ace->perms, S_IRUSR, S_IRGRP);
 
2918
        *posix_perms |= MAP_PERM(group_ace->perms, S_IWUSR, S_IWGRP);
 
2919
        *posix_perms |= MAP_PERM(group_ace->perms, S_IXUSR, S_IXGRP);
 
2920
        *posix_perms |= MAP_PERM(other_ace->perms, S_IRUSR, S_IROTH);
 
2921
        *posix_perms |= MAP_PERM(other_ace->perms, S_IWUSR, S_IWOTH);
 
2922
        *posix_perms |= MAP_PERM(other_ace->perms, S_IXUSR, S_IXOTH);
 
2923
 
 
2924
        /* The owner must have at least read access. */
 
2925
 
 
2926
        *posix_perms |= S_IRUSR;
 
2927
        if (fsp->is_directory)
 
2928
                *posix_perms |= (S_IWUSR|S_IXUSR);
 
2929
 
 
2930
        /* If requested apply the masks. */
 
2931
 
 
2932
        /* Get the initial bits to apply. */
 
2933
 
 
2934
        if (fsp->is_directory) {
 
2935
                and_bits = lp_dir_security_mask(snum);
 
2936
                or_bits = lp_force_dir_security_mode(snum);
 
2937
        } else {
 
2938
                and_bits = lp_security_mask(snum);
 
2939
                or_bits = lp_force_security_mode(snum);
 
2940
        }
 
2941
 
 
2942
        *posix_perms = (((*posix_perms) & and_bits)|or_bits);
 
2943
 
 
2944
        DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n",
 
2945
                (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms,
 
2946
                fsp->fsp_name ));
 
2947
 
 
2948
        return True;
 
2949
}
 
2950
 
 
2951
/****************************************************************************
 
2952
  Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and
 
2953
  a normal POSIX acl. Win2k needs these split acls re-merging into one ACL
 
2954
  with CI|OI set so it is inherited and also applies to the directory.
 
2955
  Based on code from "Jim McDonough" <jmcd@us.ibm.com>.
 
2956
****************************************************************************/
 
2957
 
 
2958
static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
 
2959
{
 
2960
        size_t i, j;
 
2961
 
 
2962
        for (i = 0; i < num_aces; i++) {
 
2963
                for (j = i+1; j < num_aces; j++) {
 
2964
                        uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
 
2965
                        uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
 
2966
                        bool i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
 
2967
                        bool j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
 
2968
 
 
2969
                        /* We know the lower number ACE's are file entries. */
 
2970
                        if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
 
2971
                                (nt_ace_list[i].size == nt_ace_list[j].size) &&
 
2972
                                (nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) &&
 
2973
                                sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
 
2974
                                (i_inh == j_inh) &&
 
2975
                                (i_flags_ni == 0) &&
 
2976
                                (j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT|
 
2977
                                                  SEC_ACE_FLAG_CONTAINER_INHERIT|
 
2978
                                                  SEC_ACE_FLAG_INHERIT_ONLY))) {
 
2979
                                /*
 
2980
                                 * W2K wants to have access allowed zero access ACE's
 
2981
                                 * at the end of the list. If the mask is zero, merge
 
2982
                                 * the non-inherited ACE onto the inherited ACE.
 
2983
                                 */
 
2984
 
 
2985
                                if (nt_ace_list[i].access_mask == 0) {
 
2986
                                        nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
 
2987
                                                                (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
 
2988
                                        if (num_aces - i - 1 > 0)
 
2989
                                                memmove(&nt_ace_list[i], &nt_ace_list[i+1], (num_aces-i-1) *
 
2990
                                                                sizeof(SEC_ACE));
 
2991
 
 
2992
                                        DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n",
 
2993
                                                (unsigned int)i, (unsigned int)j ));
 
2994
                                } else {
 
2995
                                        /*
 
2996
                                         * These are identical except for the flags.
 
2997
                                         * Merge the inherited ACE onto the non-inherited ACE.
 
2998
                                         */
 
2999
 
 
3000
                                        nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
 
3001
                                                                (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
 
3002
                                        if (num_aces - j - 1 > 0)
 
3003
                                                memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) *
 
3004
                                                                sizeof(SEC_ACE));
 
3005
 
 
3006
                                        DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n",
 
3007
                                                (unsigned int)j, (unsigned int)i ));
 
3008
                                }
 
3009
                                num_aces--;
 
3010
                                break;
 
3011
                        }
 
3012
                }
 
3013
        }
 
3014
 
 
3015
        return num_aces;
 
3016
}
 
3017
 
 
3018
/*
 
3019
 * Add or Replace ACE entry.
 
3020
 * In some cases we need to add a specific ACE for compatibility reasons.
 
3021
 * When doing that we must make sure we are not actually creating a duplicate
 
3022
 * entry. So we need to search whether an ACE entry already exist and eventually
 
3023
 * replacce the access mask, or add a completely new entry if none was found.
 
3024
 *
 
3025
 * This function assumes the array has enough space to add a new entry without
 
3026
 * any reallocation of memory.
 
3027
 */
 
3028
 
 
3029
static void add_or_replace_ace(SEC_ACE *nt_ace_list, size_t *num_aces,
 
3030
                                const DOM_SID *sid, enum security_ace_type type,
 
3031
                                uint32_t mask, uint8_t flags)
 
3032
{
 
3033
        int i;
 
3034
 
 
3035
        /* first search for a duplicate */
 
3036
        for (i = 0; i < *num_aces; i++) {
 
3037
                if (sid_equal(&nt_ace_list[i].trustee, sid) &&
 
3038
                    (nt_ace_list[i].flags == flags)) break;
 
3039
        }
 
3040
 
 
3041
        if (i < *num_aces) { /* found */
 
3042
                nt_ace_list[i].type = type;
 
3043
                nt_ace_list[i].access_mask = mask;
 
3044
                DEBUG(10, ("Replacing ACE %d with SID %s and flags %02x\n",
 
3045
                           i, sid_string_dbg(sid), flags));
 
3046
                return;
 
3047
        }
 
3048
 
 
3049
        /* not found, append it */
 
3050
        init_sec_ace(&nt_ace_list[(*num_aces)++], sid, type, mask, flags);
 
3051
}
 
3052
 
 
3053
 
 
3054
/****************************************************************************
 
3055
 Reply to query a security descriptor from an fsp. If it succeeds it allocates
 
3056
 the space for the return elements and returns the size needed to return the
 
3057
 security descriptor. This should be the only external function needed for
 
3058
 the UNIX style get ACL.
 
3059
****************************************************************************/
 
3060
 
 
3061
static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
 
3062
                                      const char *name,
 
3063
                                      const SMB_STRUCT_STAT *sbuf,
 
3064
                                      struct pai_val *pal,
 
3065
                                      SMB_ACL_T posix_acl,
 
3066
                                      SMB_ACL_T def_acl,
 
3067
                                      uint32_t security_info,
 
3068
                                      SEC_DESC **ppdesc)
 
3069
{
 
3070
        DOM_SID owner_sid;
 
3071
        DOM_SID group_sid;
 
3072
        size_t sd_size = 0;
 
3073
        SEC_ACL *psa = NULL;
 
3074
        size_t num_acls = 0;
 
3075
        size_t num_def_acls = 0;
 
3076
        size_t num_aces = 0;
 
3077
        canon_ace *file_ace = NULL;
 
3078
        canon_ace *dir_ace = NULL;
 
3079
        SEC_ACE *nt_ace_list = NULL;
 
3080
        size_t num_profile_acls = 0;
 
3081
        DOM_SID orig_owner_sid;
 
3082
        SEC_DESC *psd = NULL;
 
3083
        int i;
 
3084
 
 
3085
        /*
 
3086
         * Get the owner, group and world SIDs.
 
3087
         */
 
3088
 
 
3089
        create_file_sids(sbuf, &owner_sid, &group_sid);
 
3090
 
 
3091
        if (lp_profile_acls(SNUM(conn))) {
 
3092
                /* For WXP SP1 the owner must be administrators. */
 
3093
                sid_copy(&orig_owner_sid, &owner_sid);
 
3094
                sid_copy(&owner_sid, &global_sid_Builtin_Administrators);
 
3095
                sid_copy(&group_sid, &global_sid_Builtin_Users);
 
3096
                num_profile_acls = 3;
 
3097
        }
 
3098
 
 
3099
        if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) {
 
3100
 
 
3101
                /*
 
3102
                 * In the optimum case Creator Owner and Creator Group would be used for
 
3103
                 * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this
 
3104
                 * would lead to usability problems under Windows: The Creator entries
 
3105
                 * are only available in browse lists of directories and not for files;
 
3106
                 * additionally the identity of the owning group couldn't be determined.
 
3107
                 * We therefore use those identities only for Default ACLs. 
 
3108
                 */
 
3109
 
 
3110
                /* Create the canon_ace lists. */
 
3111
                file_ace = canonicalise_acl(conn, name, posix_acl, sbuf,
 
3112
                                            &owner_sid, &group_sid, pal,
 
3113
                                            SMB_ACL_TYPE_ACCESS);
 
3114
 
 
3115
                /* We must have *some* ACLS. */
 
3116
        
 
3117
                if (count_canon_ace_list(file_ace) == 0) {
 
3118
                        DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name));
 
3119
                        goto done;
 
3120
                }
 
3121
 
 
3122
                if (S_ISDIR(sbuf->st_mode) && def_acl) {
 
3123
                        dir_ace = canonicalise_acl(conn, name, def_acl,
 
3124
                                                   sbuf,
 
3125
                                                   &global_sid_Creator_Owner,
 
3126
                                                   &global_sid_Creator_Group,
 
3127
                                                   pal, SMB_ACL_TYPE_DEFAULT);
 
3128
                }
 
3129
 
 
3130
                /*
 
3131
                 * Create the NT ACE list from the canonical ace lists.
 
3132
                 */
 
3133
 
 
3134
                {
 
3135
                        canon_ace *ace;
 
3136
                        enum security_ace_type nt_acl_type;
 
3137
 
 
3138
                        if (nt4_compatible_acls() && dir_ace) {
 
3139
                                /*
 
3140
                                 * NT 4 chokes if an ACL contains an INHERIT_ONLY entry
 
3141
                                 * but no non-INHERIT_ONLY entry for one SID. So we only
 
3142
                                 * remove entries from the Access ACL if the
 
3143
                                 * corresponding Default ACL entries have also been
 
3144
                                 * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP
 
3145
                                 * are exceptions. We can do nothing
 
3146
                                 * intelligent if the Default ACL contains entries that
 
3147
                                 * are not also contained in the Access ACL, so this
 
3148
                                 * case will still fail under NT 4.
 
3149
                                 */
 
3150
 
 
3151
                                ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL);
 
3152
                                if (ace && !ace->perms) {
 
3153
                                        DLIST_REMOVE(dir_ace, ace);
 
3154
                                        SAFE_FREE(ace);
 
3155
 
 
3156
                                        ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL);
 
3157
                                        if (ace && !ace->perms) {
 
3158
                                                DLIST_REMOVE(file_ace, ace);
 
3159
                                                SAFE_FREE(ace);
 
3160
                                        }
 
3161
                                }
 
3162
 
 
3163
                                /*
 
3164
                                 * WinNT doesn't usually have Creator Group
 
3165
                                 * in browse lists, so we send this entry to
 
3166
                                 * WinNT even if it contains no relevant
 
3167
                                 * permissions. Once we can add
 
3168
                                 * Creator Group to browse lists we can
 
3169
                                 * re-enable this.
 
3170
                                 */
 
3171
 
 
3172
#if 0
 
3173
                                ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL);
 
3174
                                if (ace && !ace->perms) {
 
3175
                                        DLIST_REMOVE(dir_ace, ace);
 
3176
                                        SAFE_FREE(ace);
 
3177
                                }
 
3178
#endif
 
3179
 
 
3180
                                ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL);
 
3181
                                if (ace && !ace->perms) {
 
3182
                                        DLIST_REMOVE(file_ace, ace);
 
3183
                                        SAFE_FREE(ace);
 
3184
                                }
 
3185
                        }
 
3186
 
 
3187
                        num_acls = count_canon_ace_list(file_ace);
 
3188
                        num_def_acls = count_canon_ace_list(dir_ace);
 
3189
 
 
3190
                        /* Allocate the ace list. */
 
3191
                        if ((nt_ace_list = SMB_MALLOC_ARRAY(SEC_ACE,num_acls + num_profile_acls + num_def_acls)) == NULL) {
 
3192
                                DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
 
3193
                                goto done;
 
3194
                        }
 
3195
 
 
3196
                        memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) );
 
3197
 
 
3198
                        /*
 
3199
                         * Create the NT ACE list from the canonical ace lists.
 
3200
                         */
 
3201
 
 
3202
                        for (ace = file_ace; ace != NULL; ace = ace->next) {
 
3203
                                uint32_t acc = map_canon_ace_perms(SNUM(conn),
 
3204
                                                &nt_acl_type,
 
3205
                                                ace->perms,
 
3206
                                                S_ISDIR(sbuf->st_mode));
 
3207
                                init_sec_ace(&nt_ace_list[num_aces++],
 
3208
                                        &ace->trustee,
 
3209
                                        nt_acl_type,
 
3210
                                        acc,
 
3211
                                        ace->ace_flags);
 
3212
                        }
 
3213
 
 
3214
                        /* The User must have access to a profile share - even
 
3215
                         * if we can't map the SID. */
 
3216
                        if (lp_profile_acls(SNUM(conn))) {
 
3217
                                add_or_replace_ace(nt_ace_list, &num_aces,
 
3218
                                                   &global_sid_Builtin_Users,
 
3219
                                                   SEC_ACE_TYPE_ACCESS_ALLOWED,
 
3220
                                                   FILE_GENERIC_ALL, 0);
 
3221
                        }
 
3222
 
 
3223
                        for (ace = dir_ace; ace != NULL; ace = ace->next) {
 
3224
                                uint32_t acc = map_canon_ace_perms(SNUM(conn),
 
3225
                                                &nt_acl_type,
 
3226
                                                ace->perms,
 
3227
                                                S_ISDIR(sbuf->st_mode));
 
3228
                                init_sec_ace(&nt_ace_list[num_aces++],
 
3229
                                        &ace->trustee,
 
3230
                                        nt_acl_type,
 
3231
                                        acc,
 
3232
                                        ace->ace_flags |
 
3233
                                        SEC_ACE_FLAG_OBJECT_INHERIT|
 
3234
                                        SEC_ACE_FLAG_CONTAINER_INHERIT|
 
3235
                                        SEC_ACE_FLAG_INHERIT_ONLY);
 
3236
                        }
 
3237
 
 
3238
                        /* The User must have access to a profile share - even
 
3239
                         * if we can't map the SID. */
 
3240
                        if (lp_profile_acls(SNUM(conn))) {
 
3241
                                add_or_replace_ace(nt_ace_list, &num_aces,
 
3242
                                                &global_sid_Builtin_Users,
 
3243
                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
 
3244
                                                FILE_GENERIC_ALL,
 
3245
                                                SEC_ACE_FLAG_OBJECT_INHERIT |
 
3246
                                                SEC_ACE_FLAG_CONTAINER_INHERIT |
 
3247
                                                SEC_ACE_FLAG_INHERIT_ONLY);
 
3248
                        }
 
3249
 
 
3250
                        /*
 
3251
                         * Merge POSIX default ACLs and normal ACLs into one NT ACE.
 
3252
                         * Win2K needs this to get the inheritance correct when replacing ACLs
 
3253
                         * on a directory tree. Based on work by Jim @ IBM.
 
3254
                         */
 
3255
 
 
3256
                        num_aces = merge_default_aces(nt_ace_list, num_aces);
 
3257
 
 
3258
                        if (lp_profile_acls(SNUM(conn))) {
 
3259
                                for (i = 0; i < num_aces; i++) {
 
3260
                                        if (sid_equal(&nt_ace_list[i].trustee, &owner_sid)) {
 
3261
                                                add_or_replace_ace(nt_ace_list, &num_aces,
 
3262
                                                                   &orig_owner_sid,
 
3263
                                                                   nt_ace_list[i].type,
 
3264
                                                                   nt_ace_list[i].access_mask,
 
3265
                                                                   nt_ace_list[i].flags);
 
3266
                                                break;
 
3267
                                        }
 
3268
                                }
 
3269
                        }
 
3270
                }
 
3271
 
 
3272
                if (num_aces) {
 
3273
                        if((psa = make_sec_acl( talloc_tos(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
 
3274
                                DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
 
3275
                                goto done;
 
3276
                        }
 
3277
                }
 
3278
        } /* security_info & DACL_SECURITY_INFORMATION */
 
3279
 
 
3280
        psd = make_standard_sec_desc( talloc_tos(),
 
3281
                        (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL,
 
3282
                        (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL,
 
3283
                        psa,
 
3284
                        &sd_size);
 
3285
 
 
3286
        if(!psd) {
 
3287
                DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n"));
 
3288
                sd_size = 0;
 
3289
                goto done;
 
3290
        }
 
3291
 
 
3292
        /*
 
3293
         * Windows 2000: The DACL_PROTECTED flag in the security
 
3294
         * descriptor marks the ACL as non-inheriting, i.e., no
 
3295
         * ACEs from higher level directories propagate to this
 
3296
         * ACL. In the POSIX ACL model permissions are only
 
3297
         * inherited at file create time, so ACLs never contain
 
3298
         * any ACEs that are inherited dynamically. The DACL_PROTECTED
 
3299
         * flag doesn't seem to bother Windows NT.
 
3300
         * Always set this if map acl inherit is turned off.
 
3301
         */
 
3302
        if (pal == NULL || !lp_map_acl_inherit(SNUM(conn))) {
 
3303
                psd->type |= SEC_DESC_DACL_PROTECTED;
 
3304
        } else {
 
3305
                psd->type |= pal->sd_type;
 
3306
        }
 
3307
 
 
3308
        if (psd->dacl) {
 
3309
                dacl_sort_into_canonical_order(psd->dacl->aces, (unsigned int)psd->dacl->num_aces);
 
3310
        }
 
3311
 
 
3312
        *ppdesc = psd;
 
3313
 
 
3314
 done:
 
3315
 
 
3316
        if (posix_acl) {
 
3317
                SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
 
3318
        }
 
3319
        if (def_acl) {
 
3320
                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
 
3321
        }
 
3322
        free_canon_ace_list(file_ace);
 
3323
        free_canon_ace_list(dir_ace);
 
3324
        free_inherited_info(pal);
 
3325
        SAFE_FREE(nt_ace_list);
 
3326
 
 
3327
        return NT_STATUS_OK;
 
3328
}
 
3329
 
 
3330
NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
 
3331
                           SEC_DESC **ppdesc)
 
3332
{
 
3333
        SMB_STRUCT_STAT sbuf;
 
3334
        SMB_ACL_T posix_acl = NULL;
 
3335
        struct pai_val *pal;
 
3336
 
 
3337
        *ppdesc = NULL;
 
3338
 
 
3339
        DEBUG(10,("posix_fget_nt_acl: called for file %s\n", fsp->fsp_name ));
 
3340
 
 
3341
        /* can it happen that fsp_name == NULL ? */
 
3342
        if (fsp->is_directory ||  fsp->fh->fd == -1) {
 
3343
                return posix_get_nt_acl(fsp->conn, fsp->fsp_name,
 
3344
                                        security_info, ppdesc);
 
3345
        }
 
3346
 
 
3347
        /* Get the stat struct for the owner info. */
 
3348
        if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
 
3349
                return map_nt_error_from_unix(errno);
 
3350
        }
 
3351
 
 
3352
        /* Get the ACL from the fd. */
 
3353
        posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
 
3354
 
 
3355
        pal = fload_inherited_info(fsp);
 
3356
 
 
3357
        return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name, &sbuf, pal,
 
3358
                                       posix_acl, NULL, security_info, ppdesc);
 
3359
}
 
3360
 
 
3361
NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
 
3362
                          uint32_t security_info, SEC_DESC **ppdesc)
 
3363
{
 
3364
        SMB_STRUCT_STAT sbuf;
 
3365
        SMB_ACL_T posix_acl = NULL;
 
3366
        SMB_ACL_T def_acl = NULL;
 
3367
        struct pai_val *pal;
 
3368
        int ret;
 
3369
 
 
3370
        *ppdesc = NULL;
 
3371
 
 
3372
        DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
 
3373
 
 
3374
        /* Get the stat struct for the owner info. */
 
3375
        if (lp_posix_pathnames()) {
 
3376
                ret = SMB_VFS_LSTAT(conn, name, &sbuf);
 
3377
        } else {
 
3378
                ret = SMB_VFS_STAT(conn, name, &sbuf);
 
3379
        }
 
3380
        if(ret != 0) {
 
3381
                return map_nt_error_from_unix(errno);
 
3382
        }
 
3383
 
 
3384
        /* Get the ACL from the path. */
 
3385
        posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS);
 
3386
 
 
3387
        /* If it's a directory get the default POSIX ACL. */
 
3388
        if(S_ISDIR(sbuf.st_mode)) {
 
3389
                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT);
 
3390
                def_acl = free_empty_sys_acl(conn, def_acl);
 
3391
        }
 
3392
 
 
3393
        pal = load_inherited_info(conn, name);
 
3394
 
 
3395
        return posix_get_nt_acl_common(conn, name, &sbuf, pal, posix_acl,
 
3396
                                       def_acl, security_info, ppdesc);
 
3397
}
 
3398
 
 
3399
/****************************************************************************
 
3400
 Try to chown a file. We will be able to chown it under the following conditions.
 
3401
 
 
3402
  1) If we have root privileges, then it will just work.
 
3403
  2) If we have SeTakeOwnershipPrivilege we can change the user to the current user.
 
3404
  3) If we have SeRestorePrivilege we can change the user to any other user. 
 
3405
  4) If we have write permission to the file and dos_filemodes is set
 
3406
     then allow chown to the currently authenticated user.
 
3407
****************************************************************************/
 
3408
 
 
3409
int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
 
3410
{
 
3411
        int ret;
 
3412
        files_struct *fsp;
 
3413
        SMB_STRUCT_STAT st;
 
3414
        bool posix_paths = lp_posix_pathnames();
 
3415
 
 
3416
        if(!CAN_WRITE(conn)) {
 
3417
                return -1;
 
3418
        }
 
3419
 
 
3420
        /* Case (1). */
 
3421
        /* try the direct way first */
 
3422
        if (posix_paths) {
 
3423
                ret = SMB_VFS_LCHOWN(conn, fname, uid, gid);
 
3424
        } else {
 
3425
                ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
 
3426
        }
 
3427
        if (ret == 0)
 
3428
                return 0;
 
3429
 
 
3430
        /* Case (2) / (3) */
 
3431
        if (lp_enable_privileges()) {
 
3432
 
 
3433
                bool has_take_ownership_priv = user_has_privileges(current_user.nt_user_token,
 
3434
                                                              &se_take_ownership);
 
3435
                bool has_restore_priv = user_has_privileges(current_user.nt_user_token,
 
3436
                                                       &se_restore);
 
3437
 
 
3438
                /* Case (2) */
 
3439
                if ( ( has_take_ownership_priv && ( uid == current_user.ut.uid ) ) ||
 
3440
                /* Case (3) */
 
3441
                     ( has_restore_priv ) ) {
 
3442
 
 
3443
                        become_root();
 
3444
                        /* Keep the current file gid the same - take ownership doesn't imply group change. */
 
3445
                        ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
 
3446
                        unbecome_root();
 
3447
                        return ret;
 
3448
                }
 
3449
        }
 
3450
 
 
3451
        /* Case (4). */
 
3452
        if (!lp_dos_filemode(SNUM(conn))) {
 
3453
                errno = EPERM;
 
3454
                return -1;
 
3455
        }
 
3456
 
 
3457
        /* only allow chown to the current user. This is more secure,
 
3458
           and also copes with the case where the SID in a take ownership ACL is
 
3459
           a local SID on the users workstation
 
3460
        */
 
3461
        if (uid != current_user.ut.uid) {
 
3462
                errno = EPERM;
 
3463
                return -1;
 
3464
        }
 
3465
 
 
3466
        if (posix_paths) {
 
3467
                ret = SMB_VFS_LSTAT(conn,fname,&st);
 
3468
        } else {
 
3469
                ret = SMB_VFS_STAT(conn,fname,&st);
 
3470
        }
 
3471
        if (ret != 0) {
 
3472
                return -1;
 
3473
        }
 
3474
 
 
3475
        if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, &st, &fsp))) {
 
3476
                return -1;
 
3477
        }
 
3478
 
 
3479
        become_root();
 
3480
        /* Keep the current file gid the same. */
 
3481
        ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
 
3482
        unbecome_root();
 
3483
 
 
3484
        close_file_fchmod(NULL, fsp);
 
3485
 
 
3486
        return ret;
 
3487
}
 
3488
 
 
3489
#if 0
 
3490
/* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
 
3491
 
 
3492
/****************************************************************************
 
3493
 Take care of parent ACL inheritance.
 
3494
****************************************************************************/
 
3495
 
 
3496
NTSTATUS append_parent_acl(files_struct *fsp,
 
3497
                                const SEC_DESC *pcsd,
 
3498
                                SEC_DESC **pp_new_sd)
 
3499
{
 
3500
        SEC_DESC *parent_sd = NULL;
 
3501
        files_struct *parent_fsp = NULL;
 
3502
        TALLOC_CTX *mem_ctx = talloc_tos();
 
3503
        char *parent_name = NULL;
 
3504
        SEC_ACE *new_ace = NULL;
 
3505
        unsigned int num_aces = pcsd->dacl->num_aces;
 
3506
        SMB_STRUCT_STAT sbuf;
 
3507
        NTSTATUS status;
 
3508
        int info;
 
3509
        unsigned int i, j;
 
3510
        SEC_DESC *psd = dup_sec_desc(talloc_tos(), pcsd);
 
3511
        bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED);
 
3512
 
 
3513
        ZERO_STRUCT(sbuf);
 
3514
 
 
3515
        if (psd == NULL) {
 
3516
                return NT_STATUS_NO_MEMORY;
 
3517
        }
 
3518
 
 
3519
        if (!parent_dirname(mem_ctx, fsp->fsp_name, &parent_name, NULL)) {
 
3520
                return NT_STATUS_NO_MEMORY;
 
3521
        }
 
3522
 
 
3523
        status = SMB_VFS_CREATE_FILE(
 
3524
                fsp->conn,                              /* conn */
 
3525
                NULL,                                   /* req */
 
3526
                0,                                      /* root_dir_fid */
 
3527
                parent_name,                            /* fname */
 
3528
                0,                                      /* create_file_flags */
 
3529
                FILE_READ_ATTRIBUTES,                   /* access_mask */
 
3530
                FILE_SHARE_NONE,                        /* share_access */
 
3531
                FILE_OPEN,                              /* create_disposition*/
 
3532
                FILE_DIRECTORY_FILE,                    /* create_options */
 
3533
                0,                                      /* file_attributes */
 
3534
                INTERNAL_OPEN_ONLY,                     /* oplock_request */
 
3535
                0,                                      /* allocation_size */
 
3536
                NULL,                                   /* sd */
 
3537
                NULL,                                   /* ea_list */
 
3538
                &parent_fsp,                            /* result */
 
3539
                &info,                                  /* pinfo */
 
3540
                &sbuf);                                 /* psbuf */
 
3541
 
 
3542
        if (!NT_STATUS_IS_OK(status)) {
 
3543
                return status;
 
3544
        }
 
3545
 
 
3546
        status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name,
 
3547
                                    DACL_SECURITY_INFORMATION, &parent_sd );
 
3548
 
 
3549
        close_file(NULL, parent_fsp, NORMAL_CLOSE);
 
3550
 
 
3551
        if (!NT_STATUS_IS_OK(status)) {
 
3552
                return status;
 
3553
        }
 
3554
 
 
3555
        /*
 
3556
         * Make room for potentially all the ACLs from
 
3557
         * the parent. We used to add the ugw triple here,
 
3558
         * as we knew we were dealing with POSIX ACLs.
 
3559
         * We no longer need to do so as we can guarentee
 
3560
         * that a default ACL from the parent directory will
 
3561
         * be well formed for POSIX ACLs if it came from a
 
3562
         * POSIX ACL source, and if we're not writing to a
 
3563
         * POSIX ACL sink then we don't care if it's not well
 
3564
         * formed. JRA.
 
3565
         */
 
3566
 
 
3567
        num_aces += parent_sd->dacl->num_aces;
 
3568
 
 
3569
        if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE,
 
3570
                                        num_aces)) == NULL) {
 
3571
                return NT_STATUS_NO_MEMORY;
 
3572
        }
 
3573
 
 
3574
        /* Start by copying in all the given ACE entries. */
 
3575
        for (i = 0; i < psd->dacl->num_aces; i++) {
 
3576
                sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]);
 
3577
        }
 
3578
 
 
3579
        /*
 
3580
         * Note that we're ignoring "inherit permissions" here
 
3581
         * as that really only applies to newly created files. JRA.
 
3582
         */
 
3583
 
 
3584
        /* Finally append any inherited ACEs. */
 
3585
        for (j = 0; j < parent_sd->dacl->num_aces; j++) {
 
3586
                SEC_ACE *se = &parent_sd->dacl->aces[j];
 
3587
 
 
3588
                if (fsp->is_directory) {
 
3589
                        if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 
3590
                                /* Doesn't apply to a directory - ignore. */
 
3591
                                DEBUG(10,("append_parent_acl: directory %s "
 
3592
                                        "ignoring non container "
 
3593
                                        "inherit flags %u on ACE with sid %s "
 
3594
                                        "from parent %s\n",
 
3595
                                        fsp->fsp_name,
 
3596
                                        (unsigned int)se->flags,
 
3597
                                        sid_string_dbg(&se->trustee),
 
3598
                                        parent_name));
 
3599
                                continue;
 
3600
                        }
 
3601
                } else {
 
3602
                        if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
 
3603
                                /* Doesn't apply to a file - ignore. */
 
3604
                                DEBUG(10,("append_parent_acl: file %s "
 
3605
                                        "ignoring non object "
 
3606
                                        "inherit flags %u on ACE with sid %s "
 
3607
                                        "from parent %s\n",
 
3608
                                        fsp->fsp_name,
 
3609
                                        (unsigned int)se->flags,
 
3610
                                        sid_string_dbg(&se->trustee),
 
3611
                                        parent_name));
 
3612
                                continue;
 
3613
                        }
 
3614
                }
 
3615
 
 
3616
                if (is_dacl_protected) {
 
3617
                        /* If the DACL is protected it means we must
 
3618
                         * not overwrite an existing ACE entry with the
 
3619
                         * same SID. This is order N^2. Ouch :-(. JRA. */
 
3620
                        unsigned int k;
 
3621
                        for (k = 0; k < psd->dacl->num_aces; k++) {
 
3622
                                if (sid_equal(&psd->dacl->aces[k].trustee,
 
3623
                                                &se->trustee)) {
 
3624
                                        break;
 
3625
                                }
 
3626
                        }
 
3627
                        if (k < psd->dacl->num_aces) {
 
3628
                                /* SID matched. Ignore. */
 
3629
                                DEBUG(10,("append_parent_acl: path %s "
 
3630
                                        "ignoring ACE with protected sid %s "
 
3631
                                        "from parent %s\n",
 
3632
                                        fsp->fsp_name,
 
3633
                                        sid_string_dbg(&se->trustee),
 
3634
                                        parent_name));
 
3635
                                continue;
 
3636
                        }
 
3637
                }
 
3638
 
 
3639
                sec_ace_copy(&new_ace[i], se);
 
3640
                if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
 
3641
                        new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT);
 
3642
                }
 
3643
                new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE;
 
3644
 
 
3645
                if (fsp->is_directory) {
 
3646
                        /*
 
3647
                         * Strip off any inherit only. It's applied.
 
3648
                         */
 
3649
                        new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY);
 
3650
                        if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
 
3651
                                /* No further inheritance. */
 
3652
                                new_ace[i].flags &=
 
3653
                                        ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
 
3654
                                        SEC_ACE_FLAG_OBJECT_INHERIT);
 
3655
                        }
 
3656
                } else {
 
3657
                        /*
 
3658
                         * Strip off any container or inherit
 
3659
                         * flags, they can't apply to objects.
 
3660
                         */
 
3661
                        new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
 
3662
                                                SEC_ACE_FLAG_INHERIT_ONLY|
 
3663
                                                SEC_ACE_FLAG_NO_PROPAGATE_INHERIT);
 
3664
                }
 
3665
                i++;
 
3666
 
 
3667
                DEBUG(10,("append_parent_acl: path %s "
 
3668
                        "inheriting ACE with sid %s "
 
3669
                        "from parent %s\n",
 
3670
                        fsp->fsp_name,
 
3671
                        sid_string_dbg(&se->trustee),
 
3672
                        parent_name));
 
3673
        }
 
3674
 
 
3675
        psd->dacl->aces = new_ace;
 
3676
        psd->dacl->num_aces = i;
 
3677
        psd->type &= ~(SE_DESC_DACL_AUTO_INHERITED|
 
3678
                         SE_DESC_DACL_AUTO_INHERIT_REQ);
 
3679
 
 
3680
        *pp_new_sd = psd;
 
3681
        return status;
 
3682
}
 
3683
#endif
 
3684
 
 
3685
/****************************************************************************
 
3686
 Reply to set a security descriptor on an fsp. security_info_sent is the
 
3687
 description of the following NT ACL.
 
3688
 This should be the only external function needed for the UNIX style set ACL.
 
3689
****************************************************************************/
 
3690
 
 
3691
NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
 
3692
{
 
3693
        connection_struct *conn = fsp->conn;
 
3694
        uid_t user = (uid_t)-1;
 
3695
        gid_t grp = (gid_t)-1;
 
3696
        SMB_STRUCT_STAT sbuf;
 
3697
        DOM_SID file_owner_sid;
 
3698
        DOM_SID file_grp_sid;
 
3699
        canon_ace *file_ace_list = NULL;
 
3700
        canon_ace *dir_ace_list = NULL;
 
3701
        bool acl_perms = False;
 
3702
        mode_t orig_mode = (mode_t)0;
 
3703
        NTSTATUS status;
 
3704
        bool set_acl_as_root = false;
 
3705
        bool acl_set_support = false;
 
3706
        bool ret = false;
 
3707
        bool posix_paths = lp_posix_pathnames();
 
3708
        int sret;
 
3709
 
 
3710
        DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
 
3711
 
 
3712
        if (!CAN_WRITE(conn)) {
 
3713
                DEBUG(10,("set acl rejected on read-only share\n"));
 
3714
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
 
3715
        }
 
3716
 
 
3717
        /*
 
3718
         * Get the current state of the file.
 
3719
         */
 
3720
 
 
3721
        if(fsp->is_directory || fsp->fh->fd == -1) {
 
3722
                if (posix_paths) {
 
3723
                        sret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
 
3724
                } else {
 
3725
                        sret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
 
3726
                }
 
3727
                if (sret != 0) {
 
3728
                        return map_nt_error_from_unix(errno);
 
3729
                }
 
3730
        } else {
 
3731
                if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
 
3732
                        return map_nt_error_from_unix(errno);
 
3733
        }
 
3734
 
 
3735
        /* Save the original element we check against. */
 
3736
        orig_mode = sbuf.st_mode;
 
3737
 
 
3738
        /*
 
3739
         * Unpack the user/group/world id's.
 
3740
         */
 
3741
 
 
3742
        status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
 
3743
        if (!NT_STATUS_IS_OK(status)) {
 
3744
                return status;
 
3745
        }
 
3746
 
 
3747
        /*
 
3748
         * Do we need to chown ? If so this must be done first as the incoming
 
3749
         * CREATOR_OWNER acl will be relative to the *new* owner, not the old.
 
3750
         * Noticed by Simo.
 
3751
         */
 
3752
 
 
3753
        if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
 
3754
 
 
3755
                DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
 
3756
                                fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
 
3757
 
 
3758
                if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
 
3759
                        DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
 
3760
                                fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
 
3761
                        if (errno == EPERM) {
 
3762
                                return NT_STATUS_INVALID_OWNER;
 
3763
                        }
 
3764
                        return map_nt_error_from_unix(errno);
 
3765
                }
 
3766
 
 
3767
                /*
 
3768
                 * Recheck the current state of the file, which may have changed.
 
3769
                 * (suid/sgid bits, for instance)
 
3770
                 */
 
3771
 
 
3772
                if(fsp->is_directory) {
 
3773
                        if (posix_paths) {
 
3774
                                sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name, &sbuf);
 
3775
                        } else {
 
3776
                                sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
 
3777
                        }
 
3778
                        if (sret != 0) {
 
3779
                                return map_nt_error_from_unix(errno);
 
3780
                        }
 
3781
                } else {
 
3782
                        if(fsp->fh->fd == -1) {
 
3783
                                if (posix_paths) {
 
3784
                                        sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name, &sbuf);
 
3785
                                } else {
 
3786
                                        sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
 
3787
                                }
 
3788
                        } else {
 
3789
                                sret = SMB_VFS_FSTAT(fsp, &sbuf);
 
3790
                        }
 
3791
 
 
3792
                        if(sret != 0)
 
3793
                                return map_nt_error_from_unix(errno);
 
3794
                }
 
3795
 
 
3796
                /* Save the original element we check against. */
 
3797
                orig_mode = sbuf.st_mode;
 
3798
 
 
3799
                /* If we successfully chowned, we know we must
 
3800
                 * be able to set the acl, so do it as root.
 
3801
                 */
 
3802
                set_acl_as_root = true;
 
3803
        }
 
3804
 
 
3805
        create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
 
3806
 
 
3807
        acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
 
3808
                                        &file_ace_list, &dir_ace_list, security_info_sent, psd);
 
3809
 
 
3810
        /* Ignore W2K traverse DACL set. */
 
3811
        if (!file_ace_list && !dir_ace_list) {
 
3812
                return NT_STATUS_OK;
 
3813
        }
 
3814
 
 
3815
        if (!acl_perms) {
 
3816
                DEBUG(3,("set_nt_acl: cannot set permissions\n"));
 
3817
                free_canon_ace_list(file_ace_list);
 
3818
                free_canon_ace_list(dir_ace_list);
 
3819
                return NT_STATUS_ACCESS_DENIED;
 
3820
        }
 
3821
 
 
3822
        /*
 
3823
         * Only change security if we got a DACL.
 
3824
         */
 
3825
 
 
3826
        if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
 
3827
                free_canon_ace_list(file_ace_list);
 
3828
                free_canon_ace_list(dir_ace_list);
 
3829
                return NT_STATUS_OK;
 
3830
        }
 
3831
 
 
3832
        /*
 
3833
         * Try using the POSIX ACL set first. Fall back to chmod if
 
3834
         * we have no ACL support on this filesystem.
 
3835
         */
 
3836
 
 
3837
        if (acl_perms && file_ace_list) {
 
3838
                if (set_acl_as_root) {
 
3839
                        become_root();
 
3840
                }
 
3841
                ret = set_canon_ace_list(fsp, file_ace_list, False, &sbuf, &acl_set_support);
 
3842
                if (set_acl_as_root) {
 
3843
                        unbecome_root();
 
3844
                }
 
3845
                if (acl_set_support && ret == false) {
 
3846
                        DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
 
3847
                        free_canon_ace_list(file_ace_list);
 
3848
                        free_canon_ace_list(dir_ace_list);
 
3849
                        return map_nt_error_from_unix(errno);
 
3850
                }
 
3851
        }
 
3852
 
 
3853
        if (acl_perms && acl_set_support && fsp->is_directory) {
 
3854
                if (dir_ace_list) {
 
3855
                        if (set_acl_as_root) {
 
3856
                                become_root();
 
3857
                        }
 
3858
                        ret = set_canon_ace_list(fsp, dir_ace_list, True, &sbuf, &acl_set_support);
 
3859
                        if (set_acl_as_root) {
 
3860
                                unbecome_root();
 
3861
                        }
 
3862
                        if (ret == false) {
 
3863
                                DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
 
3864
                                free_canon_ace_list(file_ace_list);
 
3865
                                free_canon_ace_list(dir_ace_list);
 
3866
                                return map_nt_error_from_unix(errno);
 
3867
                        }
 
3868
                } else {
 
3869
                        /*
 
3870
                         * No default ACL - delete one if it exists.
 
3871
                         */
 
3872
 
 
3873
                        if (set_acl_as_root) {
 
3874
                                become_root();
 
3875
                        }
 
3876
                        sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
 
3877
                        if (set_acl_as_root) {
 
3878
                                unbecome_root();
 
3879
                        }
 
3880
                        if (sret == -1) {
 
3881
                                if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
 
3882
                                        DEBUG(5,("set_nt_acl: acl group control on and "
 
3883
                                                "current user in file %s primary group. Override delete_def_acl\n",
 
3884
                                                fsp->fsp_name ));
 
3885
 
 
3886
                                        become_root();
 
3887
                                        sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
 
3888
                                        unbecome_root();
 
3889
                                }
 
3890
 
 
3891
                                if (sret == -1) {
 
3892
                                        DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
 
3893
                                        free_canon_ace_list(file_ace_list);
 
3894
                                        free_canon_ace_list(dir_ace_list);
 
3895
                                        return map_nt_error_from_unix(errno);
 
3896
                                }
 
3897
                        }
 
3898
                }
 
3899
        }
 
3900
 
 
3901
        if (acl_set_support) {
 
3902
                if (set_acl_as_root) {
 
3903
                        become_root();
 
3904
                }
 
3905
                store_inheritance_attributes(fsp,
 
3906
                                file_ace_list,
 
3907
                                dir_ace_list,
 
3908
                                psd->type);
 
3909
                if (set_acl_as_root) {
 
3910
                        unbecome_root();
 
3911
                }
 
3912
        }
 
3913
 
 
3914
        /*
 
3915
         * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod.
 
3916
         */
 
3917
 
 
3918
        if(!acl_set_support && acl_perms) {
 
3919
                mode_t posix_perms;
 
3920
 
 
3921
                if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
 
3922
                        free_canon_ace_list(file_ace_list);
 
3923
                        free_canon_ace_list(dir_ace_list);
 
3924
                        DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
 
3925
                                fsp->fsp_name ));
 
3926
                        return NT_STATUS_ACCESS_DENIED;
 
3927
                }
 
3928
 
 
3929
                if (orig_mode != posix_perms) {
 
3930
                        DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
 
3931
                                fsp->fsp_name, (unsigned int)posix_perms ));
 
3932
 
 
3933
                        if (set_acl_as_root) {
 
3934
                                become_root();
 
3935
                        }
 
3936
                        sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
 
3937
                        if (set_acl_as_root) {
 
3938
                                unbecome_root();
 
3939
                        }
 
3940
                        if(sret == -1) {
 
3941
                                if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
 
3942
                                        DEBUG(5,("set_nt_acl: acl group control on and "
 
3943
                                                "current user in file %s primary group. Override chmod\n",
 
3944
                                                fsp->fsp_name ));
 
3945
 
 
3946
                                        become_root();
 
3947
                                        sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
 
3948
                                        unbecome_root();
 
3949
                                }
 
3950
 
 
3951
                                if (sret == -1) {
 
3952
                                        DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
 
3953
                                                fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
 
3954
                                        free_canon_ace_list(file_ace_list);
 
3955
                                        free_canon_ace_list(dir_ace_list);
 
3956
                                        return map_nt_error_from_unix(errno);
 
3957
                                }
 
3958
                        }
 
3959
                }
 
3960
        }
 
3961
 
 
3962
        free_canon_ace_list(file_ace_list);
 
3963
        free_canon_ace_list(dir_ace_list);
 
3964
 
 
3965
        return NT_STATUS_OK;
 
3966
}
 
3967
 
 
3968
/****************************************************************************
 
3969
 Get the actual group bits stored on a file with an ACL. Has no effect if
 
3970
 the file has no ACL. Needed in dosmode code where the stat() will return
 
3971
 the mask bits, not the real group bits, for a file with an ACL.
 
3972
****************************************************************************/
 
3973
 
 
3974
int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
 
3975
{
 
3976
        int entry_id = SMB_ACL_FIRST_ENTRY;
 
3977
        SMB_ACL_ENTRY_T entry;
 
3978
        SMB_ACL_T posix_acl;
 
3979
        int result = -1;
 
3980
 
 
3981
        posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
 
3982
        if (posix_acl == (SMB_ACL_T)NULL)
 
3983
                return -1;
 
3984
 
 
3985
        while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
 
3986
                SMB_ACL_TAG_T tagtype;
 
3987
                SMB_ACL_PERMSET_T permset;
 
3988
 
 
3989
                entry_id = SMB_ACL_NEXT_ENTRY;
 
3990
 
 
3991
                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
 
3992
                        break;
 
3993
 
 
3994
                if (tagtype == SMB_ACL_GROUP_OBJ) {
 
3995
                        if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
 
3996
                                break;
 
3997
                        } else {
 
3998
                                *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
 
3999
                                *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0);
 
4000
                                *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
 
4001
                                *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
 
4002
                                result = 0;
 
4003
                                break;
 
4004
                        }
 
4005
                }
 
4006
        }
 
4007
        SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
 
4008
        return result;
 
4009
}
 
4010
 
 
4011
/****************************************************************************
 
4012
 Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
 
4013
 and set the mask to rwx. Needed to preserve complex ACLs set by NT.
 
4014
****************************************************************************/
 
4015
 
 
4016
static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mode_t mode)
 
4017
{
 
4018
        int entry_id = SMB_ACL_FIRST_ENTRY;
 
4019
        SMB_ACL_ENTRY_T entry;
 
4020
        int num_entries = 0;
 
4021
 
 
4022
        while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
 
4023
                SMB_ACL_TAG_T tagtype;
 
4024
                SMB_ACL_PERMSET_T permset;
 
4025
                mode_t perms;
 
4026
 
 
4027
                entry_id = SMB_ACL_NEXT_ENTRY;
 
4028
 
 
4029
                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
 
4030
                        return -1;
 
4031
 
 
4032
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
 
4033
                        return -1;
 
4034
 
 
4035
                num_entries++;
 
4036
 
 
4037
                switch(tagtype) {
 
4038
                        case SMB_ACL_USER_OBJ:
 
4039
                                perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
 
4040
                                break;
 
4041
                        case SMB_ACL_GROUP_OBJ:
 
4042
                                perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
 
4043
                                break;
 
4044
                        case SMB_ACL_MASK:
 
4045
                                /*
 
4046
                                 * FIXME: The ACL_MASK entry permissions should really be set to
 
4047
                                 * the union of the permissions of all ACL_USER,
 
4048
                                 * ACL_GROUP_OBJ, and ACL_GROUP entries. That's what
 
4049
                                 * acl_calc_mask() does, but Samba ACLs doesn't provide it.
 
4050
                                 */
 
4051
                                perms = S_IRUSR|S_IWUSR|S_IXUSR;
 
4052
                                break;
 
4053
                        case SMB_ACL_OTHER:
 
4054
                                perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH);
 
4055
                                break;
 
4056
                        default:
 
4057
                                continue;
 
4058
                }
 
4059
 
 
4060
                if (map_acl_perms_to_permset(conn, perms, &permset) == -1)
 
4061
                        return -1;
 
4062
 
 
4063
                if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1)
 
4064
                        return -1;
 
4065
        }
 
4066
 
 
4067
        /*
 
4068
         * If this is a simple 3 element ACL or no elements then it's a standard
 
4069
         * UNIX permission set. Just use chmod...       
 
4070
         */
 
4071
 
 
4072
        if ((num_entries == 3) || (num_entries == 0))
 
4073
                return -1;
 
4074
 
 
4075
        return 0;
 
4076
}
 
4077
 
 
4078
/****************************************************************************
 
4079
 Get the access ACL of FROM, do a chmod by setting the ACL USER_OBJ,
 
4080
 GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Set the
 
4081
 resulting ACL on TO.  Note that name is in UNIX character set.
 
4082
****************************************************************************/
 
4083
 
 
4084
static int copy_access_posix_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
 
4085
{
 
4086
        SMB_ACL_T posix_acl = NULL;
 
4087
        int ret = -1;
 
4088
 
 
4089
        if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL)
 
4090
                return -1;
 
4091
 
 
4092
        if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
 
4093
                goto done;
 
4094
 
 
4095
        ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl);
 
4096
 
 
4097
 done:
 
4098
 
 
4099
        SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
 
4100
        return ret;
 
4101
}
 
4102
 
 
4103
/****************************************************************************
 
4104
 Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
 
4105
 and set the mask to rwx. Needed to preserve complex ACLs set by NT.
 
4106
 Note that name is in UNIX character set.
 
4107
****************************************************************************/
 
4108
 
 
4109
int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
 
4110
{
 
4111
        return copy_access_posix_acl(conn, name, name, mode);
 
4112
}
 
4113
 
 
4114
/****************************************************************************
 
4115
 Check for an existing default POSIX ACL on a directory.
 
4116
****************************************************************************/
 
4117
 
 
4118
static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname)
 
4119
{
 
4120
        SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
 
4121
        bool has_acl = False;
 
4122
        SMB_ACL_ENTRY_T entry;
 
4123
 
 
4124
        if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
 
4125
                has_acl = True;
 
4126
        }
 
4127
 
 
4128
        if (def_acl) {
 
4129
                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
 
4130
        }
 
4131
        return has_acl;
 
4132
}
 
4133
 
 
4134
/****************************************************************************
 
4135
 If the parent directory has no default ACL but it does have an Access ACL,
 
4136
 inherit this Access ACL to file name.
 
4137
****************************************************************************/
 
4138
 
 
4139
int inherit_access_posix_acl(connection_struct *conn, const char *inherit_from_dir,
 
4140
                       const char *name, mode_t mode)
 
4141
{
 
4142
        if (directory_has_default_posix_acl(conn, inherit_from_dir))
 
4143
                return 0;
 
4144
 
 
4145
        return copy_access_posix_acl(conn, inherit_from_dir, name, mode);
 
4146
}
 
4147
 
 
4148
/****************************************************************************
 
4149
 Do an fchmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
 
4150
 and set the mask to rwx. Needed to preserve complex ACLs set by NT.
 
4151
****************************************************************************/
 
4152
 
 
4153
int fchmod_acl(files_struct *fsp, mode_t mode)
 
4154
{
 
4155
        connection_struct *conn = fsp->conn;
 
4156
        SMB_ACL_T posix_acl = NULL;
 
4157
        int ret = -1;
 
4158
 
 
4159
        if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp)) == NULL)
 
4160
                return -1;
 
4161
 
 
4162
        if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
 
4163
                goto done;
 
4164
 
 
4165
        ret = SMB_VFS_SYS_ACL_SET_FD(fsp, posix_acl);
 
4166
 
 
4167
  done:
 
4168
 
 
4169
        SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
 
4170
        return ret;
 
4171
}
 
4172
 
 
4173
/****************************************************************************
 
4174
 Map from wire type to permset.
 
4175
****************************************************************************/
 
4176
 
 
4177
static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
 
4178
{
 
4179
        if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) {
 
4180
                return False;
 
4181
        }
 
4182
 
 
4183
        if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1) {
 
4184
                return False;
 
4185
        }
 
4186
 
 
4187
        if (wire_perm & SMB_POSIX_ACL_READ) {
 
4188
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) {
 
4189
                        return False;
 
4190
                }
 
4191
        }
 
4192
        if (wire_perm & SMB_POSIX_ACL_WRITE) {
 
4193
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) {
 
4194
                        return False;
 
4195
                }
 
4196
        }
 
4197
        if (wire_perm & SMB_POSIX_ACL_EXECUTE) {
 
4198
                if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) {
 
4199
                        return False;
 
4200
                }
 
4201
        }
 
4202
        return True;
 
4203
}
 
4204
 
 
4205
/****************************************************************************
 
4206
 Map from wire type to tagtype.
 
4207
****************************************************************************/
 
4208
 
 
4209
static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
 
4210
{
 
4211
        switch (wire_tt) {
 
4212
                case SMB_POSIX_ACL_USER_OBJ:
 
4213
                        *p_tt = SMB_ACL_USER_OBJ;
 
4214
                        break;
 
4215
                case SMB_POSIX_ACL_USER:
 
4216
                        *p_tt = SMB_ACL_USER;
 
4217
                        break;
 
4218
                case SMB_POSIX_ACL_GROUP_OBJ:
 
4219
                        *p_tt = SMB_ACL_GROUP_OBJ;
 
4220
                        break;
 
4221
                case SMB_POSIX_ACL_GROUP:
 
4222
                        *p_tt = SMB_ACL_GROUP;
 
4223
                        break;
 
4224
                case SMB_POSIX_ACL_MASK:
 
4225
                        *p_tt = SMB_ACL_MASK;
 
4226
                        break;
 
4227
                case SMB_POSIX_ACL_OTHER:
 
4228
                        *p_tt = SMB_ACL_OTHER;
 
4229
                        break;
 
4230
                default:
 
4231
                        return False;
 
4232
        }
 
4233
        return True;
 
4234
}
 
4235
 
 
4236
/****************************************************************************
 
4237
 Create a new POSIX acl from wire permissions.
 
4238
 FIXME ! How does the share mask/mode fit into this.... ?
 
4239
****************************************************************************/
 
4240
 
 
4241
static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata)
 
4242
{
 
4243
        unsigned int i;
 
4244
        SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, num_acls);
 
4245
 
 
4246
        if (the_acl == NULL) {
 
4247
                return NULL;
 
4248
        }
 
4249
 
 
4250
        for (i = 0; i < num_acls; i++) {
 
4251
                SMB_ACL_ENTRY_T the_entry;
 
4252
                SMB_ACL_PERMSET_T the_permset;
 
4253
                SMB_ACL_TAG_T tag_type;
 
4254
 
 
4255
                if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
 
4256
                        DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n",
 
4257
                                i, strerror(errno) ));
 
4258
                        goto fail;
 
4259
                }
 
4260
 
 
4261
                if (!unix_ex_wire_to_tagtype(CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), &tag_type)) {
 
4262
                        DEBUG(0,("create_posix_acl_from_wire: invalid wire tagtype %u on entry %u.\n",
 
4263
                                CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), i ));
 
4264
                        goto fail;
 
4265
                }
 
4266
 
 
4267
                if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, tag_type) == -1) {
 
4268
                        DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n",
 
4269
                                i, strerror(errno) ));
 
4270
                        goto fail;
 
4271
                }
 
4272
 
 
4273
                /* Get the permset pointer from the new ACL entry. */
 
4274
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
 
4275
                        DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n",
 
4276
                                i, strerror(errno) ));
 
4277
                        goto fail;
 
4278
                }
 
4279
 
 
4280
                /* Map from wire to permissions. */
 
4281
                if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) {
 
4282
                        DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n",
 
4283
                                CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i ));
 
4284
                        goto fail;
 
4285
                }
 
4286
 
 
4287
                /* Now apply to the new ACL entry. */
 
4288
                if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
 
4289
                        DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n",
 
4290
                                i, strerror(errno) ));
 
4291
                        goto fail;
 
4292
                }
 
4293
 
 
4294
                if (tag_type == SMB_ACL_USER) {
 
4295
                        uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 
4296
                        uid_t uid = (uid_t)uidval;
 
4297
                        if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&uid) == -1) {
 
4298
                                DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
 
4299
                                        (unsigned int)uid, i, strerror(errno) ));
 
4300
                                goto fail;
 
4301
                        }
 
4302
                }
 
4303
 
 
4304
                if (tag_type == SMB_ACL_GROUP) {
 
4305
                        uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 
4306
                        gid_t gid = (uid_t)gidval;
 
4307
                        if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&gid) == -1) {
 
4308
                                DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
 
4309
                                        (unsigned int)gid, i, strerror(errno) ));
 
4310
                                goto fail;
 
4311
                        }
 
4312
                }
 
4313
        }
 
4314
 
 
4315
        return the_acl;
 
4316
 
 
4317
 fail:
 
4318
 
 
4319
        if (the_acl != NULL) {
 
4320
                SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
 
4321
        }
 
4322
        return NULL;
 
4323
}
 
4324
 
 
4325
/****************************************************************************
 
4326
 Calls from UNIX extensions - Default POSIX ACL set.
 
4327
 If num_def_acls == 0 and not a directory just return. If it is a directory
 
4328
 and num_def_acls == 0 then remove the default acl. Else set the default acl
 
4329
 on the directory.
 
4330
****************************************************************************/
 
4331
 
 
4332
bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
 
4333
                                uint16 num_def_acls, const char *pdata)
 
4334
{
 
4335
        SMB_ACL_T def_acl = NULL;
 
4336
 
 
4337
        if (!S_ISDIR(psbuf->st_mode)) {
 
4338
                if (num_def_acls) {
 
4339
                        DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
 
4340
                        errno = EISDIR;
 
4341
                        return False;
 
4342
                } else {
 
4343
                        return True;
 
4344
                }
 
4345
        }
 
4346
 
 
4347
        if (!num_def_acls) {
 
4348
                /* Remove the default ACL. */
 
4349
                if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) {
 
4350
                        DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n",
 
4351
                                fname, strerror(errno) ));
 
4352
                        return False;
 
4353
                }
 
4354
                return True;
 
4355
        }
 
4356
 
 
4357
        if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) {
 
4358
                return False;
 
4359
        }
 
4360
 
 
4361
        if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
 
4362
                DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n",
 
4363
                        fname, strerror(errno) ));
 
4364
                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
 
4365
                return False;
 
4366
        }
 
4367
 
 
4368
        DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
 
4369
        SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
 
4370
        return True;
 
4371
}
 
4372
 
 
4373
/****************************************************************************
 
4374
 Remove an ACL from a file. As we don't have acl_delete_entry() available
 
4375
 we must read the current acl and copy all entries except MASK, USER and GROUP
 
4376
 to a new acl, then set that. This (at least on Linux) causes any ACL to be
 
4377
 removed.
 
4378
 FIXME ! How does the share mask/mode fit into this.... ?
 
4379
****************************************************************************/
 
4380
 
 
4381
static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname)
 
4382
{
 
4383
        SMB_ACL_T file_acl = NULL;
 
4384
        int entry_id = SMB_ACL_FIRST_ENTRY;
 
4385
        SMB_ACL_ENTRY_T entry;
 
4386
        bool ret = False;
 
4387
        /* Create a new ACL with only 3 entries, u/g/w. */
 
4388
        SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3);
 
4389
        SMB_ACL_ENTRY_T user_ent = NULL;
 
4390
        SMB_ACL_ENTRY_T group_ent = NULL;
 
4391
        SMB_ACL_ENTRY_T other_ent = NULL;
 
4392
 
 
4393
        if (new_file_acl == NULL) {
 
4394
                DEBUG(5,("remove_posix_acl: failed to init new ACL with 3 entries for file %s.\n", fname));
 
4395
                return False;
 
4396
        }
 
4397
 
 
4398
        /* Now create the u/g/w entries. */
 
4399
        if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &user_ent) == -1) {
 
4400
                DEBUG(5,("remove_posix_acl: Failed to create user entry for file %s. (%s)\n",
 
4401
                        fname, strerror(errno) ));
 
4402
                goto done;
 
4403
        }
 
4404
        if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, user_ent, SMB_ACL_USER_OBJ) == -1) {
 
4405
                DEBUG(5,("remove_posix_acl: Failed to set user entry for file %s. (%s)\n",
 
4406
                        fname, strerror(errno) ));
 
4407
                goto done;
 
4408
        }
 
4409
 
 
4410
        if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &group_ent) == -1) {
 
4411
                DEBUG(5,("remove_posix_acl: Failed to create group entry for file %s. (%s)\n",
 
4412
                        fname, strerror(errno) ));
 
4413
                goto done;
 
4414
        }
 
4415
        if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, group_ent, SMB_ACL_GROUP_OBJ) == -1) {
 
4416
                DEBUG(5,("remove_posix_acl: Failed to set group entry for file %s. (%s)\n",
 
4417
                        fname, strerror(errno) ));
 
4418
                goto done;
 
4419
        }
 
4420
 
 
4421
        if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &other_ent) == -1) {
 
4422
                DEBUG(5,("remove_posix_acl: Failed to create other entry for file %s. (%s)\n",
 
4423
                        fname, strerror(errno) ));
 
4424
                goto done;
 
4425
        }
 
4426
        if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, other_ent, SMB_ACL_OTHER) == -1) {
 
4427
                DEBUG(5,("remove_posix_acl: Failed to set other entry for file %s. (%s)\n",
 
4428
                        fname, strerror(errno) ));
 
4429
                goto done;
 
4430
        }
 
4431
 
 
4432
        /* Get the current file ACL. */
 
4433
        if (fsp && fsp->fh->fd != -1) {
 
4434
                file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
 
4435
        } else {
 
4436
                file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS);
 
4437
        }
 
4438
 
 
4439
        if (file_acl == NULL) {
 
4440
                /* This is only returned if an error occurred. Even for a file with
 
4441
                   no acl a u/g/w acl should be returned. */
 
4442
                DEBUG(5,("remove_posix_acl: failed to get ACL from file %s (%s).\n",
 
4443
                        fname, strerror(errno) ));
 
4444
                goto done;
 
4445
        }
 
4446
 
 
4447
        while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, file_acl, entry_id, &entry) == 1) {
 
4448
                SMB_ACL_TAG_T tagtype;
 
4449
                SMB_ACL_PERMSET_T permset;
 
4450
 
 
4451
                entry_id = SMB_ACL_NEXT_ENTRY;
 
4452
 
 
4453
                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
 
4454
                        DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n",
 
4455
                                fname, strerror(errno) ));
 
4456
                        goto done;
 
4457
                }
 
4458
 
 
4459
                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
 
4460
                        DEBUG(5,("remove_posix_acl: failed to get permset from ACL on file %s (%s).\n",
 
4461
                                fname, strerror(errno) ));
 
4462
                        goto done;
 
4463
                }
 
4464
 
 
4465
                if (tagtype == SMB_ACL_USER_OBJ) {
 
4466
                        if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, user_ent, permset) == -1) {
 
4467
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
 
4468
                                        fname, strerror(errno) ));
 
4469
                        }
 
4470
                } else if (tagtype == SMB_ACL_GROUP_OBJ) {
 
4471
                        if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, group_ent, permset) == -1) {
 
4472
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
 
4473
                                        fname, strerror(errno) ));
 
4474
                        }
 
4475
                } else if (tagtype == SMB_ACL_OTHER) {
 
4476
                        if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, other_ent, permset) == -1) {
 
4477
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
 
4478
                                        fname, strerror(errno) ));
 
4479
                        }
 
4480
                }
 
4481
        }
 
4482
 
 
4483
        /* Set the new empty file ACL. */
 
4484
        if (fsp && fsp->fh->fd != -1) {
 
4485
                if (SMB_VFS_SYS_ACL_SET_FD(fsp, new_file_acl) == -1) {
 
4486
                        DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
 
4487
                                fname, strerror(errno) ));
 
4488
                        goto done;
 
4489
                }
 
4490
        } else {
 
4491
                if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
 
4492
                        DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
 
4493
                                fname, strerror(errno) ));
 
4494
                        goto done;
 
4495
                }
 
4496
        }
 
4497
 
 
4498
        ret = True;
 
4499
 
 
4500
 done:
 
4501
 
 
4502
        if (file_acl) {
 
4503
                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
 
4504
        }
 
4505
        if (new_file_acl) {
 
4506
                SMB_VFS_SYS_ACL_FREE_ACL(conn, new_file_acl);
 
4507
        }
 
4508
        return ret;
 
4509
}
 
4510
 
 
4511
/****************************************************************************
 
4512
 Calls from UNIX extensions - POSIX ACL set.
 
4513
 If num_def_acls == 0 then read/modify/write acl after removing all entries
 
4514
 except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER.
 
4515
****************************************************************************/
 
4516
 
 
4517
bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata)
 
4518
{
 
4519
        SMB_ACL_T file_acl = NULL;
 
4520
 
 
4521
        if (!num_acls) {
 
4522
                /* Remove the ACL from the file. */
 
4523
                return remove_posix_acl(conn, fsp, fname);
 
4524
        }
 
4525
 
 
4526
        if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) {
 
4527
                return False;
 
4528
        }
 
4529
 
 
4530
        if (fsp && fsp->fh->fd != -1) {
 
4531
                /* The preferred way - use an open fd. */
 
4532
                if (SMB_VFS_SYS_ACL_SET_FD(fsp, file_acl) == -1) {
 
4533
                        DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
 
4534
                                fname, strerror(errno) ));
 
4535
                        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
 
4536
                        return False;
 
4537
                }
 
4538
        } else {
 
4539
                if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
 
4540
                        DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
 
4541
                                fname, strerror(errno) ));
 
4542
                        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
 
4543
                        return False;
 
4544
                }
 
4545
        }
 
4546
 
 
4547
        DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname ));
 
4548
        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
 
4549
        return True;
 
4550
}
 
4551
 
 
4552
/********************************************************************
 
4553
 Pull the NT ACL from a file on disk or the OpenEventlog() access
 
4554
 check.  Caller is responsible for freeing the returned security
 
4555
 descriptor via TALLOC_FREE().  This is designed for dealing with 
 
4556
 user space access checks in smbd outside of the VFS.  For example,
 
4557
 checking access rights in OpenEventlog().
 
4558
 
 
4559
 Assume we are dealing with files (for now)
 
4560
********************************************************************/
 
4561
 
 
4562
SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
 
4563
{
 
4564
        SEC_DESC *psd, *ret_sd;
 
4565
        connection_struct *conn;
 
4566
        files_struct finfo;
 
4567
        struct fd_handle fh;
 
4568
 
 
4569
        conn = TALLOC_ZERO_P(ctx, connection_struct);
 
4570
        if (conn == NULL) {
 
4571
                DEBUG(0, ("talloc failed\n"));
 
4572
                return NULL;
 
4573
        }
 
4574
 
 
4575
        if (!(conn->params = TALLOC_P(conn, struct share_params))) {
 
4576
                DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
 
4577
                TALLOC_FREE(conn);
 
4578
                return NULL;
 
4579
        }
 
4580
 
 
4581
        conn->params->service = -1;
 
4582
 
 
4583
        set_conn_connectpath(conn, "/");
 
4584
 
 
4585
        if (!smbd_vfs_init(conn)) {
 
4586
                DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
 
4587
                conn_free_internal( conn );
 
4588
                return NULL;
 
4589
        }
 
4590
 
 
4591
        ZERO_STRUCT( finfo );
 
4592
        ZERO_STRUCT( fh );
 
4593
 
 
4594
        finfo.fnum = -1;
 
4595
        finfo.conn = conn;
 
4596
        finfo.fh = &fh;
 
4597
        finfo.fh->fd = -1;
 
4598
        finfo.fsp_name = CONST_DISCARD(char *,fname);
 
4599
 
 
4600
        if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) {
 
4601
                DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
 
4602
                conn_free_internal( conn );
 
4603
                return NULL;
 
4604
        }
 
4605
 
 
4606
        ret_sd = dup_sec_desc( ctx, psd );
 
4607
 
 
4608
        conn_free_internal( conn );
 
4609
 
 
4610
        return ret_sd;
 
4611
}