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