Changed SUBPROTOCOL_VERSION from 2 to 3 because of the ACL protocol changes.
[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
1b897d50 1209#if 0
1c3344a1
WD
1210SMB_ACL_T sys_acl_get_fd(int fd)
1211{
1212 /*
1213 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1214 */
1215
1216 files_struct *fsp = file_find_fd(fd);
1217
1218 if (fsp == NULL) {
1219 errno = EBADF;
1220 return NULL;
1221 }
1222
1223 /*
1224 * We know we're in the same conn context. So we
1225 * can use the relative path.
1226 */
1227
1228 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1229}
1b897d50 1230#endif
1c3344a1
WD
1231
1232int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1233{
1234 *permset_d = 0;
1235
1236 return 0;
1237}
1238
1239int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1240{
1241 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1242 && perm != SMB_ACL_EXECUTE) {
1243 errno = EINVAL;
1244 return -1;
1245 }
1246
1247 if (permset_d == NULL) {
1248 errno = EINVAL;
1249 return -1;
1250 }
1251
1252 *permset_d |= perm;
1253
1254 return 0;
1255}
1256
1257int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1258{
1259 return *permset_d & perm;
1260}
1261
1262char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1263{
1264 int i;
1265 int len, maxlen;
1266 char *text;
1267
1268 /*
1269 * use an initial estimate of 20 bytes per ACL entry
1270 * when allocating memory for the text representation
1271 * of the ACL
1272 */
1273 len = 0;
1274 maxlen = 20 * acl_d->count;
1275 if ((text = SMB_MALLOC(maxlen)) == NULL) {
1276 errno = ENOMEM;
1277 return NULL;
1278 }
1279
1280 for (i = 0; i < acl_d->count; i++) {
1281 struct acl *ap = &acl_d->acl[i];
1282 struct group *gr;
1283 char tagbuf[12];
1284 char idbuf[12];
1285 char *tag;
1286 char *id = "";
1287 char perms[4];
1288 int nbytes;
1289
1290 switch (ap->a_type) {
1291 /*
1292 * for debugging purposes it's probably more
1293 * useful to dump unknown tag types rather
1294 * than just returning an error
1295 */
1296 default:
1297 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1298 ap->a_type);
1299 tag = tagbuf;
1300 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1301 (long)ap->a_id);
1302 id = idbuf;
1303 break;
1304
1305 case SMB_ACL_USER:
1306 id = uidtoname(ap->a_id);
1307 case SMB_ACL_USER_OBJ:
1308 tag = "user";
1309 break;
1310
1311 case SMB_ACL_GROUP:
1312 if ((gr = getgrgid(ap->a_id)) == NULL) {
1313 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1314 (long)ap->a_id);
1315 id = idbuf;
1316 } else {
1317 id = gr->gr_name;
1318 }
1319 case SMB_ACL_GROUP_OBJ:
1320 tag = "group";
1321 break;
1322
1323 case SMB_ACL_OTHER:
1324 tag = "other";
1325 break;
1326
1327 case SMB_ACL_MASK:
1328 tag = "mask";
1329 break;
1330
1331 }
1332
1333 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1334 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1335 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1336 perms[3] = '\0';
1337
1338 /* <tag> : <qualifier> : rwx \n \0 */
1339 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1340
1341 /*
1342 * If this entry would overflow the buffer
1343 * allocate enough additional memory for this
1344 * entry and an estimate of another 20 bytes
1345 * for each entry still to be processed
1346 */
1347 if ((len + nbytes) > maxlen) {
1348 char *oldtext = text;
1349
1350 maxlen += nbytes + 20 * (acl_d->count - i);
1351
1352 if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
1353 free(oldtext);
1354 errno = ENOMEM;
1355 return NULL;
1356 }
1357 }
1358
1359 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1360 len += nbytes - 1;
1361 }
1362
1363 if (len_p)
1364 *len_p = len;
1365
1366 return text;
1367}
1368
1369SMB_ACL_T sys_acl_init(int count)
1370{
1371 SMB_ACL_T a;
1372
1373 if (count < 0) {
1374 errno = EINVAL;
1375 return NULL;
1376 }
1377
1378 /*
1379 * note that since the definition of the structure pointed
1380 * to by the SMB_ACL_T includes the first element of the
1381 * acl[] array, this actually allocates an ACL with room
1382 * for (count+1) entries
1383 */
1384 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1385 errno = ENOMEM;
1386 return NULL;
1387 }
1388
1389 a->size = count + 1;
1390 a->count = 0;
1391 a->next = -1;
1392
1393 return a;
1394}
1395
1396
1397int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1398{
1399 SMB_ACL_T acl_d;
1400 SMB_ACL_ENTRY_T entry_d;
1401
1402 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1403 errno = EINVAL;
1404 return -1;
1405 }
1406
1407 if (acl_d->count >= acl_d->size) {
1408 errno = ENOSPC;
1409 return -1;
1410 }
1411
1412 entry_d = &acl_d->acl[acl_d->count++];
1413 entry_d->a_type = 0;
1414 entry_d->a_id = -1;
1415 entry_d->a_perm = 0;
1416 *entry_p = entry_d;
1417
1418 return 0;
1419}
1420
1421int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1422{
1423 switch (tag_type) {
1424 case SMB_ACL_USER:
1425 case SMB_ACL_USER_OBJ:
1426 case SMB_ACL_GROUP:
1427 case SMB_ACL_GROUP_OBJ:
1428 case SMB_ACL_OTHER:
1429 case SMB_ACL_MASK:
1430 entry_d->a_type = tag_type;
1431 break;
1432 default:
1433 errno = EINVAL;
1434 return -1;
1435 }
1436
1437 return 0;
1438}
1439
1440int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1441{
1442 if (entry_d->a_type != SMB_ACL_GROUP
1443 && entry_d->a_type != SMB_ACL_USER) {
1444 errno = EINVAL;
1445 return -1;
1446 }
1447
1448 entry_d->a_id = *((id_t *)qual_p);
1449
1450 return 0;
1451}
1452
1453int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1454{
1455 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1456 return EINVAL;
1457 }
1458
1459 entry_d->a_perm = *permset_d;
1460
1461 return 0;
1462}
1463
1464/* Structure to capture the count for each type of ACE. */
1465
1466struct hpux_acl_types {
1467 int n_user;
1468 int n_def_user;
1469 int n_user_obj;
1470 int n_def_user_obj;
1471
1472 int n_group;
1473 int n_def_group;
1474 int n_group_obj;
1475 int n_def_group_obj;
1476
1477 int n_other;
1478 int n_other_obj;
1479 int n_def_other_obj;
1480
1481 int n_class_obj;
1482 int n_def_class_obj;
1483
1484 int n_illegal_obj;
1485};
1486
1487/* count_obj:
1488 * Counts the different number of objects in a given array of ACL
1489 * structures.
1490 * Inputs:
1491 *
1492 * acl_count - Count of ACLs in the array of ACL strucutres.
1493 * aclp - Array of ACL structures.
1494 * acl_type_count - Pointer to acl_types structure. Should already be
1495 * allocated.
1496 * Output:
1497 *
1498 * acl_type_count - This structure is filled up with counts of various
1499 * acl types.
1500 */
1501
1502static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1503{
1504 int i;
1505
1506 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1507
1508 for(i=0;i<acl_count;i++) {
1509 switch(aclp[i].a_type) {
1510 case USER:
1511 acl_type_count->n_user++;
1512 break;
1513 case USER_OBJ:
1514 acl_type_count->n_user_obj++;
1515 break;
1516 case DEF_USER_OBJ:
1517 acl_type_count->n_def_user_obj++;
1518 break;
1519 case GROUP:
1520 acl_type_count->n_group++;
1521 break;
1522 case GROUP_OBJ:
1523 acl_type_count->n_group_obj++;
1524 break;
1525 case DEF_GROUP_OBJ:
1526 acl_type_count->n_def_group_obj++;
1527 break;
1528 case OTHER_OBJ:
1529 acl_type_count->n_other_obj++;
1530 break;
1531 case DEF_OTHER_OBJ:
1532 acl_type_count->n_def_other_obj++;
1533 break;
1534 case CLASS_OBJ:
1535 acl_type_count->n_class_obj++;
1536 break;
1537 case DEF_CLASS_OBJ:
1538 acl_type_count->n_def_class_obj++;
1539 break;
1540 case DEF_USER:
1541 acl_type_count->n_def_user++;
1542 break;
1543 case DEF_GROUP:
1544 acl_type_count->n_def_group++;
1545 break;
1546 default:
1547 acl_type_count->n_illegal_obj++;
1548 break;
1549 }
1550 }
1551}
1552
1553/* swap_acl_entries: Swaps two ACL entries.
1554 *
1555 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1556 */
1557
1558static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1559{
1560 struct acl temp_acl;
1561
1562 temp_acl.a_type = aclp0->a_type;
1563 temp_acl.a_id = aclp0->a_id;
1564 temp_acl.a_perm = aclp0->a_perm;
1565
1566 aclp0->a_type = aclp1->a_type;
1567 aclp0->a_id = aclp1->a_id;
1568 aclp0->a_perm = aclp1->a_perm;
1569
1570 aclp1->a_type = temp_acl.a_type;
1571 aclp1->a_id = temp_acl.a_id;
1572 aclp1->a_perm = temp_acl.a_perm;
1573}
1574
1575/* prohibited_duplicate_type
1576 * Identifies if given ACL type can have duplicate entries or
1577 * not.
1578 *
1579 * Inputs: acl_type - ACL Type.
1580 *
1581 * Outputs:
1582 *
1583 * Return..
1584 *
1585 * True - If the ACL type matches any of the prohibited types.
1586 * False - If the ACL type doesn't match any of the prohibited types.
1587 */
1588
1589static BOOL hpux_prohibited_duplicate_type(int acl_type)
1590{
1591 switch(acl_type) {
1592 case USER:
1593 case GROUP:
1594 case DEF_USER:
1595 case DEF_GROUP:
1596 return True;
1597 default:
1598 return False;
1599 }
1600}
1601
1602/* get_needed_class_perm
1603 * Returns the permissions of a ACL structure only if the ACL
1604 * type matches one of the pre-determined types for computing
1605 * CLASS_OBJ permissions.
1606 *
1607 * Inputs: aclp - Pointer to ACL structure.
1608 */
1609
1610static int hpux_get_needed_class_perm(struct acl *aclp)
1611{
1612 switch(aclp->a_type) {
1613 case USER:
1614 case GROUP_OBJ:
1615 case GROUP:
1616 case DEF_USER_OBJ:
1617 case DEF_USER:
1618 case DEF_GROUP_OBJ:
1619 case DEF_GROUP:
1620 case DEF_CLASS_OBJ:
1621 case DEF_OTHER_OBJ:
1622 return aclp->a_perm;
1623 default:
1624 return 0;
1625 }
1626}
1627
1628/* acl_sort for HPUX.
1629 * Sorts the array of ACL structures as per the description in
1630 * aclsort man page. Refer to aclsort man page for more details
1631 *
1632 * Inputs:
1633 *
1634 * acl_count - Count of ACLs in the array of ACL structures.
1635 * calclass - If this is not zero, then we compute the CLASS_OBJ
1636 * permissions.
1637 * aclp - Array of ACL structures.
1638 *
1639 * Outputs:
1640 *
1641 * aclp - Sorted array of ACL structures.
1642 *
1643 * Outputs:
1644 *
1645 * Returns 0 for success -1 for failure. Prints a message to the Samba
1646 * debug log in case of failure.
1647 */
1648
1649static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1650{
1651#if !defined(HAVE_HPUX_ACLSORT)
1652 /*
1653 * The aclsort() system call is availabe on the latest HPUX General
1654 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1655 * function. Because, we don't want to update to a new
1656 * HPUX GR bundle just for aclsort() call.
1657 */
1658
1659 struct hpux_acl_types acl_obj_count;
1660 int n_class_obj_perm = 0;
1661 int i, j;
1662
1663 if(!acl_count) {
1664 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1665 return 0;
1666 }
1667
1668 if(aclp == NULL) {
1669 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1670 return -1;
1671 }
1672
1673 /* Count different types of ACLs in the ACLs array */
1674
1675 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1676
1677 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1678 * CLASS_OBJ and OTHER_OBJ
1679 */
1680
1681 if( (acl_obj_count.n_user_obj != 1) ||
1682 (acl_obj_count.n_group_obj != 1) ||
1683 (acl_obj_count.n_class_obj != 1) ||
1684 (acl_obj_count.n_other_obj != 1)
1685 ) {
1686 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1687USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1688 return -1;
1689 }
1690
1691 /* If any of the default objects are present, there should be only
1692 * one of them each.
1693 */
1694
1695 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1696 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1697 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1698or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1699 return -1;
1700 }
1701
1702 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1703 * structures.
1704 *
1705 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1706 * same ACL type, sort by ACL id.
1707 *
1708 * I am using the trival kind of sorting method here because, performance isn't
1709 * really effected by the ACLs feature. More over there aren't going to be more
1710 * than 17 entries on HPUX.
1711 */
1712
1713 for(i=0; i<acl_count;i++) {
1714 for (j=i+1; j<acl_count; j++) {
1715 if( aclp[i].a_type > aclp[j].a_type ) {
1716 /* ACL entries out of order, swap them */
1717
1718 hpux_swap_acl_entries((aclp+i), (aclp+j));
1719
1720 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1721
1722 /* ACL entries of same type, sort by id */
1723
1724 if(aclp[i].a_id > aclp[j].a_id) {
1725 hpux_swap_acl_entries((aclp+i), (aclp+j));
1726 } else if (aclp[i].a_id == aclp[j].a_id) {
1727 /* We have a duplicate entry. */
1728 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1729 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1730 aclp[i].a_type, aclp[i].a_id));
1731 return -1;
1732 }
1733 }
1734
1735 }
1736 }
1737 }
1738
1739 /* set the class obj permissions to the computed one. */
1740 if(calclass) {
1741 int n_class_obj_index = -1;
1742
1743 for(i=0;i<acl_count;i++) {
1744 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1745
1746 if(aclp[i].a_type == CLASS_OBJ)
1747 n_class_obj_index = i;
1748 }
1749 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1750 }
1751
1752 return 0;
1753#else
1754 return aclsort(acl_count, calclass, aclp);
1755#endif
1756}
1757
1758/*
1759 * sort the ACL and check it for validity
1760 *
1761 * if it's a minimal ACL with only 4 entries then we
1762 * need to recalculate the mask permissions to make
1763 * sure that they are the same as the GROUP_OBJ
1764 * permissions as required by the UnixWare acl() system call.
1765 *
1766 * (note: since POSIX allows minimal ACLs which only contain
1767 * 3 entries - ie there is no mask entry - we should, in theory,
1768 * check for this and add a mask entry if necessary - however
1769 * we "know" that the caller of this interface always specifies
1770 * a mask so, in practice "this never happens" (tm) - if it *does*
1771 * happen aclsort() will fail and return an error and someone will
1772 * have to fix it ...)
1773 */
1774
1775static int acl_sort(SMB_ACL_T acl_d)
1776{
1777 int fixmask = (acl_d->count <= 4);
1778
1779 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1780 errno = EINVAL;
1781 return -1;
1782 }
1783 return 0;
1784}
1785
1786int sys_acl_valid(SMB_ACL_T acl_d)
1787{
1788 return acl_sort(acl_d);
1789}
1790
1791int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1792{
1793 struct stat s;
1794 struct acl *acl_p;
1795 int acl_count;
1796 struct acl *acl_buf = NULL;
1797 int ret;
1798
1799 if(hpux_acl_call_presence() == False) {
1800 /* Looks like we don't have the acl() system call on HPUX.
1801 * May be the system doesn't have the latest version of JFS.
1802 */
1803 errno=ENOSYS;
1804 return -1;
1805 }
1806
1807 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1808 errno = EINVAL;
1809 return -1;
1810 }
1811
1812 if (acl_sort(acl_d) != 0) {
1813 return -1;
1814 }
1815
1816 acl_p = &acl_d->acl[0];
1817 acl_count = acl_d->count;
1818
1819 /*
1820 * if it's a directory there is extra work to do
1821 * since the acl() system call will replace both
1822 * the access ACLs and the default ACLs (if any)
1823 */
1824 if (stat(name, &s) != 0) {
1825 return -1;
1826 }
1827 if (S_ISDIR(s.st_mode)) {
1828 SMB_ACL_T acc_acl;
1829 SMB_ACL_T def_acl;
1830 SMB_ACL_T tmp_acl;
1831 int i;
1832
1833 if (type == SMB_ACL_TYPE_ACCESS) {
1834 acc_acl = acl_d;
1835 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1836
1837 } else {
1838 def_acl = acl_d;
1839 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1840 }
1841
1842 if (tmp_acl == NULL) {
1843 return -1;
1844 }
1845
1846 /*
1847 * allocate a temporary buffer for the complete ACL
1848 */
1849 acl_count = acc_acl->count + def_acl->count;
1850 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1851
1852 if (acl_buf == NULL) {
1853 sys_acl_free_acl(tmp_acl);
1854 errno = ENOMEM;
1855 return -1;
1856 }
1857
1858 /*
1859 * copy the access control and default entries into the buffer
1860 */
1861 memcpy(&acl_buf[0], &acc_acl->acl[0],
1862 acc_acl->count * sizeof(acl_buf[0]));
1863
1864 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1865 def_acl->count * sizeof(acl_buf[0]));
1866
1867 /*
1868 * set the ACL_DEFAULT flag on the default entries
1869 */
1870 for (i = acc_acl->count; i < acl_count; i++) {
1871 acl_buf[i].a_type |= ACL_DEFAULT;
1872 }
1873
1874 sys_acl_free_acl(tmp_acl);
1875
1876 } else if (type != SMB_ACL_TYPE_ACCESS) {
1877 errno = EINVAL;
1878 return -1;
1879 }
1880
1881 ret = acl(name, ACL_SET, acl_count, acl_p);
1882
1883 if (acl_buf) {
1884 free(acl_buf);
1885 }
1886
1887 return ret;
1888}
1889
1b897d50 1890#if 0
1c3344a1
WD
1891int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1892{
1893 /*
1894 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1895 */
1896
1897 files_struct *fsp = file_find_fd(fd);
1898
1899 if (fsp == NULL) {
1900 errno = EBADF;
1901 return NULL;
1902 }
1903
1904 if (acl_sort(acl_d) != 0) {
1905 return -1;
1906 }
1907
1908 /*
1909 * We know we're in the same conn context. So we
1910 * can use the relative path.
1911 */
1912
1913 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1914}
1b897d50 1915#endif
1c3344a1
WD
1916
1917int sys_acl_delete_def_file(const char *path)
1918{
1919 SMB_ACL_T acl_d;
1920 int ret;
1921
1922 /*
1923 * fetching the access ACL and rewriting it has
1924 * the effect of deleting the default ACL
1925 */
1926 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1927 return -1;
1928 }
1929
1930 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1931
1932 sys_acl_free_acl(acl_d);
1933
1934 return ret;
1935}
1936
1937int sys_acl_free_text(char *text)
1938{
1939 free(text);
1940 return 0;
1941}
1942
1943int sys_acl_free_acl(SMB_ACL_T acl_d)
1944{
1945 free(acl_d);
1946 return 0;
1947}
1948
1949int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1950{
1951 return 0;
1952}
1953
1954#elif defined(HAVE_IRIX_ACLS)
1955
1956int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1957{
1958 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1959 errno = EINVAL;
1960 return -1;
1961 }
1962
1963 if (entry_p == NULL) {
1964 errno = EINVAL;
1965 return -1;
1966 }
1967
1968 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1969 acl_d->next = 0;
1970 }
1971
1972 if (acl_d->next < 0) {
1973 errno = EINVAL;
1974 return -1;
1975 }
1976
1977 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1978 return 0;
1979 }
1980
1981 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1982
1983 return 1;
1984}
1985
1986int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1987{
1988 *type_p = entry_d->ae_tag;
1989
1990 return 0;
1991}
1992
1993int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1994{
1995 *permset_p = entry_d;
1996
1997 return 0;
1998}
1999
2000void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
2001{
2002 if (entry_d->ae_tag != SMB_ACL_USER
2003 && entry_d->ae_tag != SMB_ACL_GROUP) {
2004 errno = EINVAL;
2005 return NULL;
2006 }
2007
2008 return &entry_d->ae_id;
2009}
2010
2011SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
2012{
2013 SMB_ACL_T a;
2014
2015 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2016 errno = ENOMEM;
2017 return NULL;
2018 }
2019 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
2020 SAFE_FREE(a);
2021 return NULL;
2022 }
2023 a->next = -1;
2024 a->freeaclp = True;
2025 return a;
2026}
2027
2028SMB_ACL_T sys_acl_get_fd(int fd)
2029{
2030 SMB_ACL_T a;
2031
2032 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2033 errno = ENOMEM;
2034 return NULL;
2035 }
2036 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2037 SAFE_FREE(a);
2038 return NULL;
2039 }
2040 a->next = -1;
2041 a->freeaclp = True;
2042 return a;
2043}
2044
2045int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2046{
2047 permset_d->ae_perm = 0;
2048
2049 return 0;
2050}
2051
2052int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2053{
2054 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2055 && perm != SMB_ACL_EXECUTE) {
2056 errno = EINVAL;
2057 return -1;
2058 }
2059
2060 if (permset_d == NULL) {
2061 errno = EINVAL;
2062 return -1;
2063 }
2064
2065 permset_d->ae_perm |= perm;
2066
2067 return 0;
2068}
2069
2070int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2071{
2072 return permset_d->ae_perm & perm;
2073}
2074
2075char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2076{
2077 return acl_to_text(acl_d->aclp, len_p);
2078}
2079
2080SMB_ACL_T sys_acl_init(int count)
2081{
2082 SMB_ACL_T a;
2083
2084 if (count < 0) {
2085 errno = EINVAL;
2086 return NULL;
2087 }
2088
2089 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
2090 errno = ENOMEM;
2091 return NULL;
2092 }
2093
2094 a->next = -1;
2095 a->freeaclp = False;
2096 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2097 a->aclp->acl_cnt = 0;
2098
2099 return a;
2100}
2101
2102
2103int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2104{
2105 SMB_ACL_T acl_d;
2106 SMB_ACL_ENTRY_T entry_d;
2107
2108 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2109 errno = EINVAL;
2110 return -1;
2111 }
2112
2113 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2114 errno = ENOSPC;
2115 return -1;
2116 }
2117
2118 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2119 entry_d->ae_tag = 0;
2120 entry_d->ae_id = 0;
2121 entry_d->ae_perm = 0;
2122 *entry_p = entry_d;
2123
2124 return 0;
2125}
2126
2127int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2128{
2129 switch (tag_type) {
2130 case SMB_ACL_USER:
2131 case SMB_ACL_USER_OBJ:
2132 case SMB_ACL_GROUP:
2133 case SMB_ACL_GROUP_OBJ:
2134 case SMB_ACL_OTHER:
2135 case SMB_ACL_MASK:
2136 entry_d->ae_tag = tag_type;
2137 break;
2138 default:
2139 errno = EINVAL;
2140 return -1;
2141 }
2142
2143 return 0;
2144}
2145
2146int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2147{
2148 if (entry_d->ae_tag != SMB_ACL_GROUP
2149 && entry_d->ae_tag != SMB_ACL_USER) {
2150 errno = EINVAL;
2151 return -1;
2152 }
2153
2154 entry_d->ae_id = *((id_t *)qual_p);
2155
2156 return 0;
2157}
2158
2159int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2160{
2161 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2162 return EINVAL;
2163 }
2164
2165 entry_d->ae_perm = permset_d->ae_perm;
2166
2167 return 0;
2168}
2169
2170int sys_acl_valid(SMB_ACL_T acl_d)
2171{
2172 return acl_valid(acl_d->aclp);
2173}
2174
2175int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2176{
2177 return acl_set_file(name, type, acl_d->aclp);
2178}
2179
2180int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2181{
2182 return acl_set_fd(fd, acl_d->aclp);
2183}
2184
2185int sys_acl_delete_def_file(const char *name)
2186{
2187 return acl_delete_def_file(name);
2188}
2189
2190int sys_acl_free_text(char *text)
2191{
2192 return acl_free(text);
2193}
2194
2195int sys_acl_free_acl(SMB_ACL_T acl_d)
2196{
2197 if (acl_d->freeaclp) {
2198 acl_free(acl_d->aclp);
2199 }
2200 acl_free(acl_d);
2201 return 0;
2202}
2203
2204int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2205{
2206 return 0;
2207}
2208
2209#elif defined(HAVE_AIX_ACLS)
2210
2211/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2212
2213int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2214{
2215 struct acl_entry_link *link;
2216 struct new_acl_entry *entry;
2217 int keep_going;
2218
2219 DEBUG(10,("This is the count: %d\n",theacl->count));
2220
2221 /* Check if count was previously set to -1. *
2222 * If it was, that means we reached the end *
2223 * of the acl last time. */
2224 if(theacl->count == -1)
2225 return(0);
2226
2227 link = theacl;
2228 /* To get to the next acl, traverse linked list until index *
2229 * of acl matches the count we are keeping. This count is *
2230 * incremented each time we return an acl entry. */
2231
2232 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2233 link = link->nextp;
2234
2235 entry = *entry_p = link->entryp;
2236
2237 DEBUG(10,("*entry_p is %d\n",entry_p));
2238 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2239
2240 /* Increment count */
2241 theacl->count++;
2242 if(link->nextp == NULL)
2243 theacl->count = -1;
2244
2245 return(1);
2246}
2247
2248int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2249{
2250 /* Initialize tag type */
2251
2252 *tag_type_p = -1;
2253 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2254
2255 /* Depending on what type of entry we have, *
2256 * return tag type. */
2257 switch(entry_d->ace_id->id_type) {
2258 case ACEID_USER:
2259 *tag_type_p = SMB_ACL_USER;
2260 break;
2261 case ACEID_GROUP:
2262 *tag_type_p = SMB_ACL_GROUP;
2263 break;
2264
2265 case SMB_ACL_USER_OBJ:
2266 case SMB_ACL_GROUP_OBJ:
2267 case SMB_ACL_OTHER:
2268 *tag_type_p = entry_d->ace_id->id_type;
2269 break;
2270
2271 default:
2272 return(-1);
2273 }
2274
2275 return(0);
2276}
2277
2278int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2279{
2280 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2281 *permset_p = &entry_d->ace_access;
2282 DEBUG(10,("**permset_p is %d\n",**permset_p));
2283 if(!(**permset_p & S_IXUSR) &&
2284 !(**permset_p & S_IWUSR) &&
2285 !(**permset_p & S_IRUSR) &&
2286 (**permset_p != 0))
2287 return(-1);
2288
2289 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2290 return(0);
2291}
2292
2293void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2294{
2295 return(entry_d->ace_id->id_data);
2296}
2297
2298SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2299{
2300 struct acl *file_acl = (struct acl *)NULL;
2301 struct acl_entry *acl_entry;
2302 struct new_acl_entry *new_acl_entry;
2303 struct ace_id *idp;
2304 struct acl_entry_link *acl_entry_link;
2305 struct acl_entry_link *acl_entry_link_head;
2306 int i;
2307 int rc = 0;
2308 uid_t user_id;
2309
2310 /* AIX has no DEFAULT */
2311 if ( type == SMB_ACL_TYPE_DEFAULT ) {
2312 errno = ENOTSUP;
2313 return NULL;
2314 }
2315
2316 /* Get the acl using statacl */
2317
2318 DEBUG(10,("Entering sys_acl_get_file\n"));
2319 DEBUG(10,("path_p is %s\n",path_p));
2320
2321 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2322
2323 if(file_acl == NULL) {
2324 errno=ENOMEM;
2325 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2326 return(NULL);
2327 }
2328
2329 memset(file_acl,0,BUFSIZ);
2330
2331 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2332 if(rc == -1) {
2333 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2334 SAFE_FREE(file_acl);
2335 return(NULL);
2336 }
2337
2338 DEBUG(10,("Got facl and returned it\n"));
2339
2340 /* Point to the first acl entry in the acl */
2341 acl_entry = file_acl->acl_ext;
2342
2343 /* Begin setting up the head of the linked list *
2344 * that will be used for the storing the acl *
2345 * in a way that is useful for the posix_acls.c *
2346 * code. */
2347
2348 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2349 if(acl_entry_link_head == NULL)
2350 return(NULL);
2351
2352 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2353 if(acl_entry_link->entryp == NULL) {
2354 SAFE_FREE(file_acl);
2355 errno = ENOMEM;
2356 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2357 return(NULL);
2358 }
2359
2360 DEBUG(10,("acl_entry is %d\n",acl_entry));
2361 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2362
2363 /* Check if the extended acl bit is on. *
2364 * If it isn't, do not show the *
2365 * contents of the acl since AIX intends *
2366 * the extended info to remain unused */
2367
2368 if(file_acl->acl_mode & S_IXACL){
2369 /* while we are not pointing to the very end */
2370 while(acl_entry < acl_last(file_acl)) {
2371 /* before we malloc anything, make sure this is */
2372 /* a valid acl entry and one that we want to map */
2373 idp = id_nxt(acl_entry->ace_id);
2374 if((acl_entry->ace_type == ACC_SPECIFY ||
2375 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2376 acl_entry = acl_nxt(acl_entry);
2377 continue;
2378 }
2379
2380 idp = acl_entry->ace_id;
2381
2382 /* Check if this is the first entry in the linked list. *
2383 * The first entry needs to keep prevp pointing to NULL *
2384 * and already has entryp allocated. */
2385
2386 if(acl_entry_link_head->count != 0) {
2387 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2388
2389 if(acl_entry_link->nextp == NULL) {
2390 SAFE_FREE(file_acl);
2391 errno = ENOMEM;
2392 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2393 return(NULL);
2394 }
2395
2396 acl_entry_link->nextp->prevp = acl_entry_link;
2397 acl_entry_link = acl_entry_link->nextp;
2398 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2399 if(acl_entry_link->entryp == NULL) {
2400 SAFE_FREE(file_acl);
2401 errno = ENOMEM;
2402 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2403 return(NULL);
2404 }
2405 acl_entry_link->nextp = NULL;
2406 }
2407
2408 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2409
2410 /* Don't really need this since all types are going *
2411 * to be specified but, it's better than leaving it 0 */
2412
2413 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2414
2415 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2416
2417 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2418
2419 /* The access in the acl entries must be left shifted by *
2420 * three bites, because they will ultimately be compared *
2421 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2422
2423 switch(acl_entry->ace_type){
2424 case ACC_PERMIT:
2425 case ACC_SPECIFY:
2426 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2427 acl_entry_link->entryp->ace_access <<= 6;
2428 acl_entry_link_head->count++;
2429 break;
2430 case ACC_DENY:
2431 /* Since there is no way to return a DENY acl entry *
2432 * change to PERMIT and then shift. */
2433 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2434 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2435 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2436 acl_entry_link->entryp->ace_access <<= 6;
2437 acl_entry_link_head->count++;
2438 break;
2439 default:
2440 return(0);
2441 }
2442
2443 DEBUG(10,("acl_entry = %d\n",acl_entry));
2444 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2445
2446 acl_entry = acl_nxt(acl_entry);
2447 }
2448 } /* end of if enabled */
2449
2450 /* Since owner, group, other acl entries are not *
2451 * part of the acl entries in an acl, they must *
2452 * be dummied up to become part of the list. */
2453
2454 for( i = 1; i < 4; i++) {
2455 DEBUG(10,("i is %d\n",i));
2456 if(acl_entry_link_head->count != 0) {
2457 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2458 if(acl_entry_link->nextp == NULL) {
2459 SAFE_FREE(file_acl);
2460 errno = ENOMEM;
2461 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2462 return(NULL);
2463 }
2464
2465 acl_entry_link->nextp->prevp = acl_entry_link;
2466 acl_entry_link = acl_entry_link->nextp;
2467 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2468 if(acl_entry_link->entryp == NULL) {
2469 SAFE_FREE(file_acl);
2470 errno = ENOMEM;
2471 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2472 return(NULL);
2473 }
2474 }
2475
2476 acl_entry_link->nextp = NULL;
2477
2478 new_acl_entry = acl_entry_link->entryp;
2479 idp = new_acl_entry->ace_id;
2480
2481 new_acl_entry->ace_len = sizeof(struct acl_entry);
2482 new_acl_entry->ace_type = ACC_PERMIT;
2483 idp->id_len = sizeof(struct ace_id);
2484 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2485 memset(idp->id_data,0,sizeof(uid_t));
2486
2487 switch(i) {
2488 case 2:
2489 new_acl_entry->ace_access = file_acl->g_access << 6;
2490 idp->id_type = SMB_ACL_GROUP_OBJ;
2491 break;
2492
2493 case 3:
2494 new_acl_entry->ace_access = file_acl->o_access << 6;
2495 idp->id_type = SMB_ACL_OTHER;
2496 break;
2497
2498 case 1:
2499 new_acl_entry->ace_access = file_acl->u_access << 6;
2500 idp->id_type = SMB_ACL_USER_OBJ;
2501 break;
2502
2503 default:
2504 return(NULL);
2505
2506 }
2507
2508 acl_entry_link_head->count++;
2509 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2510 }
2511
2512 acl_entry_link_head->count = 0;
2513 SAFE_FREE(file_acl);
2514
2515 return(acl_entry_link_head);
2516}
2517
2518SMB_ACL_T sys_acl_get_fd(int fd)
2519{
2520 struct acl *file_acl = (struct acl *)NULL;
2521 struct acl_entry *acl_entry;
2522 struct new_acl_entry *new_acl_entry;
2523 struct ace_id *idp;
2524 struct acl_entry_link *acl_entry_link;
2525 struct acl_entry_link *acl_entry_link_head;
2526 int i;
2527 int rc = 0;
2528 uid_t user_id;
2529
2530 /* Get the acl using fstatacl */
2531
2532 DEBUG(10,("Entering sys_acl_get_fd\n"));
2533 DEBUG(10,("fd is %d\n",fd));
2534 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2535
2536 if(file_acl == NULL) {
2537 errno=ENOMEM;
2538 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2539 return(NULL);
2540 }
2541
2542 memset(file_acl,0,BUFSIZ);
2543
2544 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2545 if(rc == -1) {
2546 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2547 SAFE_FREE(file_acl);
2548 return(NULL);
2549 }
2550
2551 DEBUG(10,("Got facl and returned it\n"));
2552
2553 /* Point to the first acl entry in the acl */
2554
2555 acl_entry = file_acl->acl_ext;
2556 /* Begin setting up the head of the linked list *
2557 * that will be used for the storing the acl *
2558 * in a way that is useful for the posix_acls.c *
2559 * code. */
2560
2561 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2562 if(acl_entry_link_head == NULL){
2563 SAFE_FREE(file_acl);
2564 return(NULL);
2565 }
2566
2567 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2568
2569 if(acl_entry_link->entryp == NULL) {
2570 errno = ENOMEM;
2571 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2572 SAFE_FREE(file_acl);
2573 return(NULL);
2574 }
2575
2576 DEBUG(10,("acl_entry is %d\n",acl_entry));
2577 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2578
2579 /* Check if the extended acl bit is on. *
2580 * If it isn't, do not show the *
2581 * contents of the acl since AIX intends *
2582 * the extended info to remain unused */
2583
2584 if(file_acl->acl_mode & S_IXACL){
2585 /* while we are not pointing to the very end */
2586 while(acl_entry < acl_last(file_acl)) {
2587 /* before we malloc anything, make sure this is */
2588 /* a valid acl entry and one that we want to map */
2589
2590 idp = id_nxt(acl_entry->ace_id);
2591 if((acl_entry->ace_type == ACC_SPECIFY ||
2592 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2593 acl_entry = acl_nxt(acl_entry);
2594 continue;
2595 }
2596
2597 idp = acl_entry->ace_id;
2598
2599 /* Check if this is the first entry in the linked list. *
2600 * The first entry needs to keep prevp pointing to NULL *
2601 * and already has entryp allocated. */
2602
2603 if(acl_entry_link_head->count != 0) {
2604 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2605 if(acl_entry_link->nextp == NULL) {
2606 errno = ENOMEM;
2607 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2608 SAFE_FREE(file_acl);
2609 return(NULL);
2610 }
2611 acl_entry_link->nextp->prevp = acl_entry_link;
2612 acl_entry_link = acl_entry_link->nextp;
2613 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2614 if(acl_entry_link->entryp == NULL) {
2615 errno = ENOMEM;
2616 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2617 SAFE_FREE(file_acl);
2618 return(NULL);
2619 }
2620
2621 acl_entry_link->nextp = NULL;
2622 }
2623
2624 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2625
2626 /* Don't really need this since all types are going *
2627 * to be specified but, it's better than leaving it 0 */
2628
2629 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2630 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2631
2632 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2633
2634 /* The access in the acl entries must be left shifted by *
2635 * three bites, because they will ultimately be compared *
2636 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2637
2638 switch(acl_entry->ace_type){
2639 case ACC_PERMIT:
2640 case ACC_SPECIFY:
2641 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2642 acl_entry_link->entryp->ace_access <<= 6;
2643 acl_entry_link_head->count++;
2644 break;
2645 case ACC_DENY:
2646 /* Since there is no way to return a DENY acl entry *
2647 * change to PERMIT and then shift. */
2648 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2649 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2650 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2651 acl_entry_link->entryp->ace_access <<= 6;
2652 acl_entry_link_head->count++;
2653 break;
2654 default:
2655 return(0);
2656 }
2657
2658 DEBUG(10,("acl_entry = %d\n",acl_entry));
2659 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2660
2661 acl_entry = acl_nxt(acl_entry);
2662 }
2663 } /* end of if enabled */
2664
2665 /* Since owner, group, other acl entries are not *
2666 * part of the acl entries in an acl, they must *
2667 * be dummied up to become part of the list. */
2668
2669 for( i = 1; i < 4; i++) {
2670 DEBUG(10,("i is %d\n",i));
2671 if(acl_entry_link_head->count != 0){
2672 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2673 if(acl_entry_link->nextp == NULL) {
2674 errno = ENOMEM;
2675 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2676 SAFE_FREE(file_acl);
2677 return(NULL);
2678 }
2679
2680 acl_entry_link->nextp->prevp = acl_entry_link;
2681 acl_entry_link = acl_entry_link->nextp;
2682 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2683
2684 if(acl_entry_link->entryp == NULL) {
2685 SAFE_FREE(file_acl);
2686 errno = ENOMEM;
2687 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2688 return(NULL);
2689 }
2690 }
2691
2692 acl_entry_link->nextp = NULL;
2693
2694 new_acl_entry = acl_entry_link->entryp;
2695 idp = new_acl_entry->ace_id;
2696
2697 new_acl_entry->ace_len = sizeof(struct acl_entry);
2698 new_acl_entry->ace_type = ACC_PERMIT;
2699 idp->id_len = sizeof(struct ace_id);
2700 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2701 memset(idp->id_data,0,sizeof(uid_t));
2702
2703 switch(i) {
2704 case 2:
2705 new_acl_entry->ace_access = file_acl->g_access << 6;
2706 idp->id_type = SMB_ACL_GROUP_OBJ;
2707 break;
2708
2709 case 3:
2710 new_acl_entry->ace_access = file_acl->o_access << 6;
2711 idp->id_type = SMB_ACL_OTHER;
2712 break;
2713
2714 case 1:
2715 new_acl_entry->ace_access = file_acl->u_access << 6;
2716 idp->id_type = SMB_ACL_USER_OBJ;
2717 break;
2718
2719 default:
2720 return(NULL);
2721 }
2722
2723 acl_entry_link_head->count++;
2724 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2725 }
2726
2727 acl_entry_link_head->count = 0;
2728 SAFE_FREE(file_acl);
2729
2730 return(acl_entry_link_head);
2731}
2732
2733int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2734{
2735 *permset = *permset & ~0777;
2736 return(0);
2737}
2738
2739int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2740{
2741 if((perm != 0) &&
2742 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2743 return(-1);
2744
2745 *permset |= perm;
2746 DEBUG(10,("This is the permset now: %d\n",*permset));
2747 return(0);
2748}
2749
2750char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2751{
2752 return(NULL);
2753}
2754
2755SMB_ACL_T sys_acl_init( int count)
2756{
2757 struct acl_entry_link *theacl = NULL;
2758
2759 DEBUG(10,("Entering sys_acl_init\n"));
2760
2761 theacl = SMB_MALLOC_P(struct acl_entry_link);
2762 if(theacl == NULL) {
2763 errno = ENOMEM;
2764 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2765 return(NULL);
2766 }
2767
2768 theacl->count = 0;
2769 theacl->nextp = NULL;
2770 theacl->prevp = NULL;
2771 theacl->entryp = NULL;
2772 DEBUG(10,("Exiting sys_acl_init\n"));
2773 return(theacl);
2774}
2775
2776int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2777{
2778 struct acl_entry_link *theacl;
2779 struct acl_entry_link *acl_entryp;
2780 struct acl_entry_link *temp_entry;
2781 int counting;
2782
2783 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2784
2785 theacl = acl_entryp = *pacl;
2786
2787 /* Get to the end of the acl before adding entry */
2788
2789 for(counting=0; counting < theacl->count; counting++){
2790 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2791 temp_entry = acl_entryp;
2792 acl_entryp = acl_entryp->nextp;
2793 }
2794
2795 if(theacl->count != 0){
2796 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2797 if(acl_entryp == NULL) {
2798 errno = ENOMEM;
2799 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2800 return(-1);
2801 }
2802
2803 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2804 acl_entryp->prevp = temp_entry;
2805 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2806 }
2807
2808 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2809 if(*pentry == NULL) {
2810 errno = ENOMEM;
2811 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2812 return(-1);
2813 }
2814
2815 memset(*pentry,0,sizeof(struct new_acl_entry));
2816 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2817 acl_entryp->entryp->ace_type = ACC_PERMIT;
2818 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2819 acl_entryp->nextp = NULL;
2820 theacl->count++;
2821 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2822 return(0);
2823}
2824
2825int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2826{
2827 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2828 entry->ace_id->id_type = tagtype;
2829 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2830 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2831}
2832
2833int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2834{
2835 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2836 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2837 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2838 return(0);
2839}
2840
2841int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2842{
2843 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2844 if(!(*permset & S_IXUSR) &&
2845 !(*permset & S_IWUSR) &&
2846 !(*permset & S_IRUSR) &&
2847 (*permset != 0))
2848 return(-1);
2849
2850 entry->ace_access = *permset;
2851 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2852 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2853 return(0);
2854}
2855
2856int sys_acl_valid( SMB_ACL_T theacl )
2857{
2858 int user_obj = 0;
2859 int group_obj = 0;
2860 int other_obj = 0;
2861 struct acl_entry_link *acl_entry;
2862
2863 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2864 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2865 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2866 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2867 }
2868
2869 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2870
2871 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2872 return(-1);
2873
2874 return(0);
2875}
2876
2877int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2878{
2879 struct acl_entry_link *acl_entry_link = NULL;
2880 struct acl *file_acl = NULL;
2881 struct acl *file_acl_temp = NULL;
2882 struct acl_entry *acl_entry = NULL;
2883 struct ace_id *ace_id = NULL;
2884 uint id_type;
2885 uint ace_access;
2886 uint user_id;
2887 uint acl_length;
2888 uint rc;
2889
2890 DEBUG(10,("Entering sys_acl_set_file\n"));
2891 DEBUG(10,("File name is %s\n",name));
2892
2893 /* AIX has no default ACL */
2894 if(acltype == SMB_ACL_TYPE_DEFAULT)
2895 return(0);
2896
2897 acl_length = BUFSIZ;
2898 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2899
2900 if(file_acl == NULL) {
2901 errno = ENOMEM;
2902 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2903 return(-1);
2904 }
2905
2906 memset(file_acl,0,BUFSIZ);
2907
2908 file_acl->acl_len = ACL_SIZ;
2909 file_acl->acl_mode = S_IXACL;
2910
2911 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2912 acl_entry_link->entryp->ace_access >>= 6;
2913 id_type = acl_entry_link->entryp->ace_id->id_type;
2914
2915 switch(id_type) {
2916 case SMB_ACL_USER_OBJ:
2917 file_acl->u_access = acl_entry_link->entryp->ace_access;
2918 continue;
2919 case SMB_ACL_GROUP_OBJ:
2920 file_acl->g_access = acl_entry_link->entryp->ace_access;
2921 continue;
2922 case SMB_ACL_OTHER:
2923 file_acl->o_access = acl_entry_link->entryp->ace_access;
2924 continue;
2925 case SMB_ACL_MASK:
2926 continue;
2927 }
2928
2929 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2930 acl_length += sizeof(struct acl_entry);
2931 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2932 if(file_acl_temp == NULL) {
2933 SAFE_FREE(file_acl);
2934 errno = ENOMEM;
2935 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2936 return(-1);
2937 }
2938
2939 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2940 SAFE_FREE(file_acl);
2941 file_acl = file_acl_temp;
2942 }
2943
2944 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2945 file_acl->acl_len += sizeof(struct acl_entry);
2946 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2947 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2948
2949 /* In order to use this, we'll need to wait until we can get denies */
2950 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2951 acl_entry->ace_type = ACC_SPECIFY; */
2952
2953 acl_entry->ace_type = ACC_SPECIFY;
2954
2955 ace_id = acl_entry->ace_id;
2956
2957 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2958 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2959 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2960 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2961 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2962 }
2963
2964 rc = chacl(name,file_acl,file_acl->acl_len);
2965 DEBUG(10,("errno is %d\n",errno));
2966 DEBUG(10,("return code is %d\n",rc));
2967 SAFE_FREE(file_acl);
2968 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2969 return(rc);
2970}
2971
2972int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2973{
2974 struct acl_entry_link *acl_entry_link = NULL;
2975 struct acl *file_acl = NULL;
2976 struct acl *file_acl_temp = NULL;
2977 struct acl_entry *acl_entry = NULL;
2978 struct ace_id *ace_id = NULL;
2979 uint id_type;
2980 uint user_id;
2981 uint acl_length;
2982 uint rc;
2983
2984 DEBUG(10,("Entering sys_acl_set_fd\n"));
2985 acl_length = BUFSIZ;
2986 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2987
2988 if(file_acl == NULL) {
2989 errno = ENOMEM;
2990 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2991 return(-1);
2992 }
2993
2994 memset(file_acl,0,BUFSIZ);
2995
2996 file_acl->acl_len = ACL_SIZ;
2997 file_acl->acl_mode = S_IXACL;
2998
2999 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
3000 acl_entry_link->entryp->ace_access >>= 6;
3001 id_type = acl_entry_link->entryp->ace_id->id_type;
3002 DEBUG(10,("The id_type is %d\n",id_type));
3003
3004 switch(id_type) {
3005 case SMB_ACL_USER_OBJ:
3006 file_acl->u_access = acl_entry_link->entryp->ace_access;
3007 continue;
3008 case SMB_ACL_GROUP_OBJ:
3009 file_acl->g_access = acl_entry_link->entryp->ace_access;
3010 continue;
3011 case SMB_ACL_OTHER:
3012 file_acl->o_access = acl_entry_link->entryp->ace_access;
3013 continue;
3014 case SMB_ACL_MASK:
3015 continue;
3016 }
3017
3018 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
3019 acl_length += sizeof(struct acl_entry);
3020 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
3021 if(file_acl_temp == NULL) {
3022 SAFE_FREE(file_acl);
3023 errno = ENOMEM;
3024 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
3025 return(-1);
3026 }
3027
3028 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
3029 SAFE_FREE(file_acl);
3030 file_acl = file_acl_temp;
3031 }
3032
3033 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
3034 file_acl->acl_len += sizeof(struct acl_entry);
3035 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3036 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3037
3038 /* In order to use this, we'll need to wait until we can get denies */
3039 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3040 acl_entry->ace_type = ACC_SPECIFY; */
3041
3042 acl_entry->ace_type = ACC_SPECIFY;
3043
3044 ace_id = acl_entry->ace_id;
3045
3046 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3047 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3048 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3049 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3050 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3051 }
3052
3053 rc = fchacl(fd,file_acl,file_acl->acl_len);
3054 DEBUG(10,("errno is %d\n",errno));
3055 DEBUG(10,("return code is %d\n",rc));
3056 SAFE_FREE(file_acl);
3057 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3058 return(rc);
3059}
3060
3061int sys_acl_delete_def_file(const char *name)
3062{
3063 /* AIX has no default ACL */
3064 return 0;
3065}
3066
3067int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3068{
3069 return(*permset & perm);
3070}
3071
3072int sys_acl_free_text(char *text)
3073{
3074 return(0);
3075}
3076
3077int sys_acl_free_acl(SMB_ACL_T posix_acl)
3078{
3079 struct acl_entry_link *acl_entry_link;
3080
3081 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3082 SAFE_FREE(acl_entry_link->prevp->entryp);
3083 SAFE_FREE(acl_entry_link->prevp);
3084 }
3085
3086 SAFE_FREE(acl_entry_link->prevp->entryp);
3087 SAFE_FREE(acl_entry_link->prevp);
3088 SAFE_FREE(acl_entry_link->entryp);
3089 SAFE_FREE(acl_entry_link);
3090
3091 return(0);
3092}
3093
3094int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3095{
3096 return(0);
3097}
3098
3099#else /* No ACLs. */
3100
3101int sys_acl_get_entry(UNUSED(SMB_ACL_T the_acl), UNUSED(int entry_id), UNUSED(SMB_ACL_ENTRY_T *entry_p))
3102{
3103 errno = ENOSYS;
3104 return -1;
3105}
3106
3107int sys_acl_get_tag_type(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_TAG_T *tag_type_p))
3108{
3109 errno = ENOSYS;
3110 return -1;
3111}
3112
3113int sys_acl_get_permset(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_PERMSET_T *permset_p))
3114{
3115 errno = ENOSYS;
3116 return -1;
3117}
3118
3119void *sys_acl_get_qualifier(UNUSED(SMB_ACL_ENTRY_T entry_d))
3120{
3121 errno = ENOSYS;
3122 return NULL;
3123}
3124
3125SMB_ACL_T sys_acl_get_file(UNUSED(const char *path_p), UNUSED(SMB_ACL_TYPE_T type))
3126{
3127 errno = ENOSYS;
3128 return (SMB_ACL_T)NULL;
3129}
3130
3131SMB_ACL_T sys_acl_get_fd(UNUSED(int fd))
3132{
3133 errno = ENOSYS;
3134 return (SMB_ACL_T)NULL;
3135}
3136
3137int sys_acl_clear_perms(UNUSED(SMB_ACL_PERMSET_T permset))
3138{
3139 errno = ENOSYS;
3140 return -1;
3141}
3142
3143int sys_acl_add_perm( UNUSED(SMB_ACL_PERMSET_T permset), UNUSED(SMB_ACL_PERM_T perm))
3144{
3145 errno = ENOSYS;
3146 return -1;
3147}
3148
3149int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3150{
3151 errno = ENOSYS;
3152 return (permset & perm) ? 1 : 0;
3153}
3154
3155char *sys_acl_to_text(UNUSED(SMB_ACL_T the_acl), UNUSED(ssize_t *plen))
3156{
3157 errno = ENOSYS;
3158 return NULL;
3159}
3160
3161int sys_acl_free_text(UNUSED(char *text))
3162{
3163 errno = ENOSYS;
3164 return -1;
3165}
3166
3167SMB_ACL_T sys_acl_init(UNUSED(int count))
3168{
3169 errno = ENOSYS;
3170 return NULL;
3171}
3172
3173int sys_acl_create_entry(UNUSED(SMB_ACL_T *pacl), UNUSED(SMB_ACL_ENTRY_T *pentry))
3174{
3175 errno = ENOSYS;
3176 return -1;
3177}
3178
3179int sys_acl_set_tag_type(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_TAG_T tagtype))
3180{
3181 errno = ENOSYS;
3182 return -1;
3183}
3184
3185int sys_acl_set_qualifier(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(void *qual))
3186{
3187 errno = ENOSYS;
3188 return -1;
3189}
3190
3191int sys_acl_set_permset(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_PERMSET_T permset))
3192{
3193 errno = ENOSYS;
3194 return -1;
3195}
3196
3197int sys_acl_valid(UNUSED(SMB_ACL_T theacl))
3198{
3199 errno = ENOSYS;
3200 return -1;
3201}
3202
3203int sys_acl_set_file(UNUSED(const char *name), UNUSED(SMB_ACL_TYPE_T acltype), UNUSED(SMB_ACL_T theacl))
3204{
3205 errno = ENOSYS;
3206 return -1;
3207}
3208
3209int sys_acl_set_fd(UNUSED(int fd), UNUSED(SMB_ACL_T theacl))
3210{
3211 errno = ENOSYS;
3212 return -1;
3213}
3214
3215int sys_acl_delete_def_file(UNUSED(const char *name))
3216{
3217 errno = ENOSYS;
3218 return -1;
3219}
3220
3221int sys_acl_free_acl(UNUSED(SMB_ACL_T the_acl))
3222{
3223 errno = ENOSYS;
3224 return -1;
3225}
3226
3227int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
3228{
3229 errno = ENOSYS;
3230 return -1;
3231}
3232
3233#endif /* No ACLs. */
3234
3235/************************************************************************
3236 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3237 errno, 0 if not.
3238************************************************************************/
3239
3240int no_acl_syscall_error(int err)
3241{
3242#if defined(ENOSYS)
3243 if (err == ENOSYS) {
3244 return 1;
3245 }
3246#endif
3247#if defined(ENOTSUP)
3248 if (err == ENOTSUP) {
3249 return 1;
3250 }
3251#endif
3252 return 0;
3253}
3254
3255#endif /* SUPPORT_ACLS */