~zulcss/samba/samab-3.4-test

« back to all changes in this revision

Viewing changes to source3/modules/vfs_solarisacl.c

  • Committer: Chuck Short
  • Date: 2010-05-20 18:57:13 UTC
  • Revision ID: zulcss@ubuntu.com-20100520185713-hwqvf9t50z830wck
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/Netbios implementation.
 
3
   VFS module to get and set Solaris ACLs
 
4
   Copyright (C) Michael Adam 2006,2008
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
 
 
21
#include "includes.h"
 
22
 
 
23
 
 
24
/* typedef struct acl SOLARIS_ACE_T; */
 
25
typedef aclent_t SOLARIS_ACE_T;
 
26
typedef aclent_t *SOLARIS_ACL_T;
 
27
typedef int SOLARIS_ACL_TAG_T;   /* the type of an ACL entry */
 
28
typedef o_mode_t SOLARIS_PERM_T;
 
29
 
 
30
/* for convenience: check if solaris acl entry is a default entry?  */
 
31
#define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT)
 
32
#define _IS_OF_TYPE(ace, type) ( \
 
33
        (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \
 
34
        || \
 
35
        (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \
 
36
)
 
37
 
 
38
 
 
39
/* prototypes for private functions */
 
40
 
 
41
static SOLARIS_ACL_T solaris_acl_init(int count);
 
42
static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
 
43
                SOLARIS_ACL_T *solariacl, int *count, 
 
44
                SMB_ACL_TYPE_T type);
 
45
static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count,
 
46
                SMB_ACL_TYPE_T type);
 
47
static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag);
 
48
static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag);
 
49
static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
 
50
                SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type);
 
51
static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, 
 
52
                int *count);
 
53
static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
 
54
static bool solaris_acl_sort(SOLARIS_ACL_T theacl, int count);
 
55
static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
 
56
static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
 
57
#if 0
 
58
static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
 
59
#endif
 
60
 
 
61
/* public functions - the api */
 
62
 
 
63
SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle,
 
64
                                      const char *path_p,
 
65
                                      SMB_ACL_TYPE_T type)
 
66
{
 
67
        SMB_ACL_T result = NULL;
 
68
        int count;
 
69
        SOLARIS_ACL_T solaris_acl = NULL;
 
70
        
 
71
        DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n", 
 
72
                   path_p));
 
73
 
 
74
        if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
 
75
                DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
 
76
                errno = EINVAL;
 
77
                goto done;
 
78
        }
 
79
 
 
80
        DEBUGADD(10, ("getting %s acl\n", 
 
81
                      ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
 
82
 
 
83
        if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) {
 
84
                goto done;
 
85
        }
 
86
        result = solaris_acl_to_smb_acl(solaris_acl, count, type);
 
87
        if (result == NULL) {
 
88
                DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
 
89
                           strerror(errno)));
 
90
        }
 
91
        
 
92
 done:
 
93
        DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n",
 
94
                   ((result == NULL) ? "failed" : "succeeded" )));
 
95
        SAFE_FREE(solaris_acl);
 
96
        return result;
 
97
}
 
98
 
 
99
 
 
100
/*
 
101
 * get the access ACL of a file referred to by a fd
 
102
 */
 
103
SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle,
 
104
                                    files_struct *fsp)
 
105
{
 
106
        SMB_ACL_T result = NULL;
 
107
        int count;
 
108
        SOLARIS_ACL_T solaris_acl = NULL;
 
109
 
 
110
        DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n"));
 
111
 
 
112
        if (!solaris_acl_get_fd(fsp->fh->fd, &solaris_acl, &count)) {
 
113
                goto done;
 
114
        }
 
115
        /* 
 
116
         * The facl call returns both ACCESS and DEFAULT acls (as present). 
 
117
         * The posix acl_get_fd function returns only the
 
118
         * access acl. So we need to filter this out here.  
 
119
         */
 
120
        result = solaris_acl_to_smb_acl(solaris_acl, count,
 
121
                                        SMB_ACL_TYPE_ACCESS);
 
122
        if (result == NULL) {
 
123
                DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
 
124
                           strerror(errno)));
 
125
        }
 
126
        
 
127
 done:
 
128
        DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n", 
 
129
                   ((result == NULL) ? "failed" : "succeeded")));
 
130
        SAFE_FREE(solaris_acl);
 
131
        return result;
 
132
}
 
