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