File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / lib / sysacls.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:09:30 2012 UTC (12 years, 5 months ago) by misho
Branches: rsync, MAIN
CVS tags: rsync3_0_9p0, RSYNC3_1_0, RSYNC3_0_9, HEAD
rsync

    1: /*
    2:  * Unix SMB/CIFS implementation.
    3:  * Based on the Samba ACL support code.
    4:  * Copyright (C) Jeremy Allison 2000.
    5:  * Copyright (C) 2007-2008 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 preceed 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: #include <dl.h>
  771: 
  772: /*
  773:  * Based on the Solaris/SCO code - with modifications.
  774:  */
  775: 
  776: /*
  777:  * Note that while this code implements sufficient functionality
  778:  * to support the sys_acl_* interfaces it does not provide all
  779:  * of the semantics of the POSIX ACL interfaces.
  780:  *
  781:  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
  782:  * from a call to sys_acl_get_entry() should not be assumed to be
  783:  * valid after calling any of the following functions, which may
  784:  * reorder the entries in the ACL.
  785:  *
  786:  *	sys_acl_valid()
  787:  *	sys_acl_set_file()
  788:  *	sys_acl_set_fd()
  789:  */
  790: 
  791: /* This checks if the POSIX ACL system call is defined */
  792: /* which basically corresponds to whether JFS 3.3 or   */
  793: /* higher is installed. If acl() was called when it    */
  794: /* isn't defined, it causes the process to core dump   */
  795: /* so it is important to check this and avoid acl()    */
  796: /* calls if it isn't there.                            */
  797: 
  798: static BOOL hpux_acl_call_presence(void)
  799: {
  800: 
  801: 	shl_t handle = NULL;
  802: 	void *value;
  803: 	int ret_val=0;
  804: 	static BOOL already_checked=0;
  805: 
  806: 	if(already_checked)
  807: 		return True;
  808: 
  809: 
  810: 	ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
  811: 
  812: 	if(ret_val != 0) {
  813: 		DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
  814: 			ret_val, errno, strerror(errno)));
  815: 		DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
  816: 		return False;
  817: 	}
  818: 
  819: 	DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
  820: 
  821: 	already_checked = True;
  822: 	return True;
  823: }
  824: 
  825: int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
  826: {
  827: 	if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
  828: 		errno = EINVAL;
  829: 		return -1;
  830: 	}
  831: 
  832: 	if (entry_p == NULL) {
  833: 		errno = EINVAL;
  834: 		return -1;
  835: 	}
  836: 
  837: 	if (entry_id == SMB_ACL_FIRST_ENTRY) {
  838: 		acl_d->next = 0;
  839: 	}
  840: 
  841: 	if (acl_d->next < 0) {
  842: 		errno = EINVAL;
  843: 		return -1;
  844: 	}
  845: 
  846: 	if (acl_d->next >= acl_d->count) {
  847: 		return 0;
  848: 	}
  849: 
  850: 	*entry_p = &acl_d->acl[acl_d->next++];
  851: 
  852: 	return 1;
  853: }
  854: 
  855: int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
  856: {
  857: 	*type_p = entry_d->a_type;
  858: 
  859: 	return 0;
  860: }
  861: 
  862: /*
  863:  * There is no way of knowing what size the ACL returned by
  864:  * ACL_GET will be unless you first call ACL_CNT which means
  865:  * making an additional system call.
  866:  *
  867:  * In the hope of avoiding the cost of the additional system
  868:  * call in most cases, we initially allocate enough space for
  869:  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
  870:  * be too small then we use ACL_CNT to find out the actual
  871:  * size, reallocate the ACL buffer, and then call ACL_GET again.
  872:  */
  873: 
  874: #define	INITIAL_ACL_SIZE	16
  875: 
  876: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
  877: {
  878: 	SMB_ACL_T	acl_d;
  879: 	int		count;		/* # of ACL entries allocated	*/
  880: 	int		naccess;	/* # of access ACL entries	*/
  881: 	int		ndefault;	/* # of default ACL entries	*/
  882: 
  883: 	if(hpux_acl_call_presence() == False) {
  884: 		/* Looks like we don't have the acl() system call on HPUX. 
  885: 		 * May be the system doesn't have the latest version of JFS.
  886: 		 */
  887: 		return NULL; 
  888: 	}
  889: 
  890: 	if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
  891: 		errno = EINVAL;
  892: 		return NULL;
  893: 	}
  894: 
  895: 	count = INITIAL_ACL_SIZE;
  896: 	if ((acl_d = sys_acl_init(count)) == NULL) {
  897: 		return NULL;
  898: 	}
  899: 
  900: 	/*
  901: 	 * If there isn't enough space for the ACL entries we use
  902: 	 * ACL_CNT to determine the actual number of ACL entries
  903: 	 * reallocate and try again. This is in a loop because it
  904: 	 * is possible that someone else could modify the ACL and
  905: 	 * increase the number of entries between the call to
  906: 	 * ACL_CNT and the call to ACL_GET.
  907: 	 */
  908: 	while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
  909: 
  910: 		sys_acl_free_acl(acl_d);
  911: 
  912: 		if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
  913: 			return NULL;
  914: 		}
  915: 
  916: 		if ((acl_d = sys_acl_init(count)) == NULL) {
  917: 			return NULL;
  918: 		}
  919: 	}
  920: 
  921: 	if (count < 0) {
  922: 		sys_acl_free_acl(acl_d);
  923: 		return NULL;
  924: 	}
  925: 
  926: 	/*
  927: 	 * calculate the number of access and default ACL entries
  928: 	 *
  929: 	 * Note: we assume that the acl() system call returned a
  930: 	 * well formed ACL which is sorted so that all of the
  931: 	 * access ACL entries preceed any default ACL entries
  932: 	 */
  933: 	for (naccess = 0; naccess < count; naccess++) {
  934: 		if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
  935: 			break;
  936: 	}
  937: 	ndefault = count - naccess;
  938: 	
  939: 	/*
  940: 	 * if the caller wants the default ACL we have to copy
  941: 	 * the entries down to the start of the acl[] buffer
  942: 	 * and mask out the ACL_DEFAULT flag from the type field
  943: 	 */
  944: 	if (type == SMB_ACL_TYPE_DEFAULT) {
  945: 		int	i, j;
  946: 
  947: 		for (i = 0, j = naccess; i < ndefault; i++, j++) {
  948: 			acl_d->acl[i] = acl_d->acl[j];
  949: 			acl_d->acl[i].a_type &= ~ACL_DEFAULT;
  950: 		}
  951: 
  952: 		acl_d->count = ndefault;
  953: 	} else {
  954: 		acl_d->count = naccess;
  955: 	}
  956: 
  957: 	return acl_d;
  958: }
  959: 
  960: #if 0
  961: SMB_ACL_T sys_acl_get_fd(int fd)
  962: {
  963: 	/*
  964: 	 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
  965: 	 */
  966: 
  967: 	files_struct *fsp = file_find_fd(fd);
  968: 
  969: 	if (fsp == NULL) {
  970: 		errno = EBADF;
  971: 		return NULL;
  972: 	}
  973: 
  974: 	/*
  975: 	 * We know we're in the same conn context. So we
  976: 	 * can use the relative path.
  977: 	 */
  978: 
  979: 	return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
  980: }
  981: #endif
  982: 
  983: 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)
  984: {
  985: 	*tag_type_p = entry->a_type;
  986: 
  987: 	*bits_p = entry->a_perm;
  988: 
  989: 	if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
  990: 		*u_g_id_p = entry->a_id;
  991: 
  992: 	return 0;
  993: }
  994: 
  995: SMB_ACL_T sys_acl_init(int count)
  996: {
  997: 	SMB_ACL_T	a;
  998: 
  999: 	if (count < 0) {
 1000: 		errno = EINVAL;
 1001: 		return NULL;
 1002: 	}
 1003: 
 1004: 	/*
 1005: 	 * note that since the definition of the structure pointed
 1006: 	 * to by the SMB_ACL_T includes the first element of the
 1007: 	 * acl[] array, this actually allocates an ACL with room
 1008: 	 * for (count+1) entries
 1009: 	 */
 1010: 	if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof(struct acl))) == NULL) {
 1011: 		errno = ENOMEM;
 1012: 		return NULL;
 1013: 	}
 1014: 
 1015: 	a->size = count + 1;
 1016: 	a->count = 0;
 1017: 	a->next = -1;
 1018: 
 1019: 	return a;
 1020: }
 1021: 
 1022: 
 1023: int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
 1024: {
 1025: 	SMB_ACL_T	acl_d;
 1026: 	SMB_ACL_ENTRY_T	entry_d;
 1027: 
 1028: 	if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
 1029: 		errno = EINVAL;
 1030: 		return -1;
 1031: 	}
 1032: 
 1033: 	if (acl_d->count >= acl_d->size) {
 1034: 		errno = ENOSPC;
 1035: 		return -1;
 1036: 	}
 1037: 
 1038: 	entry_d		= &acl_d->acl[acl_d->count++];
 1039: 	entry_d->a_type	= 0;
 1040: 	entry_d->a_id	= -1;
 1041: 	entry_d->a_perm	= 0;
 1042: 	*entry_p	= entry_d;
 1043: 
 1044: 	return 0;
 1045: }
 1046: 
 1047: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
 1048: {
 1049: 	entry->a_type = tag_type;
 1050: 
 1051: 	if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
 1052: 		entry->a_id = u_g_id;
 1053: 
 1054: 	entry->a_perm = bits;
 1055: 
 1056: 	return 0;
 1057: }
 1058: 
 1059: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
 1060: {
 1061: 	entry_d->a_perm = bits;
 1062: 
 1063: 	return 0;
 1064: }
 1065: 
 1066: /* Structure to capture the count for each type of ACE. */
 1067: 
 1068: struct hpux_acl_types {
 1069: 	int n_user;
 1070: 	int n_def_user;
 1071: 	int n_user_obj;
 1072: 	int n_def_user_obj;
 1073: 
 1074: 	int n_group;
 1075: 	int n_def_group;
 1076: 	int n_group_obj;
 1077: 	int n_def_group_obj;
 1078: 
 1079: 	int n_other;
 1080: 	int n_other_obj;
 1081: 	int n_def_other_obj;
 1082: 
 1083: 	int n_class_obj;
 1084: 	int n_def_class_obj;
 1085: 
 1086: 	int n_illegal_obj;
 1087: };
 1088: 
 1089: /* count_obj:
 1090:  * Counts the different number of objects in a given array of ACL
 1091:  * structures.
 1092:  * Inputs:
 1093:  *
 1094:  * acl_count      - Count of ACLs in the array of ACL strucutres.
 1095:  * aclp           - Array of ACL structures.
 1096:  * acl_type_count - Pointer to acl_types structure. Should already be
 1097:  *                  allocated.
 1098:  * Output: 
 1099:  *
 1100:  * acl_type_count - This structure is filled up with counts of various 
 1101:  *                  acl types.
 1102:  */
 1103: 
 1104: static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
 1105: {
 1106: 	int i;
 1107: 
 1108: 	memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
 1109: 
 1110: 	for(i=0;i<acl_count;i++) {
 1111: 		switch(aclp[i].a_type) {
 1112: 		case USER: 
 1113: 			acl_type_count->n_user++;
 1114: 			break;
 1115: 		case USER_OBJ: 
 1116: 			acl_type_count->n_user_obj++;
 1117: 			break;
 1118: 		case DEF_USER_OBJ: 
 1119: 			acl_type_count->n_def_user_obj++;
 1120: 			break;
 1121: 		case GROUP: 
 1122: 			acl_type_count->n_group++;
 1123: 			break;
 1124: 		case GROUP_OBJ: 
 1125: 			acl_type_count->n_group_obj++;
 1126: 			break;
 1127: 		case DEF_GROUP_OBJ: 
 1128: 			acl_type_count->n_def_group_obj++;
 1129: 			break;
 1130: 		case OTHER_OBJ: 
 1131: 			acl_type_count->n_other_obj++;
 1132: 			break;
 1133: 		case DEF_OTHER_OBJ: 
 1134: 			acl_type_count->n_def_other_obj++;
 1135: 			break;
 1136: 		case CLASS_OBJ:
 1137: 			acl_type_count->n_class_obj++;
 1138: 			break;
 1139: 		case DEF_CLASS_OBJ:
 1140: 			acl_type_count->n_def_class_obj++;
 1141: 			break;
 1142: 		case DEF_USER:
 1143: 			acl_type_count->n_def_user++;
 1144: 			break;
 1145: 		case DEF_GROUP:
 1146: 			acl_type_count->n_def_group++;
 1147: 			break;
 1148: 		default: 
 1149: 			acl_type_count->n_illegal_obj++;
 1150: 			break;
 1151: 		}
 1152: 	}
 1153: }
 1154: 
 1155: /* swap_acl_entries:  Swaps two ACL entries. 
 1156:  *
 1157:  * Inputs: aclp0, aclp1 - ACL entries to be swapped.
 1158:  */
 1159: 
 1160: static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
 1161: {
 1162: 	struct acl temp_acl;
 1163: 
 1164: 	temp_acl.a_type = aclp0->a_type;
 1165: 	temp_acl.a_id = aclp0->a_id;
 1166: 	temp_acl.a_perm = aclp0->a_perm;
 1167: 
 1168: 	aclp0->a_type = aclp1->a_type;
 1169: 	aclp0->a_id = aclp1->a_id;
 1170: 	aclp0->a_perm = aclp1->a_perm;
 1171: 
 1172: 	aclp1->a_type = temp_acl.a_type;
 1173: 	aclp1->a_id = temp_acl.a_id;
 1174: 	aclp1->a_perm = temp_acl.a_perm;
 1175: }
 1176: 
 1177: /* prohibited_duplicate_type
 1178:  * Identifies if given ACL type can have duplicate entries or 
 1179:  * not.
 1180:  *
 1181:  * Inputs: acl_type - ACL Type.
 1182:  *
 1183:  * Outputs: 
 1184:  *
 1185:  * Return.. 
 1186:  *
 1187:  * True - If the ACL type matches any of the prohibited types.
 1188:  * False - If the ACL type doesn't match any of the prohibited types.
 1189:  */ 
 1190: 
 1191: static BOOL hpux_prohibited_duplicate_type(int acl_type)
 1192: {
 1193: 	switch(acl_type) {
 1194: 		case USER:
 1195: 		case GROUP:
 1196: 		case DEF_USER: 
 1197: 		case DEF_GROUP:
 1198: 			return True;
 1199: 		default:
 1200: 			return False;
 1201: 	}
 1202: }
 1203: 
 1204: /* get_needed_class_perm
 1205:  * Returns the permissions of a ACL structure only if the ACL
 1206:  * type matches one of the pre-determined types for computing 
 1207:  * CLASS_OBJ permissions.
 1208:  *
 1209:  * Inputs: aclp - Pointer to ACL structure.
 1210:  */
 1211: 
 1212: static int hpux_get_needed_class_perm(struct acl *aclp)
 1213: {
 1214: 	switch(aclp->a_type) {
 1215: 		case USER: 
 1216: 		case GROUP_OBJ: 
 1217: 		case GROUP: 
 1218: 		case DEF_USER_OBJ: 
 1219: 		case DEF_USER:
 1220: 		case DEF_GROUP_OBJ: 
 1221: 		case DEF_GROUP:
 1222: 		case DEF_CLASS_OBJ:
 1223: 		case DEF_OTHER_OBJ: 
 1224: 			return aclp->a_perm;
 1225: 		default: 
 1226: 			return 0;
 1227: 	}
 1228: }
 1229: 
 1230: /* acl_sort for HPUX.
 1231:  * Sorts the array of ACL structures as per the description in
 1232:  * aclsort man page. Refer to aclsort man page for more details
 1233:  *
 1234:  * Inputs:
 1235:  *
 1236:  * acl_count - Count of ACLs in the array of ACL structures.
 1237:  * calclass  - If this is not zero, then we compute the CLASS_OBJ
 1238:  *             permissions.
 1239:  * aclp      - Array of ACL structures.
 1240:  *
 1241:  * Outputs:
 1242:  *
 1243:  * aclp     - Sorted array of ACL structures.
 1244:  *
 1245:  * Outputs:
 1246:  *
 1247:  * Returns 0 for success -1 for failure. Prints a message to the Samba
 1248:  * debug log in case of failure.
 1249:  */
 1250: 
 1251: static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
 1252: {
 1253: #if !defined(HAVE_HPUX_ACLSORT)
 1254: 	/*
 1255: 	 * The aclsort() system call is availabe on the latest HPUX General
 1256: 	 * Patch Bundles. So for HPUX, we developed our version of acl_sort 
 1257: 	 * function. Because, we don't want to update to a new 
 1258: 	 * HPUX GR bundle just for aclsort() call.
 1259: 	 */
 1260: 
 1261: 	struct hpux_acl_types acl_obj_count;
 1262: 	int n_class_obj_perm = 0;
 1263: 	int i, j;
 1264:  
 1265: 	if(!acl_count) {
 1266: 		DEBUG(10,("Zero acl count passed. Returning Success\n"));
 1267: 		return 0;
 1268: 	}
 1269: 
 1270: 	if(aclp == NULL) {
 1271: 		DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
 1272: 		return -1;
 1273: 	}
 1274: 
 1275: 	/* Count different types of ACLs in the ACLs array */
 1276: 
 1277: 	hpux_count_obj(acl_count, aclp, &acl_obj_count);
 1278: 
 1279: 	/* There should be only one entry each of type USER_OBJ, GROUP_OBJ, 
 1280: 	 * CLASS_OBJ and OTHER_OBJ 
 1281: 	 */
 1282: 
 1283: 	if( (acl_obj_count.n_user_obj  != 1) || 
 1284: 		(acl_obj_count.n_group_obj != 1) || 
 1285: 		(acl_obj_count.n_class_obj != 1) ||
 1286: 		(acl_obj_count.n_other_obj != 1) 
 1287: 	) {
 1288: 		DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
 1289: USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
 1290: 		return -1;
 1291: 	}
 1292: 
 1293: 	/* If any of the default objects are present, there should be only
 1294: 	 * one of them each.
 1295: 	 */
 1296: 
 1297: 	if( (acl_obj_count.n_def_user_obj  > 1) || (acl_obj_count.n_def_group_obj > 1) || 
 1298: 			(acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
 1299: 		DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
 1300: or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
 1301: 		return -1;
 1302: 	}
 1303: 
 1304: 	/* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl 
 1305: 	 * structures.  
 1306: 	 *
 1307: 	 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
 1308: 	 * same ACL type, sort by ACL id.
 1309: 	 *
 1310: 	 * I am using the trival kind of sorting method here because, performance isn't 
 1311: 	 * really effected by the ACLs feature. More over there aren't going to be more
 1312: 	 * than 17 entries on HPUX. 
 1313: 	 */
 1314: 
 1315: 	for(i=0; i<acl_count;i++) {
 1316: 		for (j=i+1; j<acl_count; j++) {
 1317: 			if( aclp[i].a_type > aclp[j].a_type ) {
 1318: 				/* ACL entries out of order, swap them */
 1319: 
 1320: 				hpux_swap_acl_entries((aclp+i), (aclp+j));
 1321: 
 1322: 			} else if ( aclp[i].a_type == aclp[j].a_type ) {
 1323: 
 1324: 				/* ACL entries of same type, sort by id */
 1325: 
 1326: 				if(aclp[i].a_id > aclp[j].a_id) {
 1327: 					hpux_swap_acl_entries((aclp+i), (aclp+j));
 1328: 				} else if (aclp[i].a_id == aclp[j].a_id) {
 1329: 					/* We have a duplicate entry. */
 1330: 					if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
 1331: 						DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
 1332: 							aclp[i].a_type, aclp[i].a_id));
 1333: 						return -1;
 1334: 					}
 1335: 				}
 1336: 
 1337: 			}
 1338: 		}
 1339: 	}
 1340: 
 1341: 	/* set the class obj permissions to the computed one. */
 1342: 	if(calclass) {
 1343: 		int n_class_obj_index = -1;
 1344: 
 1345: 		for(i=0;i<acl_count;i++) {
 1346: 			n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
 1347: 
 1348: 			if(aclp[i].a_type == CLASS_OBJ)
 1349: 				n_class_obj_index = i;
 1350: 		}
 1351: 		aclp[n_class_obj_index].a_perm = n_class_obj_perm;
 1352: 	}
 1353: 
 1354: 	return 0;
 1355: #else
 1356: 	return aclsort(acl_count, calclass, aclp);
 1357: #endif
 1358: }
 1359: 
 1360: /*
 1361:  * sort the ACL and check it for validity
 1362:  *
 1363:  * if it's a minimal ACL with only 4 entries then we
 1364:  * need to recalculate the mask permissions to make
 1365:  * sure that they are the same as the GROUP_OBJ
 1366:  * permissions as required by the UnixWare acl() system call.
 1367:  *
 1368:  * (note: since POSIX allows minimal ACLs which only contain
 1369:  * 3 entries - ie there is no mask entry - we should, in theory,
 1370:  * check for this and add a mask entry if necessary - however
 1371:  * we "know" that the caller of this interface always specifies
 1372:  * a mask so, in practice "this never happens" (tm) - if it *does*
 1373:  * happen aclsort() will fail and return an error and someone will
 1374:  * have to fix it ...)
 1375:  */
 1376: 
 1377: static int acl_sort(SMB_ACL_T acl_d)
 1378: {
 1379: 	int fixmask = (acl_d->count <= 4);
 1380: 
 1381: 	if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
 1382: 		errno = EINVAL;
 1383: 		return -1;
 1384: 	}
 1385: 	return 0;
 1386: }
 1387:  
 1388: int sys_acl_valid(SMB_ACL_T acl_d)
 1389: {
 1390: 	return acl_sort(acl_d);
 1391: }
 1392: 
 1393: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 1394: {
 1395: 	struct stat	s;
 1396: 	struct acl	*acl_p;
 1397: 	int		acl_count;
 1398: 	struct acl	*acl_buf	= NULL;
 1399: 	int		ret;
 1400: 
 1401: 	if(hpux_acl_call_presence() == False) {
 1402: 		/* Looks like we don't have the acl() system call on HPUX. 
 1403: 		 * May be the system doesn't have the latest version of JFS.
 1404: 		 */
 1405: 		errno=ENOSYS;
 1406: 		return -1; 
 1407: 	}
 1408: 
 1409: 	if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
 1410: 		errno = EINVAL;
 1411: 		return -1;
 1412: 	}
 1413: 
 1414: 	if (acl_sort(acl_d) != 0) {
 1415: 		return -1;
 1416: 	}
 1417: 
 1418: 	acl_p		= &acl_d->acl[0];
 1419: 	acl_count	= acl_d->count;
 1420: 
 1421: 	/*
 1422: 	 * if it's a directory there is extra work to do
 1423: 	 * since the acl() system call will replace both
 1424: 	 * the access ACLs and the default ACLs (if any)
 1425: 	 */
 1426: 	if (stat(name, &s) != 0) {
 1427: 		return -1;
 1428: 	}
 1429: 	if (S_ISDIR(s.st_mode)) {
 1430: 		SMB_ACL_T	acc_acl;
 1431: 		SMB_ACL_T	def_acl;
 1432: 		SMB_ACL_T	tmp_acl;
 1433: 		int		i;
 1434: 
 1435: 		if (type == SMB_ACL_TYPE_ACCESS) {
 1436: 			acc_acl = acl_d;
 1437: 			def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
 1438: 
 1439: 		} else {
 1440: 			def_acl = acl_d;
 1441: 			acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
 1442: 		}
 1443: 
 1444: 		if (tmp_acl == NULL) {
 1445: 			return -1;
 1446: 		}
 1447: 
 1448: 		/*
 1449: 		 * allocate a temporary buffer for the complete ACL
 1450: 		 */
 1451: 		acl_count = acc_acl->count + def_acl->count;
 1452: 		acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
 1453: 
 1454: 		if (acl_buf == NULL) {
 1455: 			sys_acl_free_acl(tmp_acl);
 1456: 			errno = ENOMEM;
 1457: 			return -1;
 1458: 		}
 1459: 
 1460: 		/*
 1461: 		 * copy the access control and default entries into the buffer
 1462: 		 */
 1463: 		memcpy(&acl_buf[0], &acc_acl->acl[0],
 1464: 			acc_acl->count * sizeof(acl_buf[0]));
 1465: 
 1466: 		memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
 1467: 			def_acl->count * sizeof(acl_buf[0]));
 1468: 
 1469: 		/*
 1470: 		 * set the ACL_DEFAULT flag on the default entries
 1471: 		 */
 1472: 		for (i = acc_acl->count; i < acl_count; i++) {
 1473: 			acl_buf[i].a_type |= ACL_DEFAULT;
 1474: 		}
 1475: 
 1476: 		sys_acl_free_acl(tmp_acl);
 1477: 
 1478: 	} else if (type != SMB_ACL_TYPE_ACCESS) {
 1479: 		errno = EINVAL;
 1480: 		return -1;
 1481: 	}
 1482: 
 1483: 	ret = acl(name, ACL_SET, acl_count, acl_p);
 1484: 
 1485: 	if (acl_buf) {
 1486: 		free(acl_buf);
 1487: 	}
 1488: 
 1489: 	return ret;
 1490: }
 1491: 
 1492: #if 0
 1493: int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
 1494: {
 1495: 	/*
 1496: 	 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
 1497: 	 */
 1498: 
 1499: 	files_struct *fsp = file_find_fd(fd);
 1500: 
 1501: 	if (fsp == NULL) {
 1502: 		errno = EBADF;
 1503: 		return NULL;
 1504: 	}
 1505: 
 1506: 	if (acl_sort(acl_d) != 0) {
 1507: 		return -1;
 1508: 	}
 1509: 
 1510: 	/*
 1511: 	 * We know we're in the same conn context. So we
 1512: 	 * can use the relative path.
 1513: 	 */
 1514: 
 1515: 	return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
 1516: }
 1517: #endif
 1518: 
 1519: int sys_acl_delete_def_file(const char *path)
 1520: {
 1521: 	SMB_ACL_T	acl_d;
 1522: 	int		ret;
 1523: 
 1524: 	/*
 1525: 	 * fetching the access ACL and rewriting it has
 1526: 	 * the effect of deleting the default ACL
 1527: 	 */
 1528: 	if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
 1529: 		return -1;
 1530: 	}
 1531: 
 1532: 	ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
 1533: 
 1534: 	sys_acl_free_acl(acl_d);
 1535: 	
 1536: 	return ret;
 1537: }
 1538: 
 1539: int sys_acl_free_acl(SMB_ACL_T acl_d) 
 1540: {
 1541: 	free(acl_d);
 1542: 	return 0;
 1543: }
 1544: 
 1545: #elif defined(HAVE_IRIX_ACLS) /*---------------------------------------------*/
 1546: 
 1547: int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
 1548: {
 1549: 	if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
 1550: 		errno = EINVAL;
 1551: 		return -1;
 1552: 	}
 1553: 
 1554: 	if (entry_p == NULL) {
 1555: 		errno = EINVAL;
 1556: 		return -1;
 1557: 	}
 1558: 
 1559: 	if (entry_id == SMB_ACL_FIRST_ENTRY) {
 1560: 		acl_d->next = 0;
 1561: 	}
 1562: 
 1563: 	if (acl_d->next < 0) {
 1564: 		errno = EINVAL;
 1565: 		return -1;
 1566: 	}
 1567: 
 1568: 	if (acl_d->next >= acl_d->aclp->acl_cnt) {
 1569: 		return 0;
 1570: 	}
 1571: 
 1572: 	*entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
 1573: 
 1574: 	return 1;
 1575: }
 1576: 
 1577: int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
 1578: {
 1579: 	*type_p = entry_d->ae_tag;
 1580: 
 1581: 	return 0;
 1582: }
 1583: 
 1584: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
 1585: {
 1586: 	SMB_ACL_T	a;
 1587: 
 1588: 	if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
 1589: 		errno = ENOMEM;
 1590: 		return NULL;
 1591: 	}
 1592: 	if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
 1593: 		SAFE_FREE(a);
 1594: 		return NULL;
 1595: 	}
 1596: 	a->next = -1;
 1597: 	a->freeaclp = True;
 1598: 	return a;
 1599: }
 1600: 
 1601: #if 0
 1602: SMB_ACL_T sys_acl_get_fd(int fd)
 1603: {
 1604: 	SMB_ACL_T	a;
 1605: 
 1606: 	if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
 1607: 		errno = ENOMEM;
 1608: 		return NULL;
 1609: 	}
 1610: 	if ((a->aclp = acl_get_fd(fd)) == NULL) {
 1611: 		SAFE_FREE(a);
 1612: 		return NULL;
 1613: 	}
 1614: 	a->next = -1;
 1615: 	a->freeaclp = True;
 1616: 	return a;
 1617: }
 1618: #endif
 1619: 
 1620: 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)
 1621: {
 1622: 	*tag_type_p = entry->ae_tag;
 1623: 
 1624: 	*bits_p = entry->ae_perm;
 1625: 
 1626: 	if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
 1627: 		*u_g_id_p = entry->ae_id;
 1628: 
 1629: 	return 0;
 1630: }
 1631: 
 1632: SMB_ACL_T sys_acl_init(int count)
 1633: {
 1634: 	SMB_ACL_T	a;
 1635: 
 1636: 	if (count < 0) {
 1637: 		errno = EINVAL;
 1638: 		return NULL;
 1639: 	}
 1640: 
 1641: 	if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + sizeof (struct acl))) == NULL) {
 1642: 		errno = ENOMEM;
 1643: 		return NULL;
 1644: 	}
 1645: 
 1646: 	a->next = -1;
 1647: 	a->freeaclp = False;
 1648: 	a->aclp = (struct acl *)((char *)a + sizeof a[0]);
 1649: 	a->aclp->acl_cnt = 0;
 1650: 
 1651: 	return a;
 1652: }
 1653: 
 1654: 
 1655: int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
 1656: {
 1657: 	SMB_ACL_T	acl_d;
 1658: 	SMB_ACL_ENTRY_T	entry_d;
 1659: 
 1660: 	if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
 1661: 		errno = EINVAL;
 1662: 		return -1;
 1663: 	}
 1664: 
 1665: 	if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
 1666: 		errno = ENOSPC;
 1667: 		return -1;
 1668: 	}
 1669: 
 1670: 	entry_d		= &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
 1671: 	entry_d->ae_tag	= 0;
 1672: 	entry_d->ae_id	= 0;
 1673: 	entry_d->ae_perm	= 0;
 1674: 	*entry_p	= entry_d;
 1675: 
 1676: 	return 0;
 1677: }
 1678: 
 1679: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
 1680: {
 1681: 	entry->ae_tag = tag_type;
 1682: 
 1683: 	if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
 1684: 		entry->ae_id = u_g_id;
 1685: 
 1686: 	entry->ae_perm = bits;
 1687: 
 1688: 	return 0;
 1689: }
 1690: 
 1691: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
 1692: {
 1693: 	entry_d->ae_perm = bits;
 1694: 
 1695: 	return 0;
 1696: }
 1697: 
 1698: int sys_acl_valid(SMB_ACL_T acl_d)
 1699: {
 1700: 	return acl_valid(acl_d->aclp);
 1701: }
 1702: 
 1703: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 1704: {
 1705: 	return acl_set_file(name, type, acl_d->aclp);
 1706: }
 1707: 
 1708: #if 0
 1709: int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
 1710: {
 1711: 	return acl_set_fd(fd, acl_d->aclp);
 1712: }
 1713: #endif
 1714: 
 1715: int sys_acl_delete_def_file(const char *name)
 1716: {
 1717: 	return acl_delete_def_file(name);
 1718: }
 1719: 
 1720: int sys_acl_free_acl(SMB_ACL_T acl_d) 
 1721: {
 1722: 	if (acl_d->freeaclp) {
 1723: 		acl_free(acl_d->aclp);
 1724: 	}
 1725: 	acl_free(acl_d);
 1726: 	return 0;
 1727: }
 1728: 
 1729: #elif defined(HAVE_AIX_ACLS) /*----------------------------------------------*/
 1730: 
 1731: /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
 1732: 
 1733: int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
 1734: {
 1735: 	struct acl_entry_link *link;
 1736: 	struct new_acl_entry *entry;
 1737: 	int keep_going;
 1738: 
 1739: 	if (entry_id == SMB_ACL_FIRST_ENTRY)
 1740: 		theacl->count = 0;
 1741: 	else if (entry_id != SMB_ACL_NEXT_ENTRY) {
 1742: 		errno = EINVAL;
 1743: 		return -1;
 1744: 	}
 1745: 
 1746: 	DEBUG(10,("This is the count: %d\n",theacl->count));
 1747: 
 1748: 	/* Check if count was previously set to -1. *
 1749: 	 * If it was, that means we reached the end *
 1750: 	 * of the acl last time.                    */
 1751: 	if(theacl->count == -1)
 1752: 		return(0);
 1753: 
 1754: 	link = theacl;
 1755: 	/* To get to the next acl, traverse linked list until index *
 1756: 	 * of acl matches the count we are keeping.  This count is  *
 1757: 	 * incremented each time we return an acl entry.            */
 1758: 
 1759: 	for(keep_going = 0; keep_going < theacl->count; keep_going++)
 1760: 		link = link->nextp;
 1761: 
 1762: 	entry = *entry_p =  link->entryp;
 1763: 
 1764: 	DEBUG(10,("*entry_p is %d\n",entry_p));
 1765: 	DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
 1766: 
 1767: 	/* Increment count */
 1768: 	theacl->count++;
 1769: 	if(link->nextp == NULL)
 1770: 		theacl->count = -1;
 1771: 
 1772: 	return(1);
 1773: }
 1774: 
 1775: int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
 1776: {
 1777: 	/* Initialize tag type */
 1778: 
 1779: 	*tag_type_p = -1;
 1780: 	DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
 1781: 
 1782: 	/* Depending on what type of entry we have, *
 1783: 	 * return tag type.                         */
 1784: 	switch(entry_d->ace_id->id_type) {
 1785: 	case ACEID_USER:
 1786: 		*tag_type_p = SMB_ACL_USER;
 1787: 		break;
 1788: 	case ACEID_GROUP:
 1789: 		*tag_type_p = SMB_ACL_GROUP;
 1790: 		break;
 1791: 
 1792: 	case SMB_ACL_USER_OBJ:
 1793: 	case SMB_ACL_GROUP_OBJ:
 1794: 	case SMB_ACL_OTHER:
 1795: 		*tag_type_p = entry_d->ace_id->id_type;
 1796: 		break;
 1797: 
 1798: 	default:
 1799: 		return(-1);
 1800: 	}
 1801: 
 1802: 	return(0);
 1803: }
 1804: 
 1805: SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
 1806: {
 1807: 	struct acl *file_acl = (struct acl *)NULL;
 1808: 	struct acl_entry *acl_entry;
 1809: 	struct new_acl_entry *new_acl_entry;
 1810: 	struct ace_id *idp;
 1811: 	struct acl_entry_link *acl_entry_link;
 1812: 	struct acl_entry_link *acl_entry_link_head;
 1813: 	int i;
 1814: 	int rc = 0;
 1815: 
 1816: 	/* AIX has no DEFAULT */
 1817: 	if  ( type == SMB_ACL_TYPE_DEFAULT ) {
 1818: #ifdef ENOTSUP
 1819: 		errno = ENOTSUP;
 1820: #else
 1821: 		errno = ENOSYS;
 1822: #endif
 1823: 		return NULL;
 1824: 	}
 1825: 
 1826: 	/* Get the acl using statacl */
 1827:  
 1828: 	DEBUG(10,("Entering sys_acl_get_file\n"));
 1829: 	DEBUG(10,("path_p is %s\n",path_p));
 1830: 
 1831: 	file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
 1832:  
 1833: 	if(file_acl == NULL) {
 1834: 		errno=ENOMEM;
 1835: 		DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
 1836: 		return(NULL);
 1837: 	}
 1838: 
 1839: 	memset(file_acl,0,BUFSIZ);
 1840: 
 1841: 	rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
 1842: 	if(rc == -1) {
 1843: 		DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
 1844: 		SAFE_FREE(file_acl);
 1845: 		return(NULL);
 1846: 	}
 1847: 
 1848: 	DEBUG(10,("Got facl and returned it\n"));
 1849: 
 1850: 	/* Point to the first acl entry in the acl */
 1851: 	acl_entry =  file_acl->acl_ext;
 1852: 
 1853: 	/* Begin setting up the head of the linked list *
 1854: 	 * that will be used for the storing the acl    *
 1855: 	 * in a way that is useful for the posix_acls.c *
 1856: 	 * code.                                          */
 1857: 
 1858: 	acl_entry_link_head = acl_entry_link = sys_acl_init(0);
 1859: 	if(acl_entry_link_head == NULL)
 1860: 		return(NULL);
 1861: 
 1862: 	acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 1863: 	if(acl_entry_link->entryp == NULL) {
 1864: 		SAFE_FREE(file_acl);
 1865: 		errno = ENOMEM;
 1866: 		DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
 1867: 		return(NULL);
 1868: 	}
 1869: 
 1870: 	DEBUG(10,("acl_entry is %d\n",acl_entry));
 1871: 	DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
 1872: 
 1873: 	/* Check if the extended acl bit is on.   *
 1874: 	 * If it isn't, do not show the           *
 1875: 	 * contents of the acl since AIX intends *
 1876: 	 * the extended info to remain unused     */
 1877: 
 1878: 	if(file_acl->acl_mode & S_IXACL){
 1879: 		/* while we are not pointing to the very end */
 1880: 		while(acl_entry < acl_last(file_acl)) {
 1881: 			/* before we malloc anything, make sure this is  */
 1882: 			/* a valid acl entry and one that we want to map */
 1883: 			idp = id_nxt(acl_entry->ace_id);
 1884: 			if((acl_entry->ace_type == ACC_SPECIFY ||
 1885: 				(acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
 1886: 					acl_entry = acl_nxt(acl_entry);
 1887: 					continue;
 1888: 			}
 1889: 
 1890: 			idp = acl_entry->ace_id;
 1891: 
 1892: 			/* Check if this is the first entry in the linked list. *
 1893: 			 * The first entry needs to keep prevp pointing to NULL *
 1894: 			 * and already has entryp allocated.                  */
 1895: 
 1896: 			if(acl_entry_link_head->count != 0) {
 1897: 				acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
 1898: 
 1899: 				if(acl_entry_link->nextp == NULL) {
 1900: 					SAFE_FREE(file_acl);
 1901: 					errno = ENOMEM;
 1902: 					DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
 1903: 					return(NULL);
 1904: 				}
 1905: 
 1906: 				acl_entry_link->nextp->prevp = acl_entry_link;
 1907: 				acl_entry_link = acl_entry_link->nextp;
 1908: 				acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 1909: 				if(acl_entry_link->entryp == NULL) {
 1910: 					SAFE_FREE(file_acl);
 1911: 					errno = ENOMEM;
 1912: 					DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
 1913: 					return(NULL);
 1914: 				}
 1915: 				acl_entry_link->nextp = NULL;
 1916: 			}
 1917: 
 1918: 			acl_entry_link->entryp->ace_len = acl_entry->ace_len;
 1919: 
 1920: 			/* Don't really need this since all types are going *
 1921: 			 * to be specified but, it's better than leaving it 0 */
 1922: 
 1923: 			acl_entry_link->entryp->ace_type = acl_entry->ace_type;
 1924:  
 1925: 			acl_entry_link->entryp->ace_access = acl_entry->ace_access;
 1926:  
 1927: 			memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
 1928: 
 1929: 			/* The access in the acl entries must be left shifted by *
 1930: 			 * three bites, because they will ultimately be compared *
 1931: 			 * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
 1932: 
 1933: 			switch(acl_entry->ace_type){
 1934: 			case ACC_PERMIT:
 1935: 			case ACC_SPECIFY:
 1936: 				acl_entry_link->entryp->ace_access = acl_entry->ace_access;
 1937: 				acl_entry_link->entryp->ace_access <<= 6;
 1938: 				acl_entry_link_head->count++;
 1939: 				break;
 1940: 			case ACC_DENY:
 1941: 				/* Since there is no way to return a DENY acl entry *
 1942: 				 * change to PERMIT and then shift.                 */
 1943: 				DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
 1944: 				acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
 1945: 				DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
 1946: 				acl_entry_link->entryp->ace_access <<= 6;
 1947: 				acl_entry_link_head->count++;
 1948: 				break;
 1949: 			default:
 1950: 				return(0);
 1951: 			}
 1952: 
 1953: 			DEBUG(10,("acl_entry = %d\n",acl_entry));
 1954: 			DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
 1955:  
 1956: 			acl_entry = acl_nxt(acl_entry);
 1957: 		}
 1958: 	} /* end of if enabled */
 1959: 
 1960: 	/* Since owner, group, other acl entries are not *
 1961: 	 * part of the acl entries in an acl, they must  *
 1962: 	 * be dummied up to become part of the list.     */
 1963: 
 1964: 	for( i = 1; i < 4; i++) {
 1965: 		DEBUG(10,("i is %d\n",i));
 1966: 		if(acl_entry_link_head->count != 0) {
 1967: 			acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
 1968: 			if(acl_entry_link->nextp == NULL) {
 1969: 				SAFE_FREE(file_acl);
 1970: 				errno = ENOMEM;
 1971: 				DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
 1972: 				return(NULL);
 1973: 			}
 1974: 
 1975: 			acl_entry_link->nextp->prevp = acl_entry_link;
 1976: 			acl_entry_link = acl_entry_link->nextp;
 1977: 			acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 1978: 			if(acl_entry_link->entryp == NULL) {
 1979: 				SAFE_FREE(file_acl);
 1980: 				errno = ENOMEM;
 1981: 				DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
 1982: 				return(NULL);
 1983: 			}
 1984: 		}
 1985: 
 1986: 		acl_entry_link->nextp = NULL;
 1987: 
 1988: 		new_acl_entry = acl_entry_link->entryp;
 1989: 		idp = new_acl_entry->ace_id;
 1990: 
 1991: 		new_acl_entry->ace_len = sizeof(struct acl_entry);
 1992: 		new_acl_entry->ace_type = ACC_PERMIT;
 1993: 		idp->id_len = sizeof(struct ace_id);
 1994: 		DEBUG(10,("idp->id_len = %d\n",idp->id_len));
 1995: 		memset(idp->id_data,0,sizeof(uid_t));
 1996: 
 1997: 		switch(i) {
 1998: 		case 2:
 1999: 			new_acl_entry->ace_access = file_acl->g_access << 6;
 2000: 			idp->id_type = SMB_ACL_GROUP_OBJ;
 2001: 			break;
 2002: 
 2003: 		case 3:
 2004: 			new_acl_entry->ace_access = file_acl->o_access << 6;
 2005: 			idp->id_type = SMB_ACL_OTHER;
 2006: 			break;
 2007:  
 2008: 		case 1:
 2009: 			new_acl_entry->ace_access = file_acl->u_access << 6;
 2010: 			idp->id_type = SMB_ACL_USER_OBJ;
 2011: 			break;
 2012:  
 2013: 		default:
 2014: 			return(NULL);
 2015: 
 2016: 		}
 2017: 
 2018: 		acl_entry_link_head->count++;
 2019: 		DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
 2020: 	}
 2021: 
 2022: 	acl_entry_link_head->count = 0;
 2023: 	SAFE_FREE(file_acl);
 2024: 
 2025: 	return(acl_entry_link_head);
 2026: }
 2027: 
 2028: #if 0
 2029: SMB_ACL_T sys_acl_get_fd(int fd)
 2030: {
 2031: 	struct acl *file_acl = (struct acl *)NULL;
 2032: 	struct acl_entry *acl_entry;
 2033: 	struct new_acl_entry *new_acl_entry;
 2034: 	struct ace_id *idp;
 2035: 	struct acl_entry_link *acl_entry_link;
 2036: 	struct acl_entry_link *acl_entry_link_head;
 2037: 	int i;
 2038: 	int rc = 0;
 2039: 
 2040: 	/* Get the acl using fstatacl */
 2041:    
 2042: 	DEBUG(10,("Entering sys_acl_get_fd\n"));
 2043: 	DEBUG(10,("fd is %d\n",fd));
 2044: 	file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
 2045: 
 2046: 	if(file_acl == NULL) {
 2047: 		errno=ENOMEM;
 2048: 		DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2049: 		return(NULL);
 2050: 	}
 2051: 
 2052: 	memset(file_acl,0,BUFSIZ);
 2053: 
 2054: 	rc = fstatacl(fd,0,file_acl,BUFSIZ);
 2055: 	if(rc == -1) {
 2056: 		DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
 2057: 		SAFE_FREE(file_acl);
 2058: 		return(NULL);
 2059: 	}
 2060: 
 2061: 	DEBUG(10,("Got facl and returned it\n"));
 2062: 
 2063: 	/* Point to the first acl entry in the acl */
 2064: 
 2065: 	acl_entry =  file_acl->acl_ext;
 2066: 	/* Begin setting up the head of the linked list *
 2067: 	 * that will be used for the storing the acl    *
 2068: 	 * in a way that is useful for the posix_acls.c *
 2069: 	 * code.                                        */
 2070: 
 2071: 	acl_entry_link_head = acl_entry_link = sys_acl_init(0);
 2072: 	if(acl_entry_link_head == NULL){
 2073: 		SAFE_FREE(file_acl);
 2074: 		return(NULL);
 2075: 	}
 2076: 
 2077: 	acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 2078: 
 2079: 	if(acl_entry_link->entryp == NULL) {
 2080: 		errno = ENOMEM;
 2081: 		DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2082: 		SAFE_FREE(file_acl);
 2083: 		return(NULL);
 2084: 	}
 2085: 
 2086: 	DEBUG(10,("acl_entry is %d\n",acl_entry));
 2087: 	DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
 2088:  
 2089: 	/* Check if the extended acl bit is on.   *
 2090: 	 * If it isn't, do not show the           *
 2091: 	 * contents of the acl since AIX intends  *
 2092: 	 * the extended info to remain unused     */
 2093:  
 2094: 	if(file_acl->acl_mode & S_IXACL){
 2095: 		/* while we are not pointing to the very end */
 2096: 		while(acl_entry < acl_last(file_acl)) {
 2097: 			/* before we malloc anything, make sure this is  */
 2098: 			/* a valid acl entry and one that we want to map */
 2099: 
 2100: 			idp = id_nxt(acl_entry->ace_id);
 2101: 			if((acl_entry->ace_type == ACC_SPECIFY ||
 2102: 				(acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
 2103: 					acl_entry = acl_nxt(acl_entry);
 2104: 					continue;
 2105: 			}
 2106: 
 2107: 			idp = acl_entry->ace_id;
 2108:  
 2109: 			/* Check if this is the first entry in the linked list. *
 2110: 			 * The first entry needs to keep prevp pointing to NULL *
 2111: 			 * and already has entryp allocated.                 */
 2112: 
 2113: 			if(acl_entry_link_head->count != 0) {
 2114: 				acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
 2115: 				if(acl_entry_link->nextp == NULL) {
 2116: 					errno = ENOMEM;
 2117: 					DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2118: 					SAFE_FREE(file_acl);
 2119: 					return(NULL);
 2120: 				}
 2121: 				acl_entry_link->nextp->prevp = acl_entry_link;
 2122: 				acl_entry_link = acl_entry_link->nextp;
 2123: 				acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 2124: 				if(acl_entry_link->entryp == NULL) {
 2125: 					errno = ENOMEM;
 2126: 					DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2127: 					SAFE_FREE(file_acl);
 2128: 					return(NULL);
 2129: 				}
 2130: 
 2131: 				acl_entry_link->nextp = NULL;
 2132: 			}
 2133: 
 2134: 			acl_entry_link->entryp->ace_len = acl_entry->ace_len;
 2135: 
 2136: 			/* Don't really need this since all types are going *
 2137: 			 * to be specified but, it's better than leaving it 0 */
 2138: 
 2139: 			acl_entry_link->entryp->ace_type = acl_entry->ace_type;
 2140: 			acl_entry_link->entryp->ace_access = acl_entry->ace_access;
 2141: 
 2142: 			memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
 2143: 
 2144: 			/* The access in the acl entries must be left shifted by *
 2145: 			 * three bites, because they will ultimately be compared *
 2146: 			 * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
 2147: 
 2148: 			switch(acl_entry->ace_type){
 2149: 			case ACC_PERMIT:
 2150: 			case ACC_SPECIFY:
 2151: 				acl_entry_link->entryp->ace_access = acl_entry->ace_access;
 2152: 				acl_entry_link->entryp->ace_access <<= 6;
 2153: 				acl_entry_link_head->count++;
 2154: 				break;
 2155: 			case ACC_DENY:
 2156: 				/* Since there is no way to return a DENY acl entry *
 2157: 				 * change to PERMIT and then shift.                 */
 2158: 				DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
 2159: 				acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
 2160: 				DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
 2161: 				acl_entry_link->entryp->ace_access <<= 6;
 2162: 				acl_entry_link_head->count++;
 2163: 				break;
 2164: 			default:
 2165: 				return(0);
 2166: 			}
 2167: 
 2168: 			DEBUG(10,("acl_entry = %d\n",acl_entry));
 2169: 			DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
 2170:  
 2171: 			acl_entry = acl_nxt(acl_entry);
 2172: 		}
 2173: 	} /* end of if enabled */
 2174: 
 2175: 	/* Since owner, group, other acl entries are not *
 2176: 	 * part of the acl entries in an acl, they must  *
 2177: 	 * be dummied up to become part of the list.     */
 2178: 
 2179: 	for( i = 1; i < 4; i++) {
 2180: 		DEBUG(10,("i is %d\n",i));
 2181: 		if(acl_entry_link_head->count != 0){
 2182: 			acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
 2183: 			if(acl_entry_link->nextp == NULL) {
 2184: 				errno = ENOMEM;
 2185: 				DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2186: 				SAFE_FREE(file_acl);
 2187: 				return(NULL);
 2188: 			}
 2189: 
 2190: 			acl_entry_link->nextp->prevp = acl_entry_link;
 2191: 			acl_entry_link = acl_entry_link->nextp;
 2192: 			acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
 2193: 
 2194: 			if(acl_entry_link->entryp == NULL) {
 2195: 				SAFE_FREE(file_acl);
 2196: 				errno = ENOMEM;
 2197: 				DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
 2198: 				return(NULL);
 2199: 			}
 2200: 		}
 2201: 
 2202: 		acl_entry_link->nextp = NULL;
 2203:  
 2204: 		new_acl_entry = acl_entry_link->entryp;
 2205: 		idp = new_acl_entry->ace_id;
 2206:  
 2207: 		new_acl_entry->ace_len = sizeof(struct acl_entry);
 2208: 		new_acl_entry->ace_type = ACC_PERMIT;
 2209: 		idp->id_len = sizeof(struct ace_id);
 2210: 		DEBUG(10,("idp->id_len = %d\n",idp->id_len));
 2211: 		memset(idp->id_data,0,sizeof(uid_t));
 2212:  
 2213: 		switch(i) {
 2214: 		case 2:
 2215: 			new_acl_entry->ace_access = file_acl->g_access << 6;
 2216: 			idp->id_type = SMB_ACL_GROUP_OBJ;
 2217: 			break;
 2218:  
 2219: 		case 3:
 2220: 			new_acl_entry->ace_access = file_acl->o_access << 6;
 2221: 			idp->id_type = SMB_ACL_OTHER;
 2222: 			break;
 2223:  
 2224: 		case 1:
 2225: 			new_acl_entry->ace_access = file_acl->u_access << 6;
 2226: 			idp->id_type = SMB_ACL_USER_OBJ;
 2227: 			break;
 2228:  
 2229: 		default:
 2230: 			return(NULL);
 2231: 		}
 2232:  
 2233: 		acl_entry_link_head->count++;
 2234: 		DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
 2235: 	}
 2236: 
 2237: 	acl_entry_link_head->count = 0;
 2238: 	SAFE_FREE(file_acl);
 2239:  
 2240: 	return(acl_entry_link_head);
 2241: }
 2242: #endif
 2243: 
 2244: 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)
 2245: {
 2246: 	uint *permset;
 2247: 
 2248: 	if (sys_acl_get_tag_type(entry, tag_type_p) != 0)
 2249: 		return -1;
 2250: 
 2251: 	if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
 2252: 		memcpy(u_g_id_p, entry->ace_id->id_data, sizeof (id_t));
 2253: 
 2254: 	permset = &entry->ace_access;
 2255: 
 2256: 	DEBUG(10,("*permset is %d\n",*permset));
 2257: 	*bits_p = (*permset & S_IRUSR ? 4 : 0)
 2258: 		| (*permset & S_IWUSR ? 2 : 0)
 2259: 		| (*permset & S_IXUSR ? 1 : 0);
 2260: 
 2261: 	return 0;
 2262: }
 2263: 
 2264: SMB_ACL_T sys_acl_init( int count)
 2265: {
 2266: 	struct acl_entry_link *theacl = NULL;
 2267:  
 2268: 	if (count < 0) {
 2269: 		errno = EINVAL;
 2270: 		return NULL;
 2271: 	}
 2272: 
 2273: 	DEBUG(10,("Entering sys_acl_init\n"));
 2274: 
 2275: 	theacl = SMB_MALLOC_P(struct acl_entry_link);
 2276: 	if(theacl == NULL) {
 2277: 		errno = ENOMEM;
 2278: 		DEBUG(0,("Error in sys_acl_init is %d\n",errno));
 2279: 		return(NULL);
 2280: 	}
 2281: 
 2282: 	theacl->count = 0;
 2283: 	theacl->nextp = NULL;
 2284: 	theacl->prevp = NULL;
 2285: 	theacl->entryp = NULL;
 2286: 	DEBUG(10,("Exiting sys_acl_init\n"));
 2287: 	return(theacl);
 2288: }
 2289: 
 2290: int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
 2291: {
 2292: 	struct acl_entry_link *theacl;
 2293: 	struct acl_entry_link *acl_entryp;
 2294: 	struct acl_entry_link *temp_entry;
 2295: 	int counting;
 2296: 
 2297: 	DEBUG(10,("Entering the sys_acl_create_entry\n"));
 2298: 
 2299: 	theacl = acl_entryp = *pacl;
 2300: 
 2301: 	/* Get to the end of the acl before adding entry */
 2302: 
 2303: 	for(counting=0; counting < theacl->count; counting++){
 2304: 		DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
 2305: 		temp_entry = acl_entryp;
 2306: 		acl_entryp = acl_entryp->nextp;
 2307: 	}
 2308: 
 2309: 	if(theacl->count != 0){
 2310: 		temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
 2311: 		if(acl_entryp == NULL) {
 2312: 			errno = ENOMEM;
 2313: 			DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
 2314: 			return(-1);
 2315: 		}
 2316: 
 2317: 		DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
 2318: 		acl_entryp->prevp = temp_entry;
 2319: 		DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
 2320: 	}
 2321: 
 2322: 	*pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
 2323: 	if(*pentry == NULL) {
 2324: 		errno = ENOMEM;
 2325: 		DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
 2326: 		return(-1);
 2327: 	}
 2328: 
 2329: 	memset(*pentry,0,sizeof(struct new_acl_entry));
 2330: 	acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
 2331: 	acl_entryp->entryp->ace_type = ACC_PERMIT;
 2332: 	acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
 2333: 	acl_entryp->nextp = NULL;
 2334: 	theacl->count++;
 2335: 	DEBUG(10,("Exiting sys_acl_create_entry\n"));
 2336: 	return(0);
 2337: }
 2338: 
 2339: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
 2340: {
 2341: 	entry->ace_id->id_type = tag_type;
 2342: 	DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
 2343: 
 2344: 	if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
 2345: 		memcpy(entry->ace_id->id_data, &u_g_id, sizeof (id_t));
 2346: 
 2347: 	entry->ace_access = bits;
 2348: 	DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
 2349: 
 2350: 	return 0;
 2351: }
 2352: 
 2353: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
 2354: {
 2355: 	DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
 2356: 	entry->ace_access = bits;
 2357: 	DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
 2358: 	DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
 2359: 	return(0);
 2360: }
 2361: 
 2362: int sys_acl_valid( SMB_ACL_T theacl )
 2363: {
 2364: 	int user_obj = 0;
 2365: 	int group_obj = 0;
 2366: 	int other_obj = 0;
 2367: 	struct acl_entry_link *acl_entry;
 2368: 
 2369: 	for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
 2370: 		user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
 2371: 		group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
 2372: 		other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
 2373: 	}
 2374: 
 2375: 	DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
 2376:  
 2377: 	if(user_obj != 1 || group_obj != 1 || other_obj != 1)
 2378: 		return(-1); 
 2379: 
 2380: 	return(0);
 2381: }
 2382: 
 2383: int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
 2384: {
 2385: 	struct acl_entry_link *acl_entry_link = NULL;
 2386: 	struct acl *file_acl = NULL;
 2387: 	struct acl *file_acl_temp = NULL;
 2388: 	struct acl_entry *acl_entry = NULL;
 2389: 	struct ace_id *ace_id = NULL;
 2390: 	uint id_type;
 2391: 	uint user_id;
 2392: 	uint acl_length;
 2393: 	uint rc;
 2394: 
 2395: 	DEBUG(10,("Entering sys_acl_set_file\n"));
 2396: 	DEBUG(10,("File name is %s\n",name));
 2397:  
 2398: 	/* AIX has no default ACL */
 2399: 	if(acltype == SMB_ACL_TYPE_DEFAULT)
 2400: 		return(0);
 2401: 
 2402: 	acl_length = BUFSIZ;
 2403: 	file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
 2404: 
 2405: 	if(file_acl == NULL) {
 2406: 		errno = ENOMEM;
 2407: 		DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
 2408: 		return(-1);
 2409: 	}
 2410: 
 2411: 	memset(file_acl,0,BUFSIZ);
 2412: 
 2413: 	file_acl->acl_len = ACL_SIZ;
 2414: 	file_acl->acl_mode = S_IXACL;
 2415: 
 2416: 	for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
 2417: 		acl_entry_link->entryp->ace_access >>= 6;
 2418: 		id_type = acl_entry_link->entryp->ace_id->id_type;
 2419: 
 2420: 		switch(id_type) {
 2421: 		case SMB_ACL_USER_OBJ:
 2422: 			file_acl->u_access = acl_entry_link->entryp->ace_access;
 2423: 			continue;
 2424: 		case SMB_ACL_GROUP_OBJ:
 2425: 			file_acl->g_access = acl_entry_link->entryp->ace_access;
 2426: 			continue;
 2427: 		case SMB_ACL_OTHER:
 2428: 			file_acl->o_access = acl_entry_link->entryp->ace_access;
 2429: 			continue;
 2430: 		case SMB_ACL_MASK:
 2431: 			continue;
 2432: 		}
 2433: 
 2434: 		if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
 2435: 			acl_length += sizeof(struct acl_entry);
 2436: 			file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
 2437: 			if(file_acl_temp == NULL) {
 2438: 				SAFE_FREE(file_acl);
 2439: 				errno = ENOMEM;
 2440: 				DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
 2441: 				return(-1);
 2442: 			}  
 2443: 
 2444: 			memcpy(file_acl_temp,file_acl,file_acl->acl_len);
 2445: 			SAFE_FREE(file_acl);
 2446: 			file_acl = file_acl_temp;
 2447: 		}
 2448: 
 2449: 		acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
 2450: 		file_acl->acl_len += sizeof(struct acl_entry);
 2451: 		acl_entry->ace_len = acl_entry_link->entryp->ace_len;
 2452: 		acl_entry->ace_access = acl_entry_link->entryp->ace_access;
 2453:  
 2454: 		/* In order to use this, we'll need to wait until we can get denies */
 2455: 		/* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
 2456: 		acl_entry->ace_type = ACC_SPECIFY; */
 2457: 
 2458: 		acl_entry->ace_type = ACC_SPECIFY;
 2459:  
 2460: 		ace_id = acl_entry->ace_id;
 2461:  
 2462: 		ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
 2463: 		DEBUG(10,("The id type is %d\n",ace_id->id_type));
 2464: 		ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
 2465: 		memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
 2466: 		memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
 2467: 	}
 2468: 
 2469: 	rc = chacl((char*)name,file_acl,file_acl->acl_len);
 2470: 	DEBUG(10,("errno is %d\n",errno));
 2471: 	DEBUG(10,("return code is %d\n",rc));
 2472: 	SAFE_FREE(file_acl);
 2473: 	DEBUG(10,("Exiting the sys_acl_set_file\n"));
 2474: 	return(rc);
 2475: }
 2476: 
 2477: #if 0
 2478: int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
 2479: {
 2480: 	struct acl_entry_link *acl_entry_link = NULL;
 2481: 	struct acl *file_acl = NULL;
 2482: 	struct acl *file_acl_temp = NULL;
 2483: 	struct acl_entry *acl_entry = NULL;
 2484: 	struct ace_id *ace_id = NULL;
 2485: 	uint id_type;
 2486: 	uint user_id;
 2487: 	uint acl_length;
 2488: 	uint rc;
 2489:  
 2490: 	DEBUG(10,("Entering sys_acl_set_fd\n"));
 2491: 	acl_length = BUFSIZ;
 2492: 	file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
 2493: 
 2494: 	if(file_acl == NULL) {
 2495: 		errno = ENOMEM;
 2496: 		DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
 2497: 		return(-1);
 2498: 	}
 2499: 
 2500: 	memset(file_acl,0,BUFSIZ);
 2501:  
 2502: 	file_acl->acl_len = ACL_SIZ;
 2503: 	file_acl->acl_mode = S_IXACL;
 2504: 
 2505: 	for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
 2506: 		acl_entry_link->entryp->ace_access >>= 6;
 2507: 		id_type = acl_entry_link->entryp->ace_id->id_type;
 2508: 		DEBUG(10,("The id_type is %d\n",id_type));
 2509: 
 2510: 		switch(id_type) {
 2511: 		case SMB_ACL_USER_OBJ:
 2512: 			file_acl->u_access = acl_entry_link->entryp->ace_access;
 2513: 			continue;
 2514: 		case SMB_ACL_GROUP_OBJ:
 2515: 			file_acl->g_access = acl_entry_link->entryp->ace_access;
 2516: 			continue;
 2517: 		case SMB_ACL_OTHER:
 2518: 			file_acl->o_access = acl_entry_link->entryp->ace_access;
 2519: 			continue;
 2520: 		case SMB_ACL_MASK:
 2521: 			continue;
 2522: 		}
 2523: 
 2524: 		if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
 2525: 			acl_length += sizeof(struct acl_entry);
 2526: 			file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
 2527: 			if(file_acl_temp == NULL) {
 2528: 				SAFE_FREE(file_acl);
 2529: 				errno = ENOMEM;
 2530: 				DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
 2531: 				return(-1);
 2532: 			}
 2533: 
 2534: 			memcpy(file_acl_temp,file_acl,file_acl->acl_len);
 2535: 			SAFE_FREE(file_acl);
 2536: 			file_acl = file_acl_temp;
 2537: 		}
 2538: 
 2539: 		acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
 2540: 		file_acl->acl_len += sizeof(struct acl_entry);
 2541: 		acl_entry->ace_len = acl_entry_link->entryp->ace_len;
 2542: 		acl_entry->ace_access = acl_entry_link->entryp->ace_access;
 2543:  
 2544: 		/* In order to use this, we'll need to wait until we can get denies */
 2545: 		/* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
 2546: 			acl_entry->ace_type = ACC_SPECIFY; */
 2547:  
 2548: 		acl_entry->ace_type = ACC_SPECIFY;
 2549:  
 2550: 		ace_id = acl_entry->ace_id;
 2551:  
 2552: 		ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
 2553: 		DEBUG(10,("The id type is %d\n",ace_id->id_type));
 2554: 		ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
 2555: 		memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
 2556: 		memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
 2557: 	}
 2558:  
 2559: 	rc = fchacl(fd,file_acl,file_acl->acl_len);
 2560: 	DEBUG(10,("errno is %d\n",errno));
 2561: 	DEBUG(10,("return code is %d\n",rc));
 2562: 	SAFE_FREE(file_acl);
 2563: 	DEBUG(10,("Exiting sys_acl_set_fd\n"));
 2564: 	return(rc);
 2565: }
 2566: #endif
 2567: 
 2568: int sys_acl_delete_def_file(UNUSED(const char *name))
 2569: {
 2570: 	/* AIX has no default ACL */
 2571: 	return 0;
 2572: }
 2573: 
 2574: int sys_acl_free_acl(SMB_ACL_T posix_acl)
 2575: {
 2576: 	struct acl_entry_link *acl_entry_link;
 2577: 
 2578: 	for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
 2579: 		SAFE_FREE(acl_entry_link->prevp->entryp);
 2580: 		SAFE_FREE(acl_entry_link->prevp);
 2581: 	}
 2582: 
 2583: 	SAFE_FREE(acl_entry_link->prevp->entryp);
 2584: 	SAFE_FREE(acl_entry_link->prevp);
 2585: 	SAFE_FREE(acl_entry_link->entryp);
 2586: 	SAFE_FREE(acl_entry_link);
 2587:  
 2588: 	return(0);
 2589: }
 2590: 
 2591: #elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
 2592: 
 2593: #define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
 2594: 
 2595: #include <membership.h>
 2596: 
 2597: int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
 2598: {
 2599: 	int ret = acl_get_entry(the_acl, entry_id, entry_p);
 2600: #ifdef OSX_BROKEN_GETENTRY
 2601: 	if (ret == 0)
 2602: 		ret = 1;
 2603: 	else if (ret == -1 && errno == 22)
 2604: 		ret = 0;
 2605: #endif
 2606: 	return ret;
 2607: }
 2608: 
 2609: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
 2610: {
 2611: 	if (type == ACL_TYPE_DEFAULT) {
 2612: 		errno = ENOTSUP;
 2613: 		return NULL;
 2614: 	}
 2615: 	errno = 0;
 2616: 	return acl_get_file(path_p, type);
 2617: }
 2618: 
 2619: #if 0
 2620: SMB_ACL_T sys_acl_get_fd(int fd)
 2621: {
 2622: 	return acl_get_fd(fd);
 2623: }
 2624: #endif
 2625: 
 2626: 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)
 2627: {
 2628: 	uuid_t *uup;
 2629: 	acl_tag_t tag;
 2630: 	acl_flagset_t flagset;
 2631: 	acl_permset_t permset;
 2632: 	uint32 bits, fb, bb, pb;
 2633: 	int id_type = -1;
 2634: 	int rc;
 2635: 
 2636: 	if (acl_get_tag_type(entry, &tag) != 0
 2637: 	 || acl_get_flagset_np(entry, &flagset) != 0
 2638: 	 || acl_get_permset(entry, &permset) != 0
 2639: 	 || (uup = acl_get_qualifier(entry)) == NULL)
 2640: 		return -1;
 2641: 
 2642: 	rc = mbr_uuid_to_id(*uup, u_g_id_p, &id_type);
 2643: 	acl_free(uup);
 2644: 	if (rc != 0)
 2645: 		return rc;
 2646: 
 2647: 	if (id_type == ID_TYPE_UID)
 2648: 		*tag_type_p = SMB_ACL_USER;
 2649: 	else
 2650: 		*tag_type_p = SMB_ACL_GROUP;
 2651: 
 2652: 	bits = tag == ACL_EXTENDED_ALLOW ? 1 : 0;
 2653: 
 2654: 	for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
 2655: 		if (acl_get_flag_np(flagset, fb) == 1)
 2656: 			bits |= bb;
 2657: 	}
 2658: 
 2659: 	for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
 2660: 		if (acl_get_perm_np(permset, pb) == 1)
 2661: 			bits |= bb;
 2662: 	}
 2663: 
 2664: 	*bits_p = bits;
 2665: 
 2666: 	return 0;
 2667: }
 2668: 
 2669: SMB_ACL_T sys_acl_init(int count)
 2670: {
 2671: 	return acl_init(count);
 2672: }
 2673: 
 2674: int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
 2675: {
 2676: 	return acl_create_entry(pacl, pentry);
 2677: }
 2678: 
 2679: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
 2680: {
 2681: 	acl_flagset_t flagset;
 2682: 	acl_permset_t permset;
 2683: 	uint32 fb, bb, pb;
 2684: 	int is_user = tag_type == SMB_ACL_USER;
 2685: 	uuid_t uu;
 2686: 	int rc;
 2687: 
 2688: 	tag_type = bits & 1 ? ACL_EXTENDED_ALLOW : ACL_EXTENDED_DENY;
 2689: 
 2690: 	if (acl_get_flagset_np(entry, &flagset) != 0
 2691: 	 || acl_get_permset(entry, &permset) != 0)
 2692: 		return -1;
 2693: 
 2694: 	acl_clear_flags_np(flagset);
 2695: 	acl_clear_perms(permset);
 2696: 
 2697: 	for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
 2698: 		if (bits & bb)
 2699: 			acl_add_flag_np(flagset, fb);
 2700: 	}
 2701: 
 2702: 	for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
 2703: 		if (bits & bb)
 2704: 			acl_add_perm(permset, pb);
 2705: 	}
 2706: 
 2707: 	if (is_user)
 2708: 		rc = mbr_uid_to_uuid(u_g_id, uu);
 2709: 	else
 2710: 		rc = mbr_gid_to_uuid(u_g_id, uu);
 2711: 	if (rc != 0)
 2712: 		return rc;
 2713: 
 2714: 	if (acl_set_tag_type(entry, tag_type) != 0
 2715: 	 || acl_set_qualifier(entry, &uu) != 0
 2716: 	 || acl_set_permset(entry, permset) != 0
 2717: 	 || acl_set_flagset_np(entry, flagset) != 0)
 2718: 		return -1;
 2719: 
 2720: 	return 0;
 2721: }
 2722: 
 2723: #if 0
 2724: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
 2725: {
 2726: 	return -1; /* Not needed for OS X. */
 2727: }
 2728: #endif
 2729: 
 2730: int sys_acl_valid(SMB_ACL_T theacl)
 2731: {
 2732: 	return acl_valid(theacl);
 2733: }
 2734: 
 2735: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
 2736: {
 2737: 	return acl_set_file(name, acltype, theacl);
 2738: }
 2739: 
 2740: #if 0
 2741: int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
 2742: {
 2743: 	return acl_set_fd(fd, theacl);
 2744: }
 2745: #endif
 2746: 
 2747: int sys_acl_delete_def_file(const char *name)
 2748: {
 2749: 	return acl_delete_def_file(name);
 2750: }
 2751: 
 2752: int sys_acl_free_acl(SMB_ACL_T the_acl)
 2753: {
 2754: 	return acl_free(the_acl);
 2755: }
 2756: 
 2757: #else /* No ACLs. */
 2758: 
 2759: #error No ACL functions defined for this platform!
 2760: 
 2761: #endif
 2762: 
 2763: /************************************************************************
 2764:  Deliberately outside the ACL defines. Return 1 if this is a "no acls"
 2765:  errno, 0 if not.
 2766: ************************************************************************/
 2767: 
 2768: int no_acl_syscall_error(int err)
 2769: {
 2770: #ifdef HAVE_OSX_ACLS
 2771: 	if (err == ENOENT)
 2772: 		return 1; /* Weird problem with directory ACLs. */
 2773: #endif
 2774: #if defined(ENOSYS)
 2775: 	if (err == ENOSYS) {
 2776: 		return 1;
 2777: 	}
 2778: #endif
 2779: #if defined(ENOTSUP)
 2780: 	if (err == ENOTSUP) {
 2781: 		return 1;
 2782: 	}
 2783: #endif
 2784: 	if (err == EINVAL) {
 2785: 		/* If the type of SMB_ACL_TYPE_ACCESS or SMB_ACL_TYPE_DEFAULT
 2786: 		 * isn't valid, then the ACLs must be non-POSIX. */
 2787: 		return 1;
 2788: 	}
 2789: 	return 0;
 2790: }
 2791: 
 2792: #endif /* SUPPORT_ACLS */

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