Include 2008 in the copyright years.
[rsync/rsync.git] / lib / sysacls.c
CommitLineData
4fd842f9
WD
1/*
2 * Unix SMB/CIFS implementation.
3 * Based on the Samba ACL support code.
4 * Copyright (C) Jeremy Allison 2000.
d3d07a5e 5 * Copyright (C) 2007-2008 Wayne Davison
4fd842f9
WD
6 *
7 * The permission functions have been changed to get/set all bits via
8 * one call. Some functions that rsync doesn't need were also removed.
9 *
10 * This program is free software; you can redistribute it and/or modify
8e41b68e
WD
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
4fd842f9
WD
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * with this program; if not, visit the http://fsf.org website.
22 */
1c3344a1
WD
23
24#include "rsync.h"
a30dcbc0 25#include "sysacls.h"
1c3344a1
WD
26
27#ifdef SUPPORT_ACLS
28
1c3344a1
WD
29#ifdef DEBUG
30#undef DEBUG
31#endif
32#define DEBUG(x,y)
33
34void SAFE_FREE(void *mem)
35{
36 if (mem)
37 free(mem);
38}
39
1c3344a1
WD
40/*
41 This file wraps all differing system ACL interfaces into a consistent
42 one based on the POSIX interface. It also returns the correct errors
43 for older UNIX systems that don't support ACLs.
44
45 The interfaces that each ACL implementation must support are as follows :
46
47 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
48 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
d417c516 49 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1
WD
50 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
51 SMB_ACL_T sys_acl_get_fd(int fd)
1c3344a1
WD
52 SMB_ACL_T sys_acl_init( int count)
53 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
d417c516 54 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
a30dcbc0 55 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
1c3344a1
WD
56 int sys_acl_valid( SMB_ACL_T theacl )
57 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
58 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
59 int sys_acl_delete_def_file(const char *path)
1c3344a1 60 int sys_acl_free_acl(SMB_ACL_T posix_acl)
1c3344a1
WD
61
62*/
63
d417c516 64#if defined(HAVE_POSIX_ACLS) /*--------------------------------------------*/
1c3344a1
WD
65
66/* Identity mapping - easy. */
67
68int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
69{
70 return acl_get_entry( the_acl, entry_id, entry_p);
71}
72
73int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
74{
75 return acl_get_tag_type( entry_d, tag_type_p);
76}
77
1c3344a1
WD
78SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
79{
80 return acl_get_file( path_p, type);
81}
82
a30dcbc0 83#if 0
1c3344a1
WD
84SMB_ACL_T sys_acl_get_fd(int fd)
85{
86 return acl_get_fd(fd);
87}
a30dcbc0 88#endif
1c3344a1 89
1c3344a1 90#if defined(HAVE_ACL_GET_PERM_NP)
a30dcbc0 91#define acl_get_perm(p, b) acl_get_perm_np(p, b)
1c3344a1 92#endif
1c3344a1 93
d417c516 94int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1 95{
d417c516
WD
96 acl_permset_t permset;
97
98 if (acl_get_tag_type(entry, tag_type_p) != 0
99 || acl_get_permset(entry, &permset) != 0)
100 return -1;
101
102 *bits_p = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
103 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
104 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
105
106 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
107 void *qual;
108 if ((qual = acl_get_qualifier(entry)) == NULL)
109 return -1;
110 *u_g_id_p = *(id_t*)qual;
111 acl_free(qual);
112 }
113
a30dcbc0 114 return 0;
1c3344a1
WD
115}
116
117SMB_ACL_T sys_acl_init( int count)
118{
119 return acl_init(count);
120}
121
122int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
123{
124 return acl_create_entry(pacl, pentry);
125}
126
d417c516 127int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 128{
d417c516
WD
129 if (acl_set_tag_type(entry, tag_type) != 0)
130 return -1;
1c3344a1 131
d417c516
WD
132 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
133 if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
134 return -1;
135 }
136
137 return sys_acl_set_access_bits(entry, bits);
1c3344a1
WD
138}
139
a30dcbc0 140int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
1c3344a1 141{
d417c516 142 acl_permset_t permset;
a30dcbc0
WD
143 int rc;
144 if ((rc = acl_get_permset(entry, &permset)) != 0)
145 return rc;
146 acl_clear_perms(permset);
147 if (bits & 4)
148 acl_add_perm(permset, ACL_READ);
149 if (bits & 2)
150 acl_add_perm(permset, ACL_WRITE);
151 if (bits & 1)
152 acl_add_perm(permset, ACL_EXECUTE);
1c3344a1
WD
153 return acl_set_permset(entry, permset);
154}
155
156int sys_acl_valid( SMB_ACL_T theacl )
157{
158 return acl_valid(theacl);
159}
160
161int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
162{
163 return acl_set_file(name, acltype, theacl);
164}
165
d417c516 166#if 0
1c3344a1
WD
167int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
168{
169 return acl_set_fd(fd, theacl);
170}
d417c516 171#endif
1c3344a1
WD
172
173int sys_acl_delete_def_file(const char *name)
174{
175 return acl_delete_def_file(name);
176}
177
1c3344a1
WD
178int sys_acl_free_acl(SMB_ACL_T the_acl)
179{
180 return acl_free(the_acl);
181}
182
d417c516 183#elif defined(HAVE_TRU64_ACLS) /*--------------------------------------------*/
1c3344a1
WD
184/*
185 * The interface to DEC/Compaq Tru64 UNIX ACLs
186 * is based on Draft 13 of the POSIX spec which is
187 * slightly different from the Draft 16 interface.
188 *
189 * Also, some of the permset manipulation functions
190 * such as acl_clear_perm() and acl_add_perm() appear
191 * to be broken on Tru64 so we have to manipulate
192 * the permission bits in the permset directly.
193 */
194int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
195{
196 SMB_ACL_ENTRY_T entry;
197
198 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
199 return -1;
200 }
201
202 errno = 0;
203 if ((entry = acl_get_entry(the_acl)) != NULL) {
204 *entry_p = entry;
205 return 1;
206 }
207
208 return errno ? -1 : 0;
209}
210
211int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
212{
213 return acl_get_tag_type( entry_d, tag_type_p);
214}
215
1c3344a1
WD
216SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
217{
218 return acl_get_file((char *)path_p, type);
219}
220
a30dcbc0 221#if 0
1c3344a1
WD
222SMB_ACL_T sys_acl_get_fd(int fd)
223{
224 return acl_get_fd(fd, ACL_TYPE_ACCESS);
225}
a30dcbc0 226#endif
1c3344a1 227
d417c516 228int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1 229{
d417c516
WD
230 acl_permset_t permset;
231
232 if (acl_get_tag_type(entry, tag_type_p) != 0
233 || acl_get_permset(entry, &permset) != 0)
234 return -1;
235
236 *bits_p = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
237
238 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
239 void *qual;
240 if ((qual = acl_get_qualifier(entry)) == NULL)
241 return -1;
242 *u_g_id_p = *(id_t*)qual;
243 acl_free_qualifier(qual, *tag_type_p);
244 }
245
1c3344a1
WD
246 return 0;
247}
248
1c3344a1
WD
249SMB_ACL_T sys_acl_init( int count)
250{
251 return acl_init(count);
252}
253
254int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
255{
256 SMB_ACL_ENTRY_T entry;
257
258 if ((entry = acl_create_entry(pacl)) == NULL) {
259 return -1;
260 }
261
262 *pentry = entry;
263 return 0;
264}
265
d417c516 266int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 267{
d417c516
WD
268 if (acl_set_tag_type(entry, tag_type) != 0)
269 return -1;
1c3344a1 270
d417c516
WD
271 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
272 if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
273 return -1;
274 }
275
276 return sys_acl_set_access_bits(entry, bits);
1c3344a1
WD
277}
278
a30dcbc0 279int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
1c3344a1 280{
d417c516 281 acl_permset_t permset;
a30dcbc0
WD
282 int rc;
283 if ((rc = acl_get_permset(entry, &permset)) != 0)
284 return rc;
a30dcbc0 285 *permset = bits & 7;
1c3344a1
WD
286 return acl_set_permset(entry, permset);
287}
288
289int sys_acl_valid( SMB_ACL_T theacl )
290{
291 acl_entry_t entry;
292
293 return acl_valid(theacl, &entry);
294}
295
296int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
297{
298 return acl_set_file((char *)name, acltype, theacl);
299}
300
d417c516 301#if 0
1c3344a1
WD
302int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
303{
304 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
305}
d417c516 306#endif
1c3344a1
WD
307
308int sys_acl_delete_def_file(const char *name)
309{
310 return acl_delete_def_file((char *)name);
311}
312
1c3344a1
WD
313int sys_acl_free_acl(SMB_ACL_T the_acl)
314{
315 return acl_free(the_acl);
316}
317
d417c516 318#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) /*-----------*/
1c3344a1
WD
319
320/*
321 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
322 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
323 */
324
325/*
326 * Note that while this code implements sufficient functionality
327 * to support the sys_acl_* interfaces it does not provide all
328 * of the semantics of the POSIX ACL interfaces.
329 *
330 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
331 * from a call to sys_acl_get_entry() should not be assumed to be
332 * valid after calling any of the following functions, which may
333 * reorder the entries in the ACL.
334 *
335 * sys_acl_valid()
336 * sys_acl_set_file()
337 * sys_acl_set_fd()
338 */
339
340/*
341 * The only difference between Solaris and UnixWare / OpenUNIX is
342 * that the #defines for the ACL operations have different names
343 */
344#if defined(HAVE_UNIXWARE_ACLS)
345
346#define SETACL ACL_SET
347#define GETACL ACL_GET
348#define GETACLCNT ACL_CNT
349
350#endif
351
352
353int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
354{
355 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
356 errno = EINVAL;
357 return -1;
358 }
359
360 if (entry_p == NULL) {
361 errno = EINVAL;
362 return -1;
363 }
364
365 if (entry_id == SMB_ACL_FIRST_ENTRY) {
366 acl_d->next = 0;
367 }
368
369 if (acl_d->next < 0) {
370 errno = EINVAL;
371 return -1;
372 }
373
374 if (acl_d->next >= acl_d->count) {
375 return 0;
376 }
377
378 *entry_p = &acl_d->acl[acl_d->next++];
379
380 return 1;
381}
382
383int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
384{
385 *type_p = entry_d->a_type;
386
387 return 0;
388}
389
1c3344a1
WD
390/*
391 * There is no way of knowing what size the ACL returned by
392 * GETACL will be unless you first call GETACLCNT which means
393 * making an additional system call.
394 *
395 * In the hope of avoiding the cost of the additional system
396 * call in most cases, we initially allocate enough space for
397 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
398 * be too small then we use GETACLCNT to find out the actual
399 * size, reallocate the ACL buffer, and then call GETACL again.
400 */
401
402#define INITIAL_ACL_SIZE 16
403
404SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
405{
406 SMB_ACL_T acl_d;
407 int count; /* # of ACL entries allocated */
408 int naccess; /* # of access ACL entries */
409 int ndefault; /* # of default ACL entries */
410
411 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
412 errno = EINVAL;
413 return NULL;
414 }
415
416 count = INITIAL_ACL_SIZE;
417 if ((acl_d = sys_acl_init(count)) == NULL) {
418 return NULL;
419 }
420
421 /*
422 * If there isn't enough space for the ACL entries we use
423 * GETACLCNT to determine the actual number of ACL entries
424 * reallocate and try again. This is in a loop because it
425 * is possible that someone else could modify the ACL and
426 * increase the number of entries between the call to
427 * GETACLCNT and the call to GETACL.
428 */
429 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
430 && errno == ENOSPC) {
431
432 sys_acl_free_acl(acl_d);
433
434 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
435 return NULL;
436 }
437
438 if ((acl_d = sys_acl_init(count)) == NULL) {
439 return NULL;
440 }
441 }
442
443 if (count < 0) {
444 sys_acl_free_acl(acl_d);
445 return NULL;
446 }
447
448 /*
449 * calculate the number of access and default ACL entries
450 *
451 * Note: we assume that the acl() system call returned a
452 * well formed ACL which is sorted so that all of the
453 * access ACL entries preceed any default ACL entries
454 */
455 for (naccess = 0; naccess < count; naccess++) {
456 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
457 break;
458 }
459 ndefault = count - naccess;
460
461 /*
462 * if the caller wants the default ACL we have to copy
463 * the entries down to the start of the acl[] buffer
464 * and mask out the ACL_DEFAULT flag from the type field
465 */
466 if (type == SMB_ACL_TYPE_DEFAULT) {
467 int i, j;
468
469 for (i = 0, j = naccess; i < ndefault; i++, j++) {
470 acl_d->acl[i] = acl_d->acl[j];
471 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
472 }
473
474 acl_d->count = ndefault;
475 } else {
476 acl_d->count = naccess;
477 }
478
479 return acl_d;
480}
481
a30dcbc0 482#if 0
1c3344a1
WD
483SMB_ACL_T sys_acl_get_fd(int fd)
484{
485 SMB_ACL_T acl_d;
486 int count; /* # of ACL entries allocated */
487 int naccess; /* # of access ACL entries */
488
489 count = INITIAL_ACL_SIZE;
490 if ((acl_d = sys_acl_init(count)) == NULL) {
491 return NULL;
492 }
493
494 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
495 && errno == ENOSPC) {
496
497 sys_acl_free_acl(acl_d);
498
499 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
500 return NULL;
501 }
502
503 if ((acl_d = sys_acl_init(count)) == NULL) {
504 return NULL;
505 }
506 }
507
508 if (count < 0) {
509 sys_acl_free_acl(acl_d);
510 return NULL;
511 }
512
513 /*
514 * calculate the number of access ACL entries
515 */
516 for (naccess = 0; naccess < count; naccess++) {
517 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
518 break;
519 }
520
521 acl_d->count = naccess;
522
523 return acl_d;
524}
a30dcbc0 525#endif
1c3344a1 526
d417c516 527int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1 528{
d417c516
WD
529 *tag_type_p = entry->a_type;
530
531 *bits_p = entry->a_perm;
532
533 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
534 *u_g_id_p = entry->a_id;
535
1c3344a1
WD
536 return 0;
537}
538
1c3344a1
WD
539SMB_ACL_T sys_acl_init(int count)
540{
541 SMB_ACL_T a;
542
543 if (count < 0) {
544 errno = EINVAL;
545 return NULL;
546 }
547
548 /*
549 * note that since the definition of the structure pointed
550 * to by the SMB_ACL_T includes the first element of the
551 * acl[] array, this actually allocates an ACL with room
552 * for (count+1) entries
553 */
554 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
555 errno = ENOMEM;
556 return NULL;
557 }
558
559 a->size = count + 1;
560 a->count = 0;
561 a->next = -1;
562
563 return a;
564}
565
566
567int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
568{
569 SMB_ACL_T acl_d;
570 SMB_ACL_ENTRY_T entry_d;
571
572 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
573 errno = EINVAL;
574 return -1;
575 }
576
577 if (acl_d->count >= acl_d->size) {
578 errno = ENOSPC;
579 return -1;
580 }
581
582 entry_d = &acl_d->acl[acl_d->count++];
583 entry_d->a_type = 0;
584 entry_d->a_id = -1;
585 entry_d->a_perm = 0;
586 *entry_p = entry_d;
587
588 return 0;
589}
590
d417c516 591int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 592{
d417c516 593 entry->a_type = tag_type;
1c3344a1 594
d417c516
WD
595 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
596 entry->a_id = u_g_id;
1c3344a1 597
d417c516 598 entry->a_perm = bits;
1c3344a1
WD
599
600 return 0;
601}
602
a30dcbc0 603int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1c3344a1 604{
a30dcbc0 605 entry_d->a_perm = bits;
1c3344a1
WD
606 return 0;
607}
608
609/*
610 * sort the ACL and check it for validity
611 *
612 * if it's a minimal ACL with only 4 entries then we
613 * need to recalculate the mask permissions to make
614 * sure that they are the same as the GROUP_OBJ
615 * permissions as required by the UnixWare acl() system call.
616 *
617 * (note: since POSIX allows minimal ACLs which only contain
618 * 3 entries - ie there is no mask entry - we should, in theory,
619 * check for this and add a mask entry if necessary - however
620 * we "know" that the caller of this interface always specifies
621 * a mask so, in practice "this never happens" (tm) - if it *does*
622 * happen aclsort() will fail and return an error and someone will
623 * have to fix it ...)
624 */
625
626static int acl_sort(SMB_ACL_T acl_d)
627{
628 int fixmask = (acl_d->count <= 4);
629
630 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
631 errno = EINVAL;
632 return -1;
633 }
634 return 0;
635}
636
637int sys_acl_valid(SMB_ACL_T acl_d)
638{
639 return acl_sort(acl_d);
640}
641
642int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
643{
644 struct stat s;
645 struct acl *acl_p;
646 int acl_count;
647 struct acl *acl_buf = NULL;
648 int ret;
649
650 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
651 errno = EINVAL;
652 return -1;
653 }
654
655 if (acl_sort(acl_d) != 0) {
656 return -1;
657 }
658
659 acl_p = &acl_d->acl[0];
660 acl_count = acl_d->count;
661
662 /*
663 * if it's a directory there is extra work to do
664 * since the acl() system call will replace both
665 * the access ACLs and the default ACLs (if any)
666 */
667 if (stat(name, &s) != 0) {
668 return -1;
669 }
670 if (S_ISDIR(s.st_mode)) {
671 SMB_ACL_T acc_acl;
672 SMB_ACL_T def_acl;
673 SMB_ACL_T tmp_acl;
674 int i;
675
676 if (type == SMB_ACL_TYPE_ACCESS) {
677 acc_acl = acl_d;
678 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
679
680 } else {
681 def_acl = acl_d;
682 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
683 }
684
685 if (tmp_acl == NULL) {
686 return -1;
687 }
688
689 /*
690 * allocate a temporary buffer for the complete ACL
691 */
692 acl_count = acc_acl->count + def_acl->count;
693 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
694
695 if (acl_buf == NULL) {
696 sys_acl_free_acl(tmp_acl);
697 errno = ENOMEM;
698 return -1;
699 }
700
701 /*
702 * copy the access control and default entries into the buffer
703 */
704 memcpy(&acl_buf[0], &acc_acl->acl[0],
705 acc_acl->count * sizeof(acl_buf[0]));
706
707 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
708 def_acl->count * sizeof(acl_buf[0]));
709
710 /*
711 * set the ACL_DEFAULT flag on the default entries
712 */
713 for (i = acc_acl->count; i < acl_count; i++) {
714 acl_buf[i].a_type |= ACL_DEFAULT;
715 }
716
717 sys_acl_free_acl(tmp_acl);
718
719 } else if (type != SMB_ACL_TYPE_ACCESS) {
720 errno = EINVAL;
721 return -1;
722 }
723
724 ret = acl(name, SETACL, acl_count, acl_p);
725
726 SAFE_FREE(acl_buf);
727
728 return ret;
729}
730
d417c516 731#if 0
1c3344a1
WD
732int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
733{
734 if (acl_sort(acl_d) != 0) {
735 return -1;
736 }
737
738 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
739}
d417c516 740#endif
1c3344a1
WD
741
742int sys_acl_delete_def_file(const char *path)
743{
744 SMB_ACL_T acl_d;
745 int ret;
746
747 /*
748 * fetching the access ACL and rewriting it has
749 * the effect of deleting the default ACL
750 */
751 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
752 return -1;
753 }
754
755 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
756
757 sys_acl_free_acl(acl_d);
758
759 return ret;
760}
761
1c3344a1
WD
762int sys_acl_free_acl(SMB_ACL_T acl_d)
763{
764 SAFE_FREE(acl_d);
765 return 0;
766}
767
d417c516 768#elif defined(HAVE_HPUX_ACLS) /*---------------------------------------------*/
1c3344a1 769
1c3344a1
WD
770#include <dl.h>
771
772/*
773 * Based on the Solaris/SCO code - with modifications.
774 */
775
776/*
777 * Note that while this code implements sufficient functionality
778 * to support the sys_acl_* interfaces it does not provide all
779 * of the semantics of the POSIX ACL interfaces.
780 *
781 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
782 * from a call to sys_acl_get_entry() should not be assumed to be
783 * valid after calling any of the following functions, which may
784 * reorder the entries in the ACL.
785 *
786 * sys_acl_valid()
787 * sys_acl_set_file()
788 * sys_acl_set_fd()
789 */
790
791/* This checks if the POSIX ACL system call is defined */
792/* which basically corresponds to whether JFS 3.3 or */
793/* higher is installed. If acl() was called when it */
794/* isn't defined, it causes the process to core dump */
795/* so it is important to check this and avoid acl() */
796/* calls if it isn't there. */
797
798static BOOL hpux_acl_call_presence(void)
799{
800
801 shl_t handle = NULL;
802 void *value;
803 int ret_val=0;
804 static BOOL already_checked=0;
805
806 if(already_checked)
807 return True;
808
809
810 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
811
812 if(ret_val != 0) {
813 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
814 ret_val, errno, strerror(errno)));
815 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
816 return False;
817 }
818
819 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
820
821 already_checked = True;
822 return True;
823}
824
825int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
826{
827 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
828 errno = EINVAL;
829 return -1;
830 }
831
832 if (entry_p == NULL) {
833 errno = EINVAL;
834 return -1;
835 }
836
837 if (entry_id == SMB_ACL_FIRST_ENTRY) {
838 acl_d->next = 0;
839 }
840
841 if (acl_d->next < 0) {
842 errno = EINVAL;
843 return -1;
844 }
845
846 if (acl_d->next >= acl_d->count) {
847 return 0;
848 }
849
850 *entry_p = &acl_d->acl[acl_d->next++];
851
852 return 1;
853}
854
855int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
856{
857 *type_p = entry_d->a_type;
858
859 return 0;
860}
861
1c3344a1
WD
862/*
863 * There is no way of knowing what size the ACL returned by
864 * ACL_GET will be unless you first call ACL_CNT which means
865 * making an additional system call.
866 *
867 * In the hope of avoiding the cost of the additional system
868 * call in most cases, we initially allocate enough space for
869 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
870 * be too small then we use ACL_CNT to find out the actual
871 * size, reallocate the ACL buffer, and then call ACL_GET again.
872 */
873
874#define INITIAL_ACL_SIZE 16
875
876SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
877{
878 SMB_ACL_T acl_d;
879 int count; /* # of ACL entries allocated */
880 int naccess; /* # of access ACL entries */
881 int ndefault; /* # of default ACL entries */
882
883 if(hpux_acl_call_presence() == False) {
884 /* Looks like we don't have the acl() system call on HPUX.
885 * May be the system doesn't have the latest version of JFS.
886 */
887 return NULL;
888 }
889
890 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
891 errno = EINVAL;
892 return NULL;
893 }
894
895 count = INITIAL_ACL_SIZE;
896 if ((acl_d = sys_acl_init(count)) == NULL) {
897 return NULL;
898 }
899
900 /*
901 * If there isn't enough space for the ACL entries we use
902 * ACL_CNT to determine the actual number of ACL entries
903 * reallocate and try again. This is in a loop because it
904 * is possible that someone else could modify the ACL and
905 * increase the number of entries between the call to
906 * ACL_CNT and the call to ACL_GET.
907 */
908 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
909
910 sys_acl_free_acl(acl_d);
911
912 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
913 return NULL;
914 }
915
916 if ((acl_d = sys_acl_init(count)) == NULL) {
917 return NULL;
918 }
919 }
920
921 if (count < 0) {
922 sys_acl_free_acl(acl_d);
923 return NULL;
924 }
925
926 /*
927 * calculate the number of access and default ACL entries
928 *
929 * Note: we assume that the acl() system call returned a
930 * well formed ACL which is sorted so that all of the
931 * access ACL entries preceed any default ACL entries
932 */
933 for (naccess = 0; naccess < count; naccess++) {
934 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
935 break;
936 }
937 ndefault = count - naccess;
938
939 /*
940 * if the caller wants the default ACL we have to copy
941 * the entries down to the start of the acl[] buffer
942 * and mask out the ACL_DEFAULT flag from the type field
943 */
944 if (type == SMB_ACL_TYPE_DEFAULT) {
945 int i, j;
946
947 for (i = 0, j = naccess; i < ndefault; i++, j++) {
948 acl_d->acl[i] = acl_d->acl[j];
949 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
950 }
951
952 acl_d->count = ndefault;
953 } else {
954 acl_d->count = naccess;
955 }
956
957 return acl_d;
958}
959
1b897d50 960#if 0
1c3344a1
WD
961SMB_ACL_T sys_acl_get_fd(int fd)
962{
963 /*
964 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
965 */
966
967 files_struct *fsp = file_find_fd(fd);
968
969 if (fsp == NULL) {
970 errno = EBADF;
971 return NULL;
972 }
973
974 /*
975 * We know we're in the same conn context. So we
976 * can use the relative path.
977 */
978
979 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
980}
1b897d50 981#endif
1c3344a1 982
d417c516 983int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1 984{
d417c516
WD
985 *tag_type_p = entry->a_type;
986
987 *bits_p = entry->a_perm;
988
989 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
990 *u_g_id_p = entry->a_id;
1c3344a1
WD
991
992 return 0;
993}
994
1c3344a1
WD
995SMB_ACL_T sys_acl_init(int count)
996{
997 SMB_ACL_T a;
998
999 if (count < 0) {
1000 errno = EINVAL;
1001 return NULL;
1002 }
1003
1004 /*
1005 * note that since the definition of the structure pointed
1006 * to by the SMB_ACL_T includes the first element of the
1007 * acl[] array, this actually allocates an ACL with room
1008 * for (count+1) entries
1009 */
1010 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1011 errno = ENOMEM;
1012 return NULL;
1013 }
1014
1015 a->size = count + 1;
1016 a->count = 0;
1017 a->next = -1;
1018
1019 return a;
1020}
1021
1022
1023int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1024{
1025 SMB_ACL_T acl_d;
1026 SMB_ACL_ENTRY_T entry_d;
1027
1028 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1029 errno = EINVAL;
1030 return -1;
1031 }
1032
1033 if (acl_d->count >= acl_d->size) {
1034 errno = ENOSPC;
1035 return -1;
1036 }
1037
1038 entry_d = &acl_d->acl[acl_d->count++];
1039 entry_d->a_type = 0;
1040 entry_d->a_id = -1;
1041 entry_d->a_perm = 0;
1042 *entry_p = entry_d;
1043
1044 return 0;
1045}
1046
d417c516 1047int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 1048{
d417c516 1049 entry->a_type = tag_type;
1c3344a1 1050
d417c516
WD
1051 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
1052 entry->a_id = u_g_id;
1c3344a1 1053
d417c516 1054 entry->a_perm = bits;
1c3344a1
WD
1055
1056 return 0;
1057}
1058
a30dcbc0 1059int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1c3344a1 1060{
a30dcbc0 1061 entry_d->a_perm = bits;
1c3344a1
WD
1062
1063 return 0;
1064}
1065
1066/* Structure to capture the count for each type of ACE. */
1067
1068struct hpux_acl_types {
1069 int n_user;
1070 int n_def_user;
1071 int n_user_obj;
1072 int n_def_user_obj;
1073
1074 int n_group;
1075 int n_def_group;
1076 int n_group_obj;
1077 int n_def_group_obj;
1078
1079 int n_other;
1080 int n_other_obj;
1081 int n_def_other_obj;
1082
1083 int n_class_obj;
1084 int n_def_class_obj;
1085
1086 int n_illegal_obj;
1087};
1088
1089/* count_obj:
1090 * Counts the different number of objects in a given array of ACL
1091 * structures.
1092 * Inputs:
1093 *
1094 * acl_count - Count of ACLs in the array of ACL strucutres.
1095 * aclp - Array of ACL structures.
1096 * acl_type_count - Pointer to acl_types structure. Should already be
1097 * allocated.
1098 * Output:
1099 *
1100 * acl_type_count - This structure is filled up with counts of various
1101 * acl types.
1102 */
1103
90c71cae 1104static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1c3344a1
WD
1105{
1106 int i;
1107
1108 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1109
1110 for(i=0;i<acl_count;i++) {
1111 switch(aclp[i].a_type) {
1112 case USER:
1113 acl_type_count->n_user++;
1114 break;
1115 case USER_OBJ:
1116 acl_type_count->n_user_obj++;
1117 break;
1118 case DEF_USER_OBJ:
1119 acl_type_count->n_def_user_obj++;
1120 break;
1121 case GROUP:
1122 acl_type_count->n_group++;
1123 break;
1124 case GROUP_OBJ:
1125 acl_type_count->n_group_obj++;
1126 break;
1127 case DEF_GROUP_OBJ:
1128 acl_type_count->n_def_group_obj++;
1129 break;
1130 case OTHER_OBJ:
1131 acl_type_count->n_other_obj++;
1132 break;
1133 case DEF_OTHER_OBJ:
1134 acl_type_count->n_def_other_obj++;
1135 break;
1136 case CLASS_OBJ:
1137 acl_type_count->n_class_obj++;
1138 break;
1139 case DEF_CLASS_OBJ:
1140 acl_type_count->n_def_class_obj++;
1141 break;
1142 case DEF_USER:
1143 acl_type_count->n_def_user++;
1144 break;
1145 case DEF_GROUP:
1146 acl_type_count->n_def_group++;
1147 break;
1148 default:
1149 acl_type_count->n_illegal_obj++;
1150 break;
1151 }
1152 }
1153}
1154
1155/* swap_acl_entries: Swaps two ACL entries.
1156 *
1157 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1158 */
1159
1160static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1161{
1162 struct acl temp_acl;
1163
1164 temp_acl.a_type = aclp0->a_type;
1165 temp_acl.a_id = aclp0->a_id;
1166 temp_acl.a_perm = aclp0->a_perm;
1167
1168 aclp0->a_type = aclp1->a_type;
1169 aclp0->a_id = aclp1->a_id;
1170 aclp0->a_perm = aclp1->a_perm;
1171
1172 aclp1->a_type = temp_acl.a_type;
1173 aclp1->a_id = temp_acl.a_id;
1174 aclp1->a_perm = temp_acl.a_perm;
1175}
1176
1177/* prohibited_duplicate_type
1178 * Identifies if given ACL type can have duplicate entries or
1179 * not.
1180 *
1181 * Inputs: acl_type - ACL Type.
1182 *
1183 * Outputs:
1184 *
1185 * Return..
1186 *
1187 * True - If the ACL type matches any of the prohibited types.
1188 * False - If the ACL type doesn't match any of the prohibited types.
1189 */
1190
1191static BOOL hpux_prohibited_duplicate_type(int acl_type)
1192{
1193 switch(acl_type) {
1194 case USER:
1195 case GROUP:
1196 case DEF_USER:
1197 case DEF_GROUP:
1198 return True;
1199 default:
1200 return False;
1201 }
1202}
1203
1204/* get_needed_class_perm
1205 * Returns the permissions of a ACL structure only if the ACL
1206 * type matches one of the pre-determined types for computing
1207 * CLASS_OBJ permissions.
1208 *
1209 * Inputs: aclp - Pointer to ACL structure.
1210 */
1211
1212static int hpux_get_needed_class_perm(struct acl *aclp)
1213{
1214 switch(aclp->a_type) {
1215 case USER:
1216 case GROUP_OBJ:
1217 case GROUP:
1218 case DEF_USER_OBJ:
1219 case DEF_USER:
1220 case DEF_GROUP_OBJ:
1221 case DEF_GROUP:
1222 case DEF_CLASS_OBJ:
1223 case DEF_OTHER_OBJ:
1224 return aclp->a_perm;
1225 default:
1226 return 0;
1227 }
1228}
1229
1230/* acl_sort for HPUX.
1231 * Sorts the array of ACL structures as per the description in
1232 * aclsort man page. Refer to aclsort man page for more details
1233 *
1234 * Inputs:
1235 *
1236 * acl_count - Count of ACLs in the array of ACL structures.
1237 * calclass - If this is not zero, then we compute the CLASS_OBJ
1238 * permissions.
1239 * aclp - Array of ACL structures.
1240 *
1241 * Outputs:
1242 *
1243 * aclp - Sorted array of ACL structures.
1244 *
1245 * Outputs:
1246 *
1247 * Returns 0 for success -1 for failure. Prints a message to the Samba
1248 * debug log in case of failure.
1249 */
1250
1251static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1252{
1253#if !defined(HAVE_HPUX_ACLSORT)
1254 /*
1255 * The aclsort() system call is availabe on the latest HPUX General
1256 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1257 * function. Because, we don't want to update to a new
1258 * HPUX GR bundle just for aclsort() call.
1259 */
1260
1261 struct hpux_acl_types acl_obj_count;
1262 int n_class_obj_perm = 0;
1263 int i, j;
1264
1265 if(!acl_count) {
1266 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1267 return 0;
1268 }
1269
1270 if(aclp == NULL) {
1271 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1272 return -1;
1273 }
1274
1275 /* Count different types of ACLs in the ACLs array */
1276
1277 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1278
1279 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1280 * CLASS_OBJ and OTHER_OBJ
1281 */
1282
1283 if( (acl_obj_count.n_user_obj != 1) ||
1284 (acl_obj_count.n_group_obj != 1) ||
1285 (acl_obj_count.n_class_obj != 1) ||
1286 (acl_obj_count.n_other_obj != 1)
1287 ) {
1288 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1289USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1290 return -1;
1291 }
1292
1293 /* If any of the default objects are present, there should be only
1294 * one of them each.
1295 */
1296
1297 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1298 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1299 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1300or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1301 return -1;
1302 }
1303
1304 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1305 * structures.
1306 *
1307 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1308 * same ACL type, sort by ACL id.
1309 *
1310 * I am using the trival kind of sorting method here because, performance isn't
1311 * really effected by the ACLs feature. More over there aren't going to be more
1312 * than 17 entries on HPUX.
1313 */
1314
1315 for(i=0; i<acl_count;i++) {
1316 for (j=i+1; j<acl_count; j++) {
1317 if( aclp[i].a_type > aclp[j].a_type ) {
1318 /* ACL entries out of order, swap them */
1319
1320 hpux_swap_acl_entries((aclp+i), (aclp+j));
1321
1322 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1323
1324 /* ACL entries of same type, sort by id */
1325
1326 if(aclp[i].a_id > aclp[j].a_id) {
1327 hpux_swap_acl_entries((aclp+i), (aclp+j));
1328 } else if (aclp[i].a_id == aclp[j].a_id) {
1329 /* We have a duplicate entry. */
1330 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1331 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1332 aclp[i].a_type, aclp[i].a_id));
1333 return -1;
1334 }
1335 }
1336
1337 }
1338 }
1339 }
1340
1341 /* set the class obj permissions to the computed one. */
1342 if(calclass) {
1343 int n_class_obj_index = -1;
1344
1345 for(i=0;i<acl_count;i++) {
1346 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1347
1348 if(aclp[i].a_type == CLASS_OBJ)
1349 n_class_obj_index = i;
1350 }
1351 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1352 }
1353
1354 return 0;
1355#else
1356 return aclsort(acl_count, calclass, aclp);
1357#endif
1358}
1359
1360/*
1361 * sort the ACL and check it for validity
1362 *
1363 * if it's a minimal ACL with only 4 entries then we
1364 * need to recalculate the mask permissions to make
1365 * sure that they are the same as the GROUP_OBJ
1366 * permissions as required by the UnixWare acl() system call.
1367 *
1368 * (note: since POSIX allows minimal ACLs which only contain
1369 * 3 entries - ie there is no mask entry - we should, in theory,
1370 * check for this and add a mask entry if necessary - however
1371 * we "know" that the caller of this interface always specifies
1372 * a mask so, in practice "this never happens" (tm) - if it *does*
1373 * happen aclsort() will fail and return an error and someone will
1374 * have to fix it ...)
1375 */
1376
1377static int acl_sort(SMB_ACL_T acl_d)
1378{
1379 int fixmask = (acl_d->count <= 4);
1380
1381 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1382 errno = EINVAL;
1383 return -1;
1384 }
1385 return 0;
1386}
1387
1388int sys_acl_valid(SMB_ACL_T acl_d)
1389{
1390 return acl_sort(acl_d);
1391}
1392
1393int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1394{
1395 struct stat s;
1396 struct acl *acl_p;
1397 int acl_count;
1398 struct acl *acl_buf = NULL;
1399 int ret;
1400
1401 if(hpux_acl_call_presence() == False) {
1402 /* Looks like we don't have the acl() system call on HPUX.
1403 * May be the system doesn't have the latest version of JFS.
1404 */
1405 errno=ENOSYS;
1406 return -1;
1407 }
1408
1409 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1410 errno = EINVAL;
1411 return -1;
1412 }
1413
1414 if (acl_sort(acl_d) != 0) {
1415 return -1;
1416 }
1417
1418 acl_p = &acl_d->acl[0];
1419 acl_count = acl_d->count;
1420
1421 /*
1422 * if it's a directory there is extra work to do
1423 * since the acl() system call will replace both
1424 * the access ACLs and the default ACLs (if any)
1425 */
1426 if (stat(name, &s) != 0) {
1427 return -1;
1428 }
1429 if (S_ISDIR(s.st_mode)) {
1430 SMB_ACL_T acc_acl;
1431 SMB_ACL_T def_acl;
1432 SMB_ACL_T tmp_acl;
1433 int i;
1434
1435 if (type == SMB_ACL_TYPE_ACCESS) {
1436 acc_acl = acl_d;
1437 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1438
1439 } else {
1440 def_acl = acl_d;
1441 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1442 }
1443
1444 if (tmp_acl == NULL) {
1445 return -1;
1446 }
1447
1448 /*
1449 * allocate a temporary buffer for the complete ACL
1450 */
1451 acl_count = acc_acl->count + def_acl->count;
1452 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1453
1454 if (acl_buf == NULL) {
1455 sys_acl_free_acl(tmp_acl);
1456 errno = ENOMEM;
1457 return -1;
1458 }
1459
1460 /*
1461 * copy the access control and default entries into the buffer
1462 */
1463 memcpy(&acl_buf[0], &acc_acl->acl[0],
1464 acc_acl->count * sizeof(acl_buf[0]));
1465
1466 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1467 def_acl->count * sizeof(acl_buf[0]));
1468
1469 /*
1470 * set the ACL_DEFAULT flag on the default entries
1471 */
1472 for (i = acc_acl->count; i < acl_count; i++) {
1473 acl_buf[i].a_type |= ACL_DEFAULT;
1474 }
1475
1476 sys_acl_free_acl(tmp_acl);
1477
1478 } else if (type != SMB_ACL_TYPE_ACCESS) {
1479 errno = EINVAL;
1480 return -1;
1481 }
1482
1483 ret = acl(name, ACL_SET, acl_count, acl_p);
1484
1485 if (acl_buf) {
1486 free(acl_buf);
1487 }
1488
1489 return ret;
1490}
1491
1b897d50 1492#if 0
1c3344a1
WD
1493int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1494{
1495 /*
1496 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1497 */
1498
1499 files_struct *fsp = file_find_fd(fd);
1500
1501 if (fsp == NULL) {
1502 errno = EBADF;
1503 return NULL;
1504 }
1505
1506 if (acl_sort(acl_d) != 0) {
1507 return -1;
1508 }
1509
1510 /*
1511 * We know we're in the same conn context. So we
1512 * can use the relative path.
1513 */
1514
1515 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1516}
1b897d50 1517#endif
1c3344a1
WD
1518
1519int sys_acl_delete_def_file(const char *path)
1520{
1521 SMB_ACL_T acl_d;
1522 int ret;
1523
1524 /*
1525 * fetching the access ACL and rewriting it has
1526 * the effect of deleting the default ACL
1527 */
1528 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1529 return -1;
1530 }
1531
1532 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1533
1534 sys_acl_free_acl(acl_d);
1535
1536 return ret;
1537}
1538
1c3344a1
WD
1539int sys_acl_free_acl(SMB_ACL_T acl_d)
1540{
1541 free(acl_d);
1542 return 0;
1543}
1544
d417c516 1545#elif defined(HAVE_IRIX_ACLS) /*---------------------------------------------*/
1c3344a1
WD
1546
1547int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1548{
1549 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1550 errno = EINVAL;
1551 return -1;
1552 }
1553
1554 if (entry_p == NULL) {
1555 errno = EINVAL;
1556 return -1;
1557 }
1558
1559 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1560 acl_d->next = 0;
1561 }
1562
1563 if (acl_d->next < 0) {
1564 errno = EINVAL;
1565 return -1;
1566 }
1567
1568 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1569 return 0;
1570 }
1571
1572 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1573
1574 return 1;
1575}
1576
1577int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1578{
1579 *type_p = entry_d->ae_tag;
1580
1581 return 0;
1582}
1583
1c3344a1
WD
1584SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1585{
1586 SMB_ACL_T a;
1587
1588 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1589 errno = ENOMEM;
1590 return NULL;
1591 }
1592 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1593 SAFE_FREE(a);
1594 return NULL;
1595 }
1596 a->next = -1;
1597 a->freeaclp = True;
1598 return a;
1599}
1600
a30dcbc0 1601#if 0
1c3344a1
WD
1602SMB_ACL_T sys_acl_get_fd(int fd)
1603{
1604 SMB_ACL_T a;
1605
1606 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1607 errno = ENOMEM;
1608 return NULL;
1609 }
1610 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1611 SAFE_FREE(a);
1612 return NULL;
1613 }
1614 a->next = -1;
1615 a->freeaclp = True;
1616 return a;
1617}
a30dcbc0 1618#endif
1c3344a1 1619
d417c516 1620int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1c3344a1 1621{
d417c516
WD
1622 *tag_type_p = entry->ae_tag;
1623
1624 *bits_p = entry->ae_perm;
1625
1626 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
1627 *u_g_id_p = entry->ae_id;
1c3344a1
WD
1628
1629 return 0;
1630}
1631
1c3344a1
WD
1632SMB_ACL_T sys_acl_init(int count)
1633{
1634 SMB_ACL_T a;
1635
1636 if (count < 0) {
1637 errno = EINVAL;
1638 return NULL;
1639 }
1640
1641 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1642 errno = ENOMEM;
1643 return NULL;
1644 }
1645
1646 a->next = -1;
1647 a->freeaclp = False;
1648 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1649 a->aclp->acl_cnt = 0;
1650
1651 return a;
1652}
1653
1654
1655int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1656{
1657 SMB_ACL_T acl_d;
1658 SMB_ACL_ENTRY_T entry_d;
1659
1660 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1661 errno = EINVAL;
1662 return -1;
1663 }
1664
1665 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1666 errno = ENOSPC;
1667 return -1;
1668 }
1669
1670 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1671 entry_d->ae_tag = 0;
1672 entry_d->ae_id = 0;
1673 entry_d->ae_perm = 0;
1674 *entry_p = entry_d;
1675
1676 return 0;
1677}
1678
d417c516 1679int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 1680{
d417c516 1681 entry->ae_tag = tag_type;
1c3344a1 1682
d417c516
WD
1683 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
1684 entry->ae_id = u_g_id;
1c3344a1 1685
d417c516 1686 entry->ae_perm = bits;
1c3344a1
WD
1687
1688 return 0;
1689}
1690
a30dcbc0 1691int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1c3344a1 1692{
a30dcbc0 1693 entry_d->ae_perm = bits;
1c3344a1
WD
1694
1695 return 0;
1696}
1697
1698int sys_acl_valid(SMB_ACL_T acl_d)
1699{
1700 return acl_valid(acl_d->aclp);
1701}
1702
1703int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1704{
1705 return acl_set_file(name, type, acl_d->aclp);
1706}
1707
d417c516 1708#if 0
1c3344a1
WD
1709int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1710{
1711 return acl_set_fd(fd, acl_d->aclp);
1712}
d417c516 1713#endif
1c3344a1
WD
1714
1715int sys_acl_delete_def_file(const char *name)
1716{
1717 return acl_delete_def_file(name);
1718}
1719
1c3344a1
WD
1720int sys_acl_free_acl(SMB_ACL_T acl_d)
1721{
1722 if (acl_d->freeaclp) {
1723 acl_free(acl_d->aclp);
1724 }
1725 acl_free(acl_d);
1726 return 0;
1727}
1728
d417c516 1729#elif defined(HAVE_AIX_ACLS) /*----------------------------------------------*/
1c3344a1
WD
1730
1731/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1732
1733int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1734{
1735 struct acl_entry_link *link;
1736 struct new_acl_entry *entry;
1737 int keep_going;
1738
87531e63
WD
1739 if (entry_id == SMB_ACL_FIRST_ENTRY)
1740 theacl->count = 0;
1741 else if (entry_id != SMB_ACL_NEXT_ENTRY) {
1742 errno = EINVAL;
1743 return -1;
1744 }
1745
1c3344a1
WD
1746 DEBUG(10,("This is the count: %d\n",theacl->count));
1747
1748 /* Check if count was previously set to -1. *
1749 * If it was, that means we reached the end *
1750 * of the acl last time. */
1751 if(theacl->count == -1)
1752 return(0);
1753
1754 link = theacl;
1755 /* To get to the next acl, traverse linked list until index *
1756 * of acl matches the count we are keeping. This count is *
1757 * incremented each time we return an acl entry. */
1758
1759 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1760 link = link->nextp;
1761
1762 entry = *entry_p = link->entryp;
1763
1764 DEBUG(10,("*entry_p is %d\n",entry_p));
1765 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1766
1767 /* Increment count */
1768 theacl->count++;
1769 if(link->nextp == NULL)
1770 theacl->count = -1;
1771
1772 return(1);
1773}
1774
1775int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1776{
1777 /* Initialize tag type */
1778
1779 *tag_type_p = -1;
1780 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1781
1782 /* Depending on what type of entry we have, *
1783 * return tag type. */
1784 switch(entry_d->ace_id->id_type) {
1785 case ACEID_USER:
1786 *tag_type_p = SMB_ACL_USER;
1787 break;
1788 case ACEID_GROUP:
1789 *tag_type_p = SMB_ACL_GROUP;
1790 break;
1791
1792 case SMB_ACL_USER_OBJ:
1793 case SMB_ACL_GROUP_OBJ:
1794 case SMB_ACL_OTHER:
1795 *tag_type_p = entry_d->ace_id->id_type;
1796 break;
d417c516 1797
1c3344a1
WD
1798 default:
1799 return(-1);
1800 }
1801
1802 return(0);
1803}
1804
1c3344a1
WD
1805SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1806{
1807 struct acl *file_acl = (struct acl *)NULL;
1808 struct acl_entry *acl_entry;
1809 struct new_acl_entry *new_acl_entry;
1810 struct ace_id *idp;
1811 struct acl_entry_link *acl_entry_link;
1812 struct acl_entry_link *acl_entry_link_head;
1813 int i;
1814 int rc = 0;
1c3344a1
WD
1815
1816 /* AIX has no DEFAULT */
1817 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1818 errno = ENOTSUP;
1819 return NULL;
1820 }
1821
1822 /* Get the acl using statacl */
1823
1824 DEBUG(10,("Entering sys_acl_get_file\n"));
1825 DEBUG(10,("path_p is %s\n",path_p));
1826
1827 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1828
1829 if(file_acl == NULL) {
1830 errno=ENOMEM;
1831 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1832 return(NULL);
1833 }
1834
1835 memset(file_acl,0,BUFSIZ);
1836
1837 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1838 if(rc == -1) {
1839 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1840 SAFE_FREE(file_acl);
1841 return(NULL);
1842 }
1843
1844 DEBUG(10,("Got facl and returned it\n"));
1845
1846 /* Point to the first acl entry in the acl */
1847 acl_entry = file_acl->acl_ext;
1848
1849 /* Begin setting up the head of the linked list *
1850 * that will be used for the storing the acl *
1851 * in a way that is useful for the posix_acls.c *
1852 * code. */
1853
1854 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1855 if(acl_entry_link_head == NULL)
1856 return(NULL);
1857
1858 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1859 if(acl_entry_link->entryp == NULL) {
1860 SAFE_FREE(file_acl);
1861 errno = ENOMEM;
1862 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1863 return(NULL);
1864 }
1865
1866 DEBUG(10,("acl_entry is %d\n",acl_entry));
1867 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1868
1869 /* Check if the extended acl bit is on. *
1870 * If it isn't, do not show the *
1871 * contents of the acl since AIX intends *
1872 * the extended info to remain unused */
1873
1874 if(file_acl->acl_mode & S_IXACL){
1875 /* while we are not pointing to the very end */
1876 while(acl_entry < acl_last(file_acl)) {
1877 /* before we malloc anything, make sure this is */
1878 /* a valid acl entry and one that we want to map */
1879 idp = id_nxt(acl_entry->ace_id);
1880 if((acl_entry->ace_type == ACC_SPECIFY ||
1881 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1882 acl_entry = acl_nxt(acl_entry);
1883 continue;
1884 }
1885
1886 idp = acl_entry->ace_id;
1887
1888 /* Check if this is the first entry in the linked list. *
1889 * The first entry needs to keep prevp pointing to NULL *
1890 * and already has entryp allocated. */
1891
1892 if(acl_entry_link_head->count != 0) {
1893 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1894
1895 if(acl_entry_link->nextp == NULL) {
1896 SAFE_FREE(file_acl);
1897 errno = ENOMEM;
1898 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1899 return(NULL);
1900 }
1901
1902 acl_entry_link->nextp->prevp = acl_entry_link;
1903 acl_entry_link = acl_entry_link->nextp;
1904 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1905 if(acl_entry_link->entryp == NULL) {
1906 SAFE_FREE(file_acl);
1907 errno = ENOMEM;
1908 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1909 return(NULL);
1910 }
1911 acl_entry_link->nextp = NULL;
1912 }
1913
1914 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1915
1916 /* Don't really need this since all types are going *
1917 * to be specified but, it's better than leaving it 0 */
1918
1919 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1920
1921 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1922
1923 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1924
1925 /* The access in the acl entries must be left shifted by *
1926 * three bites, because they will ultimately be compared *
1927 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1928
1929 switch(acl_entry->ace_type){
1930 case ACC_PERMIT:
1931 case ACC_SPECIFY:
1932 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1933 acl_entry_link->entryp->ace_access <<= 6;
1934 acl_entry_link_head->count++;
1935 break;
1936 case ACC_DENY:
1937 /* Since there is no way to return a DENY acl entry *
1938 * change to PERMIT and then shift. */
1939 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1940 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1941 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1942 acl_entry_link->entryp->ace_access <<= 6;
1943 acl_entry_link_head->count++;
1944 break;
1945 default:
1946 return(0);
1947 }
1948
1949 DEBUG(10,("acl_entry = %d\n",acl_entry));
1950 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1951
1952 acl_entry = acl_nxt(acl_entry);
1953 }
1954 } /* end of if enabled */
1955
1956 /* Since owner, group, other acl entries are not *
1957 * part of the acl entries in an acl, they must *
1958 * be dummied up to become part of the list. */
1959
1960 for( i = 1; i < 4; i++) {
1961 DEBUG(10,("i is %d\n",i));
1962 if(acl_entry_link_head->count != 0) {
1963 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1964 if(acl_entry_link->nextp == NULL) {
1965 SAFE_FREE(file_acl);
1966 errno = ENOMEM;
1967 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1968 return(NULL);
1969 }
1970
1971 acl_entry_link->nextp->prevp = acl_entry_link;
1972 acl_entry_link = acl_entry_link->nextp;
1973 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1974 if(acl_entry_link->entryp == NULL) {
1975 SAFE_FREE(file_acl);
1976 errno = ENOMEM;
1977 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1978 return(NULL);
1979 }
1980 }
1981
1982 acl_entry_link->nextp = NULL;
1983
1984 new_acl_entry = acl_entry_link->entryp;
1985 idp = new_acl_entry->ace_id;
1986
1987 new_acl_entry->ace_len = sizeof(struct acl_entry);
1988 new_acl_entry->ace_type = ACC_PERMIT;
1989 idp->id_len = sizeof(struct ace_id);
1990 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1991 memset(idp->id_data,0,sizeof(uid_t));
1992
1993 switch(i) {
1994 case 2:
1995 new_acl_entry->ace_access = file_acl->g_access << 6;
1996 idp->id_type = SMB_ACL_GROUP_OBJ;
1997 break;
1998
1999 case 3:
2000 new_acl_entry->ace_access = file_acl->o_access << 6;
2001 idp->id_type = SMB_ACL_OTHER;
2002 break;
2003
2004 case 1:
2005 new_acl_entry->ace_access = file_acl->u_access << 6;
2006 idp->id_type = SMB_ACL_USER_OBJ;
2007 break;
2008
2009 default:
2010 return(NULL);
2011
2012 }
2013
2014 acl_entry_link_head->count++;
2015 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2016 }
2017
2018 acl_entry_link_head->count = 0;
2019 SAFE_FREE(file_acl);
2020
2021 return(acl_entry_link_head);
2022}
2023
a30dcbc0 2024#if 0
1c3344a1
WD
2025SMB_ACL_T sys_acl_get_fd(int fd)
2026{
2027 struct acl *file_acl = (struct acl *)NULL;
2028 struct acl_entry *acl_entry;
2029 struct new_acl_entry *new_acl_entry;
2030 struct ace_id *idp;
2031 struct acl_entry_link *acl_entry_link;
2032 struct acl_entry_link *acl_entry_link_head;
2033 int i;
2034 int rc = 0;
1c3344a1
WD
2035
2036 /* Get the acl using fstatacl */
2037
2038 DEBUG(10,("Entering sys_acl_get_fd\n"));
2039 DEBUG(10,("fd is %d\n",fd));
2040 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2041
2042 if(file_acl == NULL) {
2043 errno=ENOMEM;
2044 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2045 return(NULL);
2046 }
2047
2048 memset(file_acl,0,BUFSIZ);
2049
2050 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2051 if(rc == -1) {
2052 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2053 SAFE_FREE(file_acl);
2054 return(NULL);
2055 }
2056
2057 DEBUG(10,("Got facl and returned it\n"));
2058
2059 /* Point to the first acl entry in the acl */
2060
2061 acl_entry = file_acl->acl_ext;
2062 /* Begin setting up the head of the linked list *
2063 * that will be used for the storing the acl *
2064 * in a way that is useful for the posix_acls.c *
2065 * code. */
2066
2067 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2068 if(acl_entry_link_head == NULL){
2069 SAFE_FREE(file_acl);
2070 return(NULL);
2071 }
2072
2073 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2074
2075 if(acl_entry_link->entryp == NULL) {
2076 errno = ENOMEM;
2077 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2078 SAFE_FREE(file_acl);
2079 return(NULL);
2080 }
2081
2082 DEBUG(10,("acl_entry is %d\n",acl_entry));
2083 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2084
2085 /* Check if the extended acl bit is on. *
2086 * If it isn't, do not show the *
2087 * contents of the acl since AIX intends *
2088 * the extended info to remain unused */
2089
2090 if(file_acl->acl_mode & S_IXACL){
2091 /* while we are not pointing to the very end */
2092 while(acl_entry < acl_last(file_acl)) {
2093 /* before we malloc anything, make sure this is */
2094 /* a valid acl entry and one that we want to map */
2095
2096 idp = id_nxt(acl_entry->ace_id);
2097 if((acl_entry->ace_type == ACC_SPECIFY ||
2098 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2099 acl_entry = acl_nxt(acl_entry);
2100 continue;
2101 }
2102
2103 idp = acl_entry->ace_id;
2104
2105 /* Check if this is the first entry in the linked list. *
2106 * The first entry needs to keep prevp pointing to NULL *
2107 * and already has entryp allocated. */
2108
2109 if(acl_entry_link_head->count != 0) {
2110 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2111 if(acl_entry_link->nextp == NULL) {
2112 errno = ENOMEM;
2113 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2114 SAFE_FREE(file_acl);
2115 return(NULL);
2116 }
2117 acl_entry_link->nextp->prevp = acl_entry_link;
2118 acl_entry_link = acl_entry_link->nextp;
2119 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2120 if(acl_entry_link->entryp == NULL) {
2121 errno = ENOMEM;
2122 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2123 SAFE_FREE(file_acl);
2124 return(NULL);
2125 }
2126
2127 acl_entry_link->nextp = NULL;
2128 }
2129
2130 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2131
2132 /* Don't really need this since all types are going *
2133 * to be specified but, it's better than leaving it 0 */
2134
2135 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2136 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2137
2138 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2139
2140 /* The access in the acl entries must be left shifted by *
2141 * three bites, because they will ultimately be compared *
2142 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2143
2144 switch(acl_entry->ace_type){
2145 case ACC_PERMIT:
2146 case ACC_SPECIFY:
2147 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2148 acl_entry_link->entryp->ace_access <<= 6;
2149 acl_entry_link_head->count++;
2150 break;
2151 case ACC_DENY:
2152 /* Since there is no way to return a DENY acl entry *
2153 * change to PERMIT and then shift. */
2154 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2155 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2156 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2157 acl_entry_link->entryp->ace_access <<= 6;
2158 acl_entry_link_head->count++;
2159 break;
2160 default:
2161 return(0);
2162 }
2163
2164 DEBUG(10,("acl_entry = %d\n",acl_entry));
2165 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2166
2167 acl_entry = acl_nxt(acl_entry);
2168 }
2169 } /* end of if enabled */
2170
2171 /* Since owner, group, other acl entries are not *
2172 * part of the acl entries in an acl, they must *
2173 * be dummied up to become part of the list. */
2174
2175 for( i = 1; i < 4; i++) {
2176 DEBUG(10,("i is %d\n",i));
2177 if(acl_entry_link_head->count != 0){
2178 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2179 if(acl_entry_link->nextp == NULL) {
2180 errno = ENOMEM;
2181 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2182 SAFE_FREE(file_acl);
2183 return(NULL);
2184 }
2185
2186 acl_entry_link->nextp->prevp = acl_entry_link;
2187 acl_entry_link = acl_entry_link->nextp;
2188 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2189
2190 if(acl_entry_link->entryp == NULL) {
2191 SAFE_FREE(file_acl);
2192 errno = ENOMEM;
2193 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2194 return(NULL);
2195 }
2196 }
2197
2198 acl_entry_link->nextp = NULL;
2199
2200 new_acl_entry = acl_entry_link->entryp;
2201 idp = new_acl_entry->ace_id;
2202
2203 new_acl_entry->ace_len = sizeof(struct acl_entry);
2204 new_acl_entry->ace_type = ACC_PERMIT;
2205 idp->id_len = sizeof(struct ace_id);
2206 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2207 memset(idp->id_data,0,sizeof(uid_t));
2208
2209 switch(i) {
2210 case 2:
2211 new_acl_entry->ace_access = file_acl->g_access << 6;
2212 idp->id_type = SMB_ACL_GROUP_OBJ;
2213 break;
2214
2215 case 3:
2216 new_acl_entry->ace_access = file_acl->o_access << 6;
2217 idp->id_type = SMB_ACL_OTHER;
2218 break;
2219
2220 case 1:
2221 new_acl_entry->ace_access = file_acl->u_access << 6;
2222 idp->id_type = SMB_ACL_USER_OBJ;
2223 break;
2224
2225 default:
2226 return(NULL);
2227 }
2228
2229 acl_entry_link_head->count++;
2230 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2231 }
2232
2233 acl_entry_link_head->count = 0;
2234 SAFE_FREE(file_acl);
2235
2236 return(acl_entry_link_head);
2237}
a30dcbc0 2238#endif
1c3344a1 2239
d417c516
WD
2240int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
2241{
2242 uint *permset;
2243
2244 if (sys_acl_get_tag_type(entry, tag_type_p) != 0)
2245 return -1;
2246
2247 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
14dfad38 2248 memcpy(u_g_id_p, entry->ace_id->id_data, sizeof (id_t));
d417c516
WD
2249
2250 permset = &entry->ace_access;
2251
2252 DEBUG(10,("*permset is %d\n",*permset));
2253 *bits_p = (*permset & S_IRUSR ? 4 : 0)
2254 | (*permset & S_IWUSR ? 2 : 0)
2255 | (*permset & S_IXUSR ? 1 : 0);
2256
2257 return 0;
2258}
2259
1c3344a1
WD
2260SMB_ACL_T sys_acl_init( int count)
2261{
2262 struct acl_entry_link *theacl = NULL;
2263
87531e63
WD
2264 if (count < 0) {
2265 errno = EINVAL;
2266 return NULL;
2267 }
2268
1c3344a1
WD
2269 DEBUG(10,("Entering sys_acl_init\n"));
2270
2271 theacl = SMB_MALLOC_P(struct acl_entry_link);
2272 if(theacl == NULL) {
2273 errno = ENOMEM;
2274 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2275 return(NULL);
2276 }
2277
2278 theacl->count = 0;
2279 theacl->nextp = NULL;
2280 theacl->prevp = NULL;
2281 theacl->entryp = NULL;
2282 DEBUG(10,("Exiting sys_acl_init\n"));
2283 return(theacl);
2284}
2285
2286int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2287{
2288 struct acl_entry_link *theacl;
2289 struct acl_entry_link *acl_entryp;
2290 struct acl_entry_link *temp_entry;
2291 int counting;
2292
2293 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2294
2295 theacl = acl_entryp = *pacl;
2296
2297 /* Get to the end of the acl before adding entry */
2298
2299 for(counting=0; counting < theacl->count; counting++){
2300 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2301 temp_entry = acl_entryp;
2302 acl_entryp = acl_entryp->nextp;
2303 }
2304
2305 if(theacl->count != 0){
2306 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2307 if(acl_entryp == NULL) {
2308 errno = ENOMEM;
2309 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2310 return(-1);
2311 }
2312
2313 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2314 acl_entryp->prevp = temp_entry;
2315 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2316 }
2317
2318 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2319 if(*pentry == NULL) {
2320 errno = ENOMEM;
2321 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2322 return(-1);
2323 }
2324
2325 memset(*pentry,0,sizeof(struct new_acl_entry));
2326 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2327 acl_entryp->entryp->ace_type = ACC_PERMIT;
2328 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2329 acl_entryp->nextp = NULL;
2330 theacl->count++;
2331 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2332 return(0);
2333}
2334
d417c516 2335int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1c3344a1 2336{
d417c516 2337 entry->ace_id->id_type = tag_type;
1c3344a1 2338 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1c3344a1 2339
d417c516
WD
2340 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
2341 memcpy(entry->ace_id->id_data, &u_g_id, sizeof (id_t));
2342
2343 entry->ace_access = bits;
2344 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2345
2346 return 0;
1c3344a1
WD
2347}
2348
a30dcbc0 2349int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
1c3344a1
WD
2350{
2351 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
a30dcbc0 2352 entry->ace_access = bits;
1c3344a1
WD
2353 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2354 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2355 return(0);
2356}
2357
2358int sys_acl_valid( SMB_ACL_T theacl )
2359{
2360 int user_obj = 0;
2361 int group_obj = 0;
2362 int other_obj = 0;
2363 struct acl_entry_link *acl_entry;
2364
2365 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2366 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2367 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2368 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2369 }
2370
2371 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2372
2373 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2374 return(-1);
2375
2376 return(0);
2377}
2378
2379int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2380{
2381 struct acl_entry_link *acl_entry_link = NULL;
2382 struct acl *file_acl = NULL;
2383 struct acl *file_acl_temp = NULL;
2384 struct acl_entry *acl_entry = NULL;
2385 struct ace_id *ace_id = NULL;
2386 uint id_type;
1c3344a1
WD
2387 uint user_id;
2388 uint acl_length;
2389 uint rc;
2390
2391 DEBUG(10,("Entering sys_acl_set_file\n"));
2392 DEBUG(10,("File name is %s\n",name));
2393
2394 /* AIX has no default ACL */
2395 if(acltype == SMB_ACL_TYPE_DEFAULT)
2396 return(0);
2397
2398 acl_length = BUFSIZ;
2399 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2400
2401 if(file_acl == NULL) {
2402 errno = ENOMEM;
2403 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2404 return(-1);
2405 }
2406
2407 memset(file_acl,0,BUFSIZ);
2408
2409 file_acl->acl_len = ACL_SIZ;
2410 file_acl->acl_mode = S_IXACL;
2411
2412 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2413 acl_entry_link->entryp->ace_access >>= 6;
2414 id_type = acl_entry_link->entryp->ace_id->id_type;
2415
2416 switch(id_type) {
2417 case SMB_ACL_USER_OBJ:
2418 file_acl->u_access = acl_entry_link->entryp->ace_access;
2419 continue;
2420 case SMB_ACL_GROUP_OBJ:
2421 file_acl->g_access = acl_entry_link->entryp->ace_access;
2422 continue;
2423 case SMB_ACL_OTHER:
2424 file_acl->o_access = acl_entry_link->entryp->ace_access;
2425 continue;
2426 case SMB_ACL_MASK:
2427 continue;
2428 }
2429
2430 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2431 acl_length += sizeof(struct acl_entry);
2432 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2433 if(file_acl_temp == NULL) {
2434 SAFE_FREE(file_acl);
2435 errno = ENOMEM;
2436 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2437 return(-1);
2438 }
2439
2440 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2441 SAFE_FREE(file_acl);
2442 file_acl = file_acl_temp;
2443 }
2444
2445 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2446 file_acl->acl_len += sizeof(struct acl_entry);
2447 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2448 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2449
2450 /* In order to use this, we'll need to wait until we can get denies */
2451 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2452 acl_entry->ace_type = ACC_SPECIFY; */
2453
2454 acl_entry->ace_type = ACC_SPECIFY;
2455
2456 ace_id = acl_entry->ace_id;
2457
2458 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2459 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2460 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2461 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2462 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2463 }
2464
14dfad38 2465 rc = chacl((char*)name,file_acl,file_acl->acl_len);
1c3344a1
WD
2466 DEBUG(10,("errno is %d\n",errno));
2467 DEBUG(10,("return code is %d\n",rc));
2468 SAFE_FREE(file_acl);
2469 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2470 return(rc);
2471}
2472
d417c516 2473#if 0
1c3344a1
WD
2474int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2475{
2476 struct acl_entry_link *acl_entry_link = NULL;
2477 struct acl *file_acl = NULL;
2478 struct acl *file_acl_temp = NULL;
2479 struct acl_entry *acl_entry = NULL;
2480 struct ace_id *ace_id = NULL;
2481 uint id_type;
2482 uint user_id;
2483 uint acl_length;
2484 uint rc;
2485
2486 DEBUG(10,("Entering sys_acl_set_fd\n"));
2487 acl_length = BUFSIZ;
2488 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2489
2490 if(file_acl == NULL) {
2491 errno = ENOMEM;
2492 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2493 return(-1);
2494 }
2495
2496 memset(file_acl,0,BUFSIZ);
2497
2498 file_acl->acl_len = ACL_SIZ;
2499 file_acl->acl_mode = S_IXACL;
2500
2501 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2502 acl_entry_link->entryp->ace_access >>= 6;
2503 id_type = acl_entry_link->entryp->ace_id->id_type;
2504 DEBUG(10,("The id_type is %d\n",id_type));
2505
2506 switch(id_type) {
2507 case SMB_ACL_USER_OBJ:
2508 file_acl->u_access = acl_entry_link->entryp->ace_access;
2509 continue;
2510 case SMB_ACL_GROUP_OBJ:
2511 file_acl->g_access = acl_entry_link->entryp->ace_access;
2512 continue;
2513 case SMB_ACL_OTHER:
2514 file_acl->o_access = acl_entry_link->entryp->ace_access;
2515 continue;
2516 case SMB_ACL_MASK:
2517 continue;
2518 }
2519
2520 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2521 acl_length += sizeof(struct acl_entry);
2522 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2523 if(file_acl_temp == NULL) {
2524 SAFE_FREE(file_acl);
2525 errno = ENOMEM;
2526 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2527 return(-1);
2528 }
2529
2530 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2531 SAFE_FREE(file_acl);
2532 file_acl = file_acl_temp;
2533 }
2534
2535 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2536 file_acl->acl_len += sizeof(struct acl_entry);
2537 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2538 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2539
2540 /* In order to use this, we'll need to wait until we can get denies */
2541 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2542 acl_entry->ace_type = ACC_SPECIFY; */
2543
2544 acl_entry->ace_type = ACC_SPECIFY;
2545
2546 ace_id = acl_entry->ace_id;
2547
2548 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2549 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2550 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2551 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2552 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2553 }
2554
2555 rc = fchacl(fd,file_acl,file_acl->acl_len);
2556 DEBUG(10,("errno is %d\n",errno));
2557 DEBUG(10,("return code is %d\n",rc));
2558 SAFE_FREE(file_acl);
2559 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2560 return(rc);
2561}
d417c516 2562#endif
1c3344a1 2563
87531e63 2564int sys_acl_delete_def_file(UNUSED(const char *name))
1c3344a1
WD
2565{
2566 /* AIX has no default ACL */
2567 return 0;
2568}
2569
1c3344a1
WD
2570int sys_acl_free_acl(SMB_ACL_T posix_acl)
2571{
2572 struct acl_entry_link *acl_entry_link;
2573
2574 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2575 SAFE_FREE(acl_entry_link->prevp->entryp);
2576 SAFE_FREE(acl_entry_link->prevp);
2577 }
2578
2579 SAFE_FREE(acl_entry_link->prevp->entryp);
2580 SAFE_FREE(acl_entry_link->prevp);
2581 SAFE_FREE(acl_entry_link->entryp);
2582 SAFE_FREE(acl_entry_link);
2583
2584 return(0);
2585}
2586
d417c516
WD
2587#elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
2588
2589#define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
2590
2591#include <membership.h>
2592
2593int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1c3344a1 2594{
d417c516
WD
2595 int ret = acl_get_entry(the_acl, entry_id, entry_p);
2596#ifdef OSX_BROKEN_GETENTRY
2597 if (ret == 0)
2598 ret = 1;
2599 else if (ret == -1 && errno == 22)
2600 ret = 0;
2601#endif
2602 return ret;
2603}
2604
2605SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
2606{
2607 if (type == ACL_TYPE_DEFAULT) {
2608 errno = ENOTSUP;
2609 return NULL;
2610 }
2611 errno = 0;
2612 return acl_get_file(path_p, type);
2613}
2614
2615#if 0
2616SMB_ACL_T sys_acl_get_fd(int fd)
2617{
2618 return acl_get_fd(fd);
2619}
2620#endif
2621
2622int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
2623{
2624 uuid_t *uup;
2625 acl_tag_t tag;
2626 acl_flagset_t flagset;
2627 acl_permset_t permset;
2628 uint32 bits, fb, bb, pb;
5ebb7935 2629 int id_type = -1;
d417c516
WD
2630 int rc;
2631
2632 if (acl_get_tag_type(entry, &tag) != 0
2633 || acl_get_flagset_np(entry, &flagset) != 0
2634 || acl_get_permset(entry, &permset) != 0
2635 || (uup = acl_get_qualifier(entry)) == NULL)
2636 return -1;
2637
5ebb7935 2638 rc = mbr_uuid_to_id(*uup, u_g_id_p, &id_type);
d417c516
WD
2639 acl_free(uup);
2640 if (rc != 0)
2641 return rc;
2642
5ebb7935 2643 if (id_type == ID_TYPE_UID)
d417c516
WD
2644 *tag_type_p = SMB_ACL_USER;
2645 else
2646 *tag_type_p = SMB_ACL_GROUP;
2647
2648 bits = tag == ACL_EXTENDED_ALLOW ? 1 : 0;
2649
2650 for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
2651 if (acl_get_flag_np(flagset, fb) == 1)
2652 bits |= bb;
2653 }
2654
2655 for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
2656 if (acl_get_perm_np(permset, pb) == 1)
2657 bits |= bb;
2658 }
2659
2660 *bits_p = bits;
2661
2662 return 0;
2663}
2664
2665SMB_ACL_T sys_acl_init(int count)
2666{
2667 return acl_init(count);
2668}
2669
2670int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2671{
2672 return acl_create_entry(pacl, pentry);
2673}
2674
2675int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
2676{
2677 acl_flagset_t flagset;
2678 acl_permset_t permset;
2679 uint32 fb, bb, pb;
2680 int is_user = tag_type == SMB_ACL_USER;
2681 uuid_t uu;
2682 int rc;
2683
2684 tag_type = bits & 1 ? ACL_EXTENDED_ALLOW : ACL_EXTENDED_DENY;
2685
2686 if (acl_get_flagset_np(entry, &flagset) != 0
2687 || acl_get_permset(entry, &permset) != 0)
2688 return -1;
2689
2690 acl_clear_flags_np(flagset);
2691 acl_clear_perms(permset);
2692
2693 for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
2694 if (bits & bb)
2695 acl_add_flag_np(flagset, fb);
2696 }
2697
d417c516
WD
2698 for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
2699 if (bits & bb)
2700 acl_add_perm(permset, pb);
2701 }
2702
2703 if (is_user)
2704 rc = mbr_uid_to_uuid(u_g_id, uu);
2705 else
2706 rc = mbr_gid_to_uuid(u_g_id, uu);
85b057cc
WD
2707 if (rc != 0)
2708 return rc;
d417c516
WD
2709
2710 if (acl_set_tag_type(entry, tag_type) != 0
2711 || acl_set_qualifier(entry, &uu) != 0
2712 || acl_set_permset(entry, permset) != 0
2713 || acl_set_flagset_np(entry, flagset) != 0)
2714 return -1;
2715
2716 return 0;
2717}
2718
2719#if 0
2720int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2721{
2722 return -1; /* Not needed for OS X. */
2723}
2724#endif
2725
2726int sys_acl_valid(SMB_ACL_T theacl)
2727{
2728 return acl_valid(theacl);
2729}
2730
2731int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2732{
2733 return acl_set_file(name, acltype, theacl);
2734}
2735
2736#if 0
2737int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
2738{
2739 return acl_set_fd(fd, theacl);
2740}
2741#endif
2742
2743int sys_acl_delete_def_file(const char *name)
2744{
2745 return acl_delete_def_file(name);
2746}
2747
2748int sys_acl_free_acl(SMB_ACL_T the_acl)
2749{
2750 return acl_free(the_acl);
1c3344a1
WD
2751}
2752
2753#else /* No ACLs. */
2754
a30dcbc0 2755#error No ACL functions defined for this platform!
1c3344a1 2756
a30dcbc0 2757#endif
1c3344a1
WD
2758
2759/************************************************************************
2760 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2761 errno, 0 if not.
2762************************************************************************/
2763
2764int no_acl_syscall_error(int err)
2765{
d417c516
WD
2766#ifdef HAVE_OSX_ACLS
2767 if (err == ENOENT)
2768 return 1; /* Weird problem with directory ACLs. */
2769#endif
1c3344a1
WD
2770#if defined(ENOSYS)
2771 if (err == ENOSYS) {
2772 return 1;
2773 }
2774#endif
2775#if defined(ENOTSUP)
2776 if (err == ENOTSUP) {
2777 return 1;
2778 }
2779#endif
2780 return 0;
2781}
2782
2783#endif /* SUPPORT_ACLS */