File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / lib / sysacls.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    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: 
   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: 
   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: 
   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: 
   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: 
   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: 
  117: SMB_ACL_T sys_acl_init(int count)
  118: {
  119: 	return acl_init(count);
  120: }
  121: 
  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: 
  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: 
  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: 
  156: int sys_acl_valid(SMB_ACL_T theacl)
  157: {
  158: 	return acl_valid(theacl);
  159: }
  160: 
  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: 
  173: int sys_acl_delete_def_file(const char *name)
  174: {
  175: 	return acl_delete_def_file(name);
  176: }
  177: 
  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:  */
  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: 
  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: 
  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: 
  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: 
  249: SMB_ACL_T sys_acl_init(int count)
  250: {
  251: 	return acl_init(count);
  252: }
  253: 
  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: 
  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: 
  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: 
  289: int sys_acl_valid(SMB_ACL_T theacl)
  290: {
  291: 	acl_entry_t	entry;
  292: 
  293: 	return acl_valid(theacl, &entry);
  294: }
  295: 
  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: 
  308: int sys_acl_delete_def_file(const char *name)
  309: {
  310: 	return acl_delete_def_file((char *)name);
  311: }
  312: 
  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: 
  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: 
  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: 
  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: 
  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: 
  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: 
  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: 
  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: 
  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: 
  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:  
  637: int sys_acl_valid(SMB_ACL_T acl_d)
  638: {
  639: 	return acl_sort(acl_d);
  640: }
  641: 
  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: 
  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: 
  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
  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: 
  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: 
  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: 
  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: 
  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: 
  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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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:  
 1394: int sys_acl_valid(SMB_ACL_T acl_d)
 1395: {
 1396: 	return acl_sort(acl_d);
 1397: }
 1398: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 1704: int sys_acl_valid(SMB_ACL_T acl_d)
 1705: {
 1706: 	return acl_valid(acl_d->aclp);
 1707: }
 1708: 
 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: 
 1721: int sys_acl_delete_def_file(const char *name)
 1722: {
 1723: 	return acl_delete_def_file(name);
 1724: }
 1725: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 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: 
 2574: int sys_acl_delete_def_file(UNUSED(const char *name))
 2575: {
 2576: 	/* AIX has no default ACL */
 2577: 	return 0;
 2578: }
 2579: 
 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: 
 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: 
 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: 
 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: 
 2675: SMB_ACL_T sys_acl_init(int count)
 2676: {
 2677: 	return acl_init(count);
 2678: }
 2679: 
 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: 
 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: 
 2736: int sys_acl_valid(SMB_ACL_T theacl)
 2737: {
 2738: 	return acl_valid(theacl);
 2739: }
 2740: 
 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: 
 2753: int sys_acl_delete_def_file(const char *name)
 2754: {
 2755: 	return acl_delete_def_file(name);
 2756: }
 2757: 
 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: 
 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 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>