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