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