133
 
 
134
int solarisacl_sys_acl_set_file(vfs_handle_struct *handle,
 
135
                                const char *name,
 
136
                                SMB_ACL_TYPE_T type,
 
137
                                SMB_ACL_T theacl)
 
138
{
 
139
        int ret = -1;
 
140
        struct stat s;
 
141
        SOLARIS_ACL_T solaris_acl = NULL;
 
142
        int count;
 
143
        
 
144
        DEBUG(10, ("solarisacl_sys_acl_set_file called for file '%s'\n",
 
145
                   name));
 
146
 
 
147
        if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) {
 
148
                errno = EINVAL;
 
149
                DEBUG(10, ("invalid smb acl type given (%d).\n", type));
 
150
                goto done;
 
151
        }
 
152
        DEBUGADD(10, ("setting %s acl\n", 
 
153
                      ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
 
154
 
 
155
        if(!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, type)) {
 
156
                DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
 
157
                           strerror(errno)));
 
158
                goto done;
 
159
        }
 
160
 
 
161
        /*
 
162
         * if the file is a directory, there is extra work to do:
 
163
         * since the solaris acl call stores both the access acl and 
 
164
         * the default acl as provided, we have to get the acl part 
 
165
         * that has not been specified in "type" from the file first 
 
166
         * and concatenate it with the acl provided.
 
167
         */
 
168
        if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
 
169
                DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
 
170
                goto done;
 
171
        }
 
172
        if (S_ISDIR(s.st_mode)) {
 
173
                SOLARIS_ACL_T other_acl; 
 
174
                int other_count;
 
175
                SMB_ACL_TYPE_T other_type;
 
176
 
 
177
                other_type = (type == SMB_ACL_TYPE_ACCESS) 
 
178
                        ? SMB_ACL_TYPE_DEFAULT
 
179
                        : SMB_ACL_TYPE_ACCESS;
 
180
                DEBUGADD(10, ("getting acl from filesystem\n"));
 
181
                if (!solaris_acl_get_file(name, &other_acl, &other_count)) {
 
182
                        DEBUG(10, ("error getting acl from directory\n"));
 
183
                        goto done;
 
184
                }
 
185
                DEBUG(10, ("adding %s part of fs acl to given acl\n",
 
186
                           ((other_type == SMB_ACL_TYPE_ACCESS) 
 
187
                            ? "access"
 
188
                            : "default")));
 
189
                if (!solaris_add_to_acl(&solaris_acl, &count, other_acl,
 
190
                                        other_count, other_type)) 
 
191
                {
 
192
                        DEBUG(10, ("error adding other acl.\n"));
 
193
                        SAFE_FREE(other_acl);
 
194
                        goto done;
 
195
                }
 
196
                SAFE_FREE(other_acl);
 
197
        }
 
198
        else if (type != SMB_ACL_TYPE_ACCESS) {
 
199
                errno = EINVAL;
 
200
                goto done;
 
201
        }
 
202
 
 
203
        if (!solaris_acl_sort(solaris_acl, count)) {
 
204
                DEBUG(10, ("resulting acl is not valid!\n"));
 
205
                goto done;
 
206
        }
 
207
 
 
208
        ret = acl(name, SETACL, count, solaris_acl);
 
209
        
 
210
 done:
 
211
        DEBUG(10, ("solarisacl_sys_acl_set_file %s.\n",
 
212
                   ((ret != 0) ? "failed" : "succeeded")));
 
213
        SAFE_FREE(solaris_acl);
 
214
        return ret;
 
215
}
 
216
 
 
217
/*
 
218
 * set the access ACL on the file referred to by a fd 
 
219
 */
 
220
int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
 
221
                              files_struct *fsp,
 
222
                              SMB_ACL_T theacl)
 
223
{
 
224
        SOLARIS_ACL_T solaris_acl = NULL;
 
225
        SOLARIS_ACL_T default_acl = NULL;
 
226
        int count, default_count;
 
227
        int ret = -1;
 
228
 
 
229
        DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n"));
 
230
 
 
231
        /* 
 
232
         * the posix acl_set_fd call sets the access acl of the
 
233
         * file referred to by fd. the solaris facl-SETACL call
 
234
         * sets the access and default acl as provided, so we
 
235
         * have to retrieve the default acl of the file and 
 
236
         * concatenate it with the access acl provided.
 
237
         */
 
238
        if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, 
 
239
                                    SMB_ACL_TYPE_ACCESS))
 
