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