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