240
        {
 
241
                DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
 
242
                           strerror(errno)));
 
243
                goto done;
 
244
        }
 
245
        if (!solaris_acl_get_fd(fsp->fh->fd, &default_acl, &default_count)) {
 
246
                DEBUG(10, ("error getting (default) acl from fd\n"));
 
247
                goto done;
 
248
        }
 
249
        if (!solaris_add_to_acl(&solaris_acl, &count,
 
250
                                default_acl, default_count,
 
251
                                SMB_ACL_TYPE_DEFAULT))
 
252
        {
 
253
                DEBUG(10, ("error adding default acl to solaris acl\n"));
 
254
                goto done;
 
255
        }
 
256
        if (!solaris_acl_sort(solaris_acl, count)) {
 
257
                DEBUG(10, ("resulting acl is not valid!\n"));
 
258
                goto done;
 
259
        }
 
260
 
 
261
        ret = facl(fsp->fh->fd, SETACL, count, solaris_acl);
 
262
        if (ret != 0) {
 
263
                DEBUG(10, ("call of facl failed (%s).\n", strerror(errno)));
 
264
        }
 
265
 
 
266
 done:
 
267
        DEBUG(10, ("solarisacl_sys_acl_set_fd %s.\n",
 
268
                   ((ret == 0) ? "succeeded" : "failed" )));
 
269
        SAFE_FREE(solaris_acl);
 
270
        SAFE_FREE(default_acl);
 
271
        return ret;
 
272
}
 
273
 
 
274
/*
 
275
 * delete the default ACL of a directory
 
276
 *
 
277
 * This is achieved by fetching the access ACL and rewriting it 
 
278
 * directly, via the solaris system call: the SETACL call on 
 
279
 * directories writes both the access and the default ACL as provided.
 
280
 *
 
281
 * XXX: posix acl_delete_def_file returns an error if
 
282
 * the file referred to by path is not a directory.
 
283
 * this function does not complain but the actions 
 
284
 * have no effect on a file other than a directory.
 
285
 * But sys_acl_delete_default_file is only called in
 
286
 * smbd/posixacls.c after having checked that the file
 
287
 * is a directory, anyways. So implementing the extra
 
288
 * check is considered unnecessary. --- Agreed? XXX
 
289
 */
 
290
int solarisacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
 
291
                                       const char *path)
 
292
{
 
293
        SMB_ACL_T smb_acl;
 
294
        int ret = -1;
 
295
        SOLARIS_ACL_T solaris_acl = NULL;
 
296
        int count;
 
297
 
 
298
        DEBUG(10, ("entering solarisacl_sys_acl_delete_def_file.\n"));
 
299
        
 
300
        smb_acl = solarisacl_sys_acl_get_file(handle, path, 
 
301
                                              SMB_ACL_TYPE_ACCESS);
 
302
        if (smb_acl == NULL) {
 
303
                DEBUG(10, ("getting file acl failed!\n"));
 
304
                goto done;
 
305
        }
 
306
        if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count, 
 
307
                                    SMB_ACL_TYPE_ACCESS))
 
308
        {
 
309
                DEBUG(10, ("conversion smb_acl -> solaris_acl failed.\n"));
 
310
                goto done;
 
311
        }
 
312
        if (!solaris_acl_sort(solaris_acl, count)) {
 
313
                DEBUG(10, ("resulting acl is not valid!\n"));
 
314
                goto done;
 
315
        }
 
316
        ret = acl(path, SETACL, count, solaris_acl);
 
317
        if (ret != 0) {
 
318
                DEBUG(10, ("settinge file acl failed!\n"));
 
319
        }
 
320
        
 
321
 done:
 
322
        DEBUG(10, ("solarisacl_sys_acl_delete_def_file %s.\n",
 
323
                   ((ret != 0) ? "failed" : "succeeded" )));
 
324
        SAFE_FREE(smb_acl);
 
325
        return ret;
 
326
}
 
327
 
 
328
 
 
329
/* private functions */
 
330
 
 
331
static SOLARIS_ACL_T solaris_acl_init(int count)
 
332
{
 
333
        SOLARIS_ACL_T solaris_acl = 
 
334
                (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count);
 
335
        if (solaris_acl == NULL) {
 
336
                errno = ENOMEM;
 
337
        }
 
338
        return solaris_acl;
 
339
}
 
340
 
 
341
/*
 
342
 * Convert the SMB acl to the ACCESS or DEFAULT part of a 
 
343
 * solaris ACL, as desired.
 
344
 */
 
345
static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
 
346
                                   SOLARIS_ACL_T *solaris_acl, int *count, 
 
347
                                   SMB_ACL_TYPE_T type)
 
348
{
 
349
        bool ret = False;
 
350
        int i;
 
351
 
 
352
        DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
 
353
        
 
354
        *solaris_acl = NULL;
 
355
        *count = 0;
 
356
 
 
357
        for (i = 0; i < smb_acl->count; i++) {
 
358
                const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]);
 
359
                SOLARIS_ACE_T solaris_entry;
 
360
 
 
361
                ZERO_STRUCT(solaris_entry);
 
362
 
 
363
                solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type);
 
364
                if (solaris_entry.a_type == 0) {
 
365
                        DEBUG(10, ("smb_tag to solaris_tag failed\n"));
 
366
                        goto fail;
 
367
                }
 
368
                switch(solaris_entry.a_type) {
 
369
                case USER:
 
370
                        DEBUG(10, ("got tag type USER with uid %u\n", 
 
371
                                   (unsigned int)smb_entry->uid));
 
372
                        solaris_entry.a_id = (uid_t)smb_entry->uid;
 
373
                        break;
 
374
                case GROUP:
 
375
                        DEBUG(10, ("got tag type GROUP with gid %u\n", 
 
376
                                   (unsigned int)smb_entry->gid));
 
377
                        solaris_entry.a_id = (uid_t)smb_entry->gid;
 
378
                        break;
 
379
                default:
 
380
                        break;
 
381
                }
 
382
                if (type == SMB_ACL_TYPE_DEFAULT) {
 
383
                        DEBUG(10, ("adding default bit to solaris ace\n"));
 
384
                        solaris_entry.a_type |= ACL_DEFAULT;
 
385
                }
 
386
                
 
387
                solaris_entry.a_perm = 
 
388
                        smb_perm_to_solaris_perm(smb_entry->a_perm);
 
389
                DEBUG(10, ("assembled the following solaris ace:\n"));
 
390
                DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type));
 
391
                DEBUGADD(10, (" - id: %u\n", (unsigned int)solaris_entry.a_id));
 
392
                DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm));
 
393
                if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry, 
 
394
                                        1, type))
 
395
                {
 
396
                        DEBUG(10, ("error adding acl entry\n"));
 
397
                        goto fail;
 
398
                }
 
399
                DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i));
 
400
                DEBUG(10, ("test, if entry has been copied into acl:\n"));
 
401
                DEBUGADD(10, (" - type: 0x%04x\n",
 
402
                              (*solaris_acl)[(*count)-1].a_type));
 
403
                DEBUGADD(10, (" - id: %u\n",
 
404
                              (unsigned int)(*solaris_acl)[(*count)-1].a_id));
 
405
                DEBUGADD(10, (" - perm: o%o\n",
 
406
                              (*solaris_acl)[(*count)-1].a_perm));
 
407
        }
 
408
 
 
409
        ret = True;
 
410
        goto done;
 
411
        
 
412
 fail:
 
413
        SAFE_FREE(*solaris_acl);
 
414
 done:
 
415
        DEBUG(10, ("smb_acl_to_solaris_acl %s\n",
 
416
                   ((ret == True) ? "succeeded" : "failed")));
 
417
        return ret;
 
418
}
 
419
 
 
420
/* 
 
421
 * convert either the access or the default part of a 
 
422
 * soaris acl to the SMB_ACL format.
 
423
 */
 
424
static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count, 
 
425
                                        SMB_ACL_TYPE_T type)
 
426
{
 
427
        SMB_ACL_T result;
 
428
        int i;
 
429
 
 
430
        if ((result = sys_acl_init(0)) == NULL) {
 
431
                DEBUG(10, ("error allocating memory for SMB_ACL\n"));
 
432
                goto fail;
 
433
        }
 
434
        for (i = 0; i < count; i++) {
 
435
                SMB_ACL_ENTRY_T smb_entry;
 
436
                SMB_ACL_PERM_T smb_perm;
 
437
                
 
438
                if (!_IS_OF_TYPE(solaris_acl[i], type)) {
 
439
                        continue;
 
440
                }
 
441
                result = SMB_REALLOC(result, 
 
442
                                     sizeof(struct smb_acl_t) +
 
443
                                     (sizeof(struct smb_acl_entry) *
 
444
                                      (result->count + 1)));
 
445
                if (result == NULL) {
 
446
                        DEBUG(10, ("error reallocating memory for SMB_ACL\n"));
 
447
                        goto fail;
 
448
                }
 
449
                smb_entry = &result->acl[result->count];
 
450
                if (sys_acl_set_tag_type(smb_entry,
 
451
                                         solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0)
 
452
                {
 
453
                        DEBUG(10, ("invalid tag type given: 0x%04x\n",
 
454
                                   solaris_acl[i].a_type));
 
455
                        goto fail;
 
456
                }
 
457
                /* intentionally not checking return code here: */
 
458
                sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id);
 
459
                smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm);
 
460
                if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) {
 
461
                        DEBUG(10, ("invalid permset given: %d\n", 
 
462
                                   solaris_acl[i].a_perm));
 
463
                        goto fail;
 
464
                }
 
465
                result->count += 1;
 
466
        }
 
467
        goto done;
 
468
        
 
469
 fail:
 
470
        SAFE_FREE(result);
 
471
 done:
 
472
        DEBUG(10, ("solaris_acl_to_smb_acl %s\n",
 
473
                   ((result == NULL) ? "failed" : "succeeded")));
 
474
        return result;
 
475
}
 
476
 
 
477
 
 
478
 
 
479
static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag)
 
480
{
 
481
        SOLARIS_ACL_TAG_T solaris_tag = 0;
 
482
 
 
483
        DEBUG(10, ("smb_tag_to_solaris_tag\n"));
 
484
        DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag));
 
485
        
 
486
        switch (smb_tag) {
 
487
        case SMB_ACL_USER:
 
488
                solaris_tag = USER;
 
489
                break;
 
490
        case SMB_ACL_USER_OBJ:
 
491
                solaris_tag = USER_OBJ;
 
492
                break;
 
493
        case SMB_ACL_GROUP:
 
494
                solaris_tag = GROUP;
 
495
                break;
 
496
        case SMB_ACL_GROUP_OBJ:
 
497
                solaris_tag = GROUP_OBJ;
 
498
                break;
 
499
        case SMB_ACL_OTHER:
 
500
                solaris_tag = OTHER_OBJ;
 
501
                break;
 
502
        case SMB_ACL_MASK:
 
503
                solaris_tag = CLASS_OBJ;
 
504
                break;
 
505
        default:
 
506
                DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag));
 
507
                break;
 
508
        }
 
509
        
 
510
        DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag));
 
511
 
 
512
        return solaris_tag;
 
513
}
 
514
 
 
515
static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag)
 
516
{
 
517
        SMB_ACL_TAG_T smb_tag = 0;
 
518
 
 
519
        DEBUG(10, ("solaris_tag_to_smb_tag:\n"));
 
520
        DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag)); 
 
521
        
 
522
        solaris_tag &= ~ACL_DEFAULT; 
 
523
 
 
524
        switch (solaris_tag) {
 
525
        case USER:
 
526
                smb_tag = SMB_ACL_USER;
 
527
                break;
 
528
        case USER_OBJ:
 
529
                smb_tag = SMB_ACL_USER_OBJ;
 
530
                break;
 
531
        case GROUP:
 
532
                smb_tag = SMB_ACL_GROUP;
 
533
                break;
 
534
        case GROUP_OBJ:
 
535
                smb_tag = SMB_ACL_GROUP_OBJ;
 
536
                break;
 
537
        case OTHER_OBJ:
 
538
                smb_tag = SMB_ACL_OTHER;
 
539
                break;
 
540
        case CLASS_OBJ:
 
541
                smb_tag = SMB_ACL_MASK;
 
542
                break;
 
543
        default:
 
544
                DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n", 
 
545
                                        solaris_tag));
 
546
                break;
 
547
        }
 
548
 
 
549
        DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag));
 
550
        
 
551
        return smb_tag;
 
552
}
 
553
 
 
554
 
 
555
static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm)
 
556
{
 
557
        SMB_ACL_PERM_T smb_perm = 0;
 
558
        smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
 
559
        smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
 
560
        smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 
561
        return smb_perm;
 
562
}
 
563
 
 
564
 
 
565
static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm)
 
566
{
 
567
        SOLARIS_PERM_T solaris_perm = 0;
 
568
        solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
 
569
        solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
 
570
        solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 
571
        return solaris_perm;
 
572
}
 
573
 
 
574
 
 
575
static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl, 
 
576
                                 int *count)
 
577
{
 
578
        bool result = False;
 
579
 
 
580
        DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name));
 
581
        
 
582
        /* 
 
583
         * The original code tries some INITIAL_ACL_SIZE
 
584
         * and only did the GETACLCNT call upon failure
 
585
         * (for performance reasons).
 
586
         * For the sake of simplicity, I skip this for now. 
 
587
         */
 
588
        *count = acl(name, GETACLCNT, 0, NULL);
 
589
        if (*count < 0) {
 
590
                DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno)));
 
591
                goto done;
 
592
        }
 
593
        *solaris_acl = solaris_acl_init(*count);
 
594
        if (*solaris_acl == NULL) {
 
595
                DEBUG(10, ("error allocating memory for solaris acl...\n"));
 
596
                goto done;
 
597
        }
 
598
        *count = acl(name, GETACL, *count, *solaris_acl);
 
599
        if (*count < 0) {
 
600
                DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno)));
 
601
                goto done;
 
602
        }
 
603
        result = True;
 
604
 
 
605
 done:
 
606
        DEBUG(10, ("solaris_acl_get_file %s.\n",
 
607
                   ((result == True) ? "succeeded" : "failed" )));
 
608
        return result;
 
609
}
 
610
 
 
611
 
 
612
static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count)
 
613
{
 
614
        bool ret = False;
 
615
 
 
616
        DEBUG(10, ("entering solaris_acl_get_fd\n"));
 
617
 
 
618
        /* 
 
619
         * see solaris_acl_get_file for comment about omission 
 
620
         * of INITIAL_ACL_SIZE... 
 
621
         */
 
622
        *count = facl(fd, GETACLCNT, 0, NULL);
 
623
        if (*count < 0) {
 
624
                DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno)));
 
625
                goto done;
 
626
        }
 
627
        *solaris_acl = solaris_acl_init(*count);
 
628
        if (*solaris_acl == NULL) {
 
629
                DEBUG(10, ("error allocating memory for solaris acl...\n"));
 
630
                goto done;
 
631
        }
 
632
        *count = facl(fd, GETACL, *count, *solaris_acl);
 
633
        if (*count < 0) {
 
634
                DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno)));
 
635
                goto done;
 
636
        }
 
637
        ret = True;
 
638
 
 
639
 done:
 
640
        DEBUG(10, ("solaris_acl_get_fd %s\n",
 
641
                   ((ret == True) ? "succeeded" : "failed")));
 
642
        return ret;
 
643
}
 
644
 
 
645
 
 
646
 
 
647
/*
 
648
 * Add entries to a solaris ACL.
 
649
 *
 
650
 * Entries are directly added to the solarisacl parameter.
 
651
 * if memory allocation fails, this may result in solarisacl 
 
652
 * being NULL. if the resulting acl is to be checked and is 
 
653
 * not valid, it is kept in solarisacl but False is returned.
 
654
 *
 
655
 * The type of ACEs (access/default) to be added to the ACL can 
 
656
 * be selected via the type parameter. 
 
657
 * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS
 
658
 * is defined as "0", this means that one can only add either
 
659
 * access or default ACEs, not both at the same time. If it 
 
660
 * should become necessary to add all of an ACL, one would have
 
661
 * to replace this parameter by another type.
 
662
 */
 
663
static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
 
664
                               SOLARIS_ACL_T add_acl, int add_count, 
 
665
                               SMB_ACL_TYPE_T type)
 
666
{
 
667
        int i;
 
668
        
 
669
        if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) 
 
670
        {
 
671
                DEBUG(10, ("invalid acl type given: %d\n", type));
 
672
                errno = EINVAL;
 
673
                return False;
 
674
        }
 
675
        for (i = 0; i < add_count; i++) {
 
676
                if (!_IS_OF_TYPE(add_acl[i], type)) {
 
677
                        continue;
 
678
                }
 
679
                ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i], 
 
680
                             solaris_acl, count);
 
681
                if (solaris_acl == NULL) {
 
682
                        DEBUG(10, ("error enlarging acl.\n"));
 
683
                        errno = ENOMEM;
 
684
                        return False;
 
685
                }
 
686
        }
 
687
        return True;
 
688
}
 
689
 
 
690
 
 
691
/* 
 
692
 * sort the ACL and check it for validity
 
693
 *
 
694
 * [original comment from lib/sysacls.c:]
 
695
 * 
 
696
 * if it's a minimal ACL with only 4 entries then we
 
697
 * need to recalculate the mask permissions to make
 
698
 * sure that they are the same as the GROUP_OBJ
 
699
 * permissions as required by the UnixWare acl() system call.
 
700
 *
 
701
 * (note: since POSIX allows minimal ACLs which only contain
 
702
 * 3 entries - ie there is no mask entry - we should, in theory,
 
703
 * check for this and add a mask entry if necessary - however
 
704
 * we "know" that the caller of this interface always specifies
 
705
 * a mask, so in practice "this never happens" (tm) - if it *does*
 
706
 * happen aclsort() will fail and return an error and someone will
 
707
 * have to fix it...)
 
708
 */
 
709
static bool solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
 
710
{
 
711
        int fixmask = (count <= 4);
 
712
 
 
713
        if (aclsort(count, fixmask, solaris_acl) != 0) {
 
714
                errno = EINVAL;
 
715
                return False;
 
716
        }
 
717
        return True;
 
718
}
 
719
 
 
720
#if 0
 
721
/*
 
722
 * acl check function:
 
723
 *   unused at the moment but could be used to get more
 
724
 *   concrete error messages for debugging...
 
725
 *   (acl sort just says that the acl is invalid...)
 
726
 */
 
727
static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
 
728
{
 
729
        int check_rc;
 
730
        int check_which;
 
731
        
 
732
        check_rc = aclcheck(solaris_acl, count, &check_which);
 
733
        if (check_rc != 0) {
 
734
                DEBUG(10, ("acl is not valid:\n"));
 
735
                DEBUGADD(10, (" - return code: %d\n", check_rc));
 
736
                DEBUGADD(10, (" - which: %d\n", check_which));
 
737
                if (check_which != -1) {
 
738
                        DEBUGADD(10, (" - invalid entry:\n"));
 
739
                        DEBUGADD(10, ("   * type: %d:\n", 
 
740
                                      solaris_acl[check_which].a_type));
 
741
                        DEBUGADD(10, ("   * id: %d\n",
 
742
                                      solaris_acl[check_which].a_id));
 
743
                        DEBUGADD(10, ("   * perm: 0o%o\n",
 
744
                                      solaris_acl[check_which].a_perm));
 
745
                }
 
746
                return False;
 
747
        }
 
748
        return True;
 
749
}
 
750
#endif
 
751
 
 
752
/* VFS operations structure */
 
753
 
 
754
static vfs_op_tuple solarisacl_op_tuples[] = {
 
755
        /* Disk operations */
 
756
        {SMB_VFS_OP(solarisacl_sys_acl_get_file),
 
757
         SMB_VFS_OP_SYS_ACL_GET_FILE,
 
758
         SMB_VFS_LAYER_TRANSPARENT},
 
759
 
 
760
        {SMB_VFS_OP(solarisacl_sys_acl_get_fd),
 
761
         SMB_VFS_OP_SYS_ACL_GET_FD,
 
762
         SMB_VFS_LAYER_TRANSPARENT},
 
763
 
 
764
        {SMB_VFS_OP(solarisacl_sys_acl_set_file),
 
765
         SMB_VFS_OP_SYS_ACL_SET_FILE,
 
766
         SMB_VFS_LAYER_TRANSPARENT},
 
767
 
 
768
        {SMB_VFS_OP(solarisacl_sys_acl_set_fd),
 
769
         SMB_VFS_OP_SYS_ACL_SET_FD,
 
770
         SMB_VFS_LAYER_TRANSPARENT},
 
771
 
 
772
        {SMB_VFS_OP(solarisacl_sys_acl_delete_def_file),
 
773
         SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
 
774
         SMB_VFS_LAYER_TRANSPARENT},
 
775
 
 
776
        {SMB_VFS_OP(NULL),
 
777
         SMB_VFS_OP_NOOP,
 
778
         SMB_VFS_LAYER_NOOP}
 
779
};
 
780
 
 
781
NTSTATUS vfs_solarisacl_init(void);
 
782
NTSTATUS vfs_solarisacl_init(void)
 
783
{
 
784
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl",
 
785
                                solarisacl_op_tuples);
 
786
}
 
787
 
 
788
/* ENTE */