Esempio n. 1
0
File: acl.c Progetto: grke/burp
static int do_set_acl(struct asfd *asfd, const char *path,
	const char *acltext, int acltype, struct cntr *cntr)
{
	acl_t acl;
	int ret=-1;
	if(!(acl=acl_from_text(acltext)))
	{
		logp("acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		logw(asfd, cntr, "acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		goto end;
	}
	if(acl_valid(acl))
	{
		logp("acl_valid error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl_valid error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	if(acl_set_file(path, acltype, acl))
	{
		logp("acl set error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl set error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	ret=0;
end:
	if(acl) acl_free(acl);
	return ret;
}
Esempio n. 2
0
int fpm_unix_set_socket_premissions(struct fpm_worker_pool_s *wp, const char *path) /* {{{ */
{
#ifdef HAVE_FPM_ACL
    if (wp->socket_acl) {
        acl_t aclfile, aclconf;
        acl_entry_t entryfile, entryconf;
        int i;

        /* Read the socket ACL */
        aclconf = wp->socket_acl;
        aclfile = acl_get_file (path, ACL_TYPE_ACCESS);
        if (!aclfile) {
            zlog(ZLOG_SYSERROR, "[pool %s] failed to read the ACL of the socket '%s'", wp->config->name, path);
            return -1;
        }
        /* Copy the new ACL entry from config */
        for (i=ACL_FIRST_ENTRY ; acl_get_entry(aclconf, i, &entryconf) ; i=ACL_NEXT_ENTRY) {
            if (0 > acl_create_entry (&aclfile, &entryfile) ||
                    0 > acl_copy_entry(entryfile, entryconf)) {
                zlog(ZLOG_SYSERROR, "[pool %s] failed to add entry to the ACL of the socket '%s'", wp->config->name, path);
                acl_free(aclfile);
                return -1;
            }
        }
        /* Write the socket ACL */
        if (0 > acl_calc_mask (&aclfile) ||
                0 > acl_valid (aclfile) ||
                0 > acl_set_file (path, ACL_TYPE_ACCESS, aclfile)) {
            zlog(ZLOG_SYSERROR, "[pool %s] failed to write the ACL of the socket '%s'", wp->config->name, path);
            acl_free(aclfile);
            return -1;
        } else {
            zlog(ZLOG_DEBUG, "[pool %s] ACL of the socket '%s' is set", wp->config->name, path);
        }

        acl_free(aclfile);
        return 0;
    }
    /* When listen.users and listen.groups not configured, continue with standard right */
#endif

    if (wp->socket_uid != -1 || wp->socket_gid != -1) {
        if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
            zlog(ZLOG_SYSERROR, "[pool %s] failed to chown() the socket '%s'", wp->config->name, wp->config->listen_address);
            return -1;
        }
    }
    return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	acl_t acl;
	int n, ret = 0;

	progname = basename(argv[0]);

	if (argc < 3) {
		printf("%s -- set access control list of files\n"
			"Usage: %s acl file ...\n",
			progname, progname);
		return 1;
	}

	acl = acl_from_text(argv[1]);
	if (!acl) {
		fprintf(stderr, "%s: `%s': %s\n",
			progname, argv[1], strerror(errno));
		return 1;
	}
	if (acl_valid(acl) != 0) {
		fprintf(stderr, "%s: `%s': invalid/incomplete acl\n",
			progname, argv[1]);
		acl_free(acl);
		return 1;
	}

	for (n = 2; n < argc; n++) {
		if (acl_set_file(argv[n], ACL_TYPE_ACCESS, acl) != 0) {
			fprintf(stderr, "%s: setting acl of %s: %s\n",
				progname, argv[n], strerror(errno));
			ret = 1;
		}
	}

	acl_free(acl);

	return ret;
}
Esempio n. 4
0
/*!
 * Remove any ACL_USER, ACL_GROUP, ACL_MASK or ACL_TYPE_DEFAULT ACEs from an object
 *
 * @param name  (r) filesystem object name
 *
 * @returns AFP error code, AFP_OK (= 0) on success, AFPERR_MISC on error
 */
int remove_acl_vfs(const char *name)
{
    EC_INIT;

    struct stat st;
    acl_t acl = NULL;
    acl_entry_t e;
    acl_tag_t tag;
    int entry_id = ACL_FIRST_ENTRY;


    /* Remove default ACL if it's a dir */
    EC_ZERO_ERR(stat(name, &st), AFPERR_MISC);
    if (S_ISDIR(st.st_mode)) {
        EC_NULL_LOG_ERR(acl = acl_init(0), AFPERR_MISC);
        EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, acl), AFPERR_MISC);
        EC_ZERO_LOG_ERR(acl_free(acl), AFPERR_MISC);
        acl = NULL;
    }

    /* Now get ACL and remove ACL_MASK, ACL_USER or ACL_GROUP entries, then re-set
     * the ACL again. acl_calc_mask() must not be called because there is no need
     * for an ACL_MASK entry in a basic ACL. */
    EC_NULL_LOG_ERR(acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC);
    for ( ; acl_get_entry(acl, entry_id, &e) == 1; entry_id = ACL_NEXT_ENTRY) {
        EC_ZERO_LOG_ERR(acl_get_tag_type(e, &tag), AFPERR_MISC);
        if (tag == ACL_USER || tag == ACL_GROUP || tag == ACL_MASK)
            EC_ZERO_LOG_ERR(acl_delete_entry(acl, e), AFPERR_MISC);
    }
    EC_ZERO_LOG_ERR(acl_valid(acl), AFPERR_MISC);
    EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, acl), AFPERR_MISC);

EC_CLEANUP:
    if (errno == ENOENT) EC_STATUS(0);
    if (acl) acl_free(acl);

    EC_EXIT;
}
Esempio n. 5
0
File: acl.c Progetto: vanElden/burp
static int do_set_acl(struct asfd *asfd, const char *path,
	const char *acltext, size_t alen,
	int acltype, struct cntr *cntr)
{
	acl_t acl;
	int ret=-1;
	if(!(acl=acl_from_text(acltext)))
	{
		logp("acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		logw(asfd, cntr, "acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		goto end;
	}
//#ifndef HAVE_FREEBSD_OS // Bacula says that acl_valid fails on valid input
			// on freebsd. It works OK for me on FreeBSD 8.2.
	if(acl_valid(acl))
	{
		logp("acl_valid error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl_valid error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
//#endif
	if(acl_set_file(path, acltype, acl))
	{
		logp("acl set error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl set error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	ret=0;
end:
	if(acl) acl_free(acl);
	return ret; 
}
Esempio n. 6
0
/*
 * acl_from_text -- Convert a string into an ACL.
 * Postpone most validity checking until the end and call acl_valid() to do
 * that.
 */
acl_t
acl_from_text(const char *buf_p)
{
	acl_t		 acl;
	char		*mybuf_p, *line, *cur, *notcomment, *comment, *entry;
	int		 error;

	/* Local copy we can mess up. */
	mybuf_p = strdup(buf_p);
	if (mybuf_p == NULL)
		return(NULL);

	acl = acl_init(3); /* XXX: WTF, 3? */
	if (acl == NULL) {
		free(mybuf_p);
		return(NULL);
	}

	/* Outer loop: delimit at \n boundaries. */
	cur = mybuf_p;
	while ((line = strsep(&cur, "\n"))) {
		/* Now split the line on the first # to strip out comments. */
		comment = line;
		notcomment = strsep(&comment, "#");

		/* Inner loop: delimit at ',' boundaries. */
		while ((entry = strsep(&notcomment, ","))) {

			/* Skip empty lines. */
			if (strlen(string_skip_whitespace(entry)) == 0)
				continue;

			if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
				if (_text_is_nfs4_entry(entry))
					_acl_brand_as(acl, ACL_BRAND_NFS4);
				else
					_acl_brand_as(acl, ACL_BRAND_POSIX);
			}

			switch (_acl_brand(acl)) {
			case ACL_BRAND_NFS4:
				error = _nfs4_acl_entry_from_text(acl, entry);
				break;

			case ACL_BRAND_POSIX:
				error = _posix1e_acl_entry_from_text(acl, entry);
				break;

			default:
				error = EINVAL;
				break;
			}

			if (error)
				goto error_label;
		}
	}

#if 0
	/* XXX Should we only return ACLs valid according to acl_valid? */
	/* Verify validity of the ACL we read in. */
	if (acl_valid(acl) == -1) {
		errno = EINVAL;
		goto error_label;
	}
#endif

	free(mybuf_p);
	return(acl);

error_label:
	acl_free(acl);
	free(mybuf_p);
	return(NULL);
}
Esempio n. 7
0
File: cert.c Progetto: jelmer/cups
void
cupsdAddCert(int        pid,		/* I - Process ID */
             const char *username,	/* I - Username */
             int        type)		/* I - AuthType for username */
{
  int		i;			/* Looping var */
  cupsd_cert_t	*cert;			/* Current certificate */
  int		fd;			/* Certificate file */
  char		filename[1024];		/* Certificate filename */
  static const char hex[] = "0123456789ABCDEF";
					/* Hex constants... */


  cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsdAddCert: Adding certificate for PID %d", pid);

 /*
  * Allocate memory for the certificate...
  */

  if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL)
    return;

 /*
  * Fill in the certificate information...
  */

  cert->pid  = pid;
  cert->type = type;
  strlcpy(cert->username, username, sizeof(cert->username));

  for (i = 0; i < 32; i ++)
    cert->certificate[i] = hex[CUPS_RAND() & 15];

 /*
  * Save the certificate to a file readable only by the User and Group
  * (or root and SystemGroup for PID == 0)...
  */

  snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
  unlink(filename);

  if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create certificate file %s - %s",
                    filename, strerror(errno));
    free(cert);
    return;
  }

  if (pid == 0)
  {
#ifdef HAVE_ACL_INIT
    acl_t		acl;		/* ACL information */
    acl_entry_t		entry;		/* ACL entry */
    acl_permset_t	permset;	/* Permissions */
#  ifdef HAVE_MBR_UID_TO_UUID
    uuid_t		group;		/* Group ID */
#  endif /* HAVE_MBR_UID_TO_UUID */
    static int		acls_not_supported = 0;
					/* Only warn once */
#endif /* HAVE_ACL_INIT */


   /*
    * Root certificate...
    */

    fchmod(fd, 0440);
    fchown(fd, RunUser, SystemGroupIDs[0]);

    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d",
                    NumSystemGroups);

#ifdef HAVE_ACL_INIT
    if (NumSystemGroups > 1)
    {
     /*
      * Set POSIX ACLs for the root certificate so that all system
      * groups can access it...
      */

      int	j;			/* Looping var */

#  ifdef HAVE_MBR_UID_TO_UUID
     /*
      * On MacOS X, ACLs use UUIDs instead of GIDs...
      */

      acl = acl_init(NumSystemGroups - 1);

      for (i = 1; i < NumSystemGroups; i ++)
      {
       /*
        * Add each group ID to the ACL...
	*/

        for (j = 0; j < i; j ++)
	  if (SystemGroupIDs[j] == SystemGroupIDs[i])
            break;

        if (j < i)
          continue;			/* Skip duplicate groups */

        acl_create_entry(&acl, &entry);
	acl_get_permset(entry, &permset);
	acl_add_perm(permset, ACL_READ_DATA);
	acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
	mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group);
	acl_set_qualifier(entry, &group);
	acl_set_permset(entry, permset);
      }

#  else
     /*
      * POSIX ACLs need permissions for owner, group, other, and mask
      * in addition to the rest of the system groups...
      */

      acl = acl_init(NumSystemGroups + 3);

      /* Owner */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_USER_OBJ);
      acl_set_permset(entry, permset);

      /* Group */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_GROUP_OBJ);
      acl_set_permset(entry, permset);

      /* Others */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, 0);
      acl_set_tag_type(entry, ACL_OTHER);
      acl_set_permset(entry, permset);

      /* Mask */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_MASK);
      acl_set_permset(entry, permset);

      for (i = 1; i < NumSystemGroups; i ++)
      {
       /*
        * Add each group ID to the ACL...
	*/

        for (j = 0; j < i; j ++)
	  if (SystemGroupIDs[j] == SystemGroupIDs[i])
            break;

        if (j < i)
          continue;			/* Skip duplicate groups */

        acl_create_entry(&acl, &entry);
	acl_get_permset(entry, &permset);
	acl_add_perm(permset, ACL_READ);
	acl_set_tag_type(entry, ACL_GROUP);
	acl_set_qualifier(entry, SystemGroupIDs + i);
	acl_set_permset(entry, permset);
      }

      if (acl_valid(acl))
      {
        char *text, *textptr;		/* Temporary string */

        cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s",
	                strerror(errno));
        text = acl_to_text(acl, NULL);
	for (textptr = strchr(text, '\n');
	     textptr;
	     textptr = strchr(textptr + 1, '\n'))
	  *textptr = ',';

	cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
	acl_free(text);
      }
#  endif /* HAVE_MBR_UID_TO_UUID */

      if (acl_set_fd(fd, acl))
      {
	if (errno != EOPNOTSUPP || !acls_not_supported)
	  cupsdLogMessage(CUPSD_LOG_ERROR,
			  "Unable to set ACLs on root certificate \"%s\" - %s",
			  filename, strerror(errno));

	if (errno == EOPNOTSUPP)
	  acls_not_supported = 1;
      }

      acl_free(acl);
    }
#endif /* HAVE_ACL_INIT */

    RootCertTime = time(NULL);
  }
  else
  {
   /*
    * CGI certificate...
    */

    fchmod(fd, 0400);
    fchown(fd, User, Group);
  }

  DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
                cert->certificate));

  write(fd, cert->certificate, strlen(cert->certificate));
  close(fd);

 /*
  * Insert the certificate at the front of the list...
  */

  cert->next = Certs;
  Certs      = cert;
}
Esempio n. 8
0
int
main(int argc, char *argv[])
{
    Boolean recalcMask, useDefaultACL;
    Boolean modifyACL, removeACL, removeDefaultACL, checkValidity;
    int optCnt, j, opt, numEntries, en;
    acl_type_t type;
    char *aclSpec;
    acl_t acl;
    acl_entry_t entry;
    struct AccessControlEntry aclist[MAX_ENTRIES];

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageError(argv[0], NULL, FALSE);

    /* Parse command-line options */

    recalcMask = TRUE;
    useDefaultACL = FALSE;
    modifyACL = FALSE;
    removeACL = FALSE;
    checkValidity = FALSE;
    removeDefaultACL = FALSE;
    optCnt = 0;

    while ((opt = getopt(argc, argv, "m:x:kdnV:")) != -1) {
        switch (opt) {
        case 'm':
            modifyACL = TRUE;
            aclSpec = optarg;
            optCnt++;
            break;

        case 'x':
            removeACL = TRUE;
            aclSpec = optarg;
            optCnt++;
            break;

        case 'k':
            removeDefaultACL = TRUE;
            optCnt++;
            break;

        case 'V':
            checkValidity = TRUE;
            aclSpec = optarg;
            optCnt++;
            break;

        case 'd':
            useDefaultACL = TRUE;
            break;

        case 'n':
            recalcMask = FALSE;
            break;

        default:
            usageError(argv[0], "Bad option\n", TRUE);
            break;
        }
    }

    if (optCnt != 1)
        usageError(argv[0], "Specify exactly one of -m, -x, -k, or -V\n", TRUE);

    if (checkValidity && useDefaultACL)
        usageError(argv[0], "Can't specify -d with -V\n", TRUE);

    if (checkValidity) {
        if (parseACL(aclSpec, aclist, TRUE) == -1) {
            fatal("Bad ACL entry specification");
        } else {
            printf("ACL is valid\n");
            exit(EXIT_SUCCESS);
        }
    }

    if (modifyACL || removeACL) {
        numEntries = parseACL(aclSpec, aclist, modifyACL);
        if (numEntries == -1)
            usageError(argv[0], "Bad ACL specification\n", TRUE);
    }

    type = useDefaultACL ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS;

    /* Perform the operation on each file argument */

    for (j = optind; j < argc; j++) {
        if (removeDefaultACL) {
            if (acl_delete_def_file(argv[j]) == -1)
                errExit("acl_delete_def_file: %s", argv[j]);

        } else if (modifyACL || removeACL) {

            acl = acl_get_file(argv[j], type);
            if (acl == NULL)
                errExit("acl_get_file");

            /* Apply each of the entries in 'aclist' to the
               current file */

            for (en = 0; en < numEntries; en++) {
                entry = findEntry(acl, aclist[en].tag, aclist[en].qual);

                if (removeACL) {
                    if (entry != NULL)
                        if (acl_delete_entry(acl, entry) == -1)
                            errExit("acl_delete_entry");

                } else {        /* modifyACL */

                    if (entry == NULL) {

                        /* Entry didn't exist in ACL -- create a new
                           entry with required tag and qualifier */

                        if (acl_create_entry(&acl, &entry) == -1)
                            errExit("acl_create_entry");
                        if (acl_set_tag_type(entry, aclist[en].tag) == -1)
                            errExit("acl_set_tag_type");
                        if (aclist[en].tag == ACL_USER ||
                                aclist[en].tag == ACL_GROUP)
                            if (acl_set_qualifier(entry,
                                        &aclist[en].qual) == -1)
                                errExit("acl_set_qualifier");
                    }

                    setPerms(entry, aclist[en].perms);
                }

                /* Recalculate the mask entry if requested */

                if (recalcMask)
                    if (acl_calc_mask(&acl) == -1)
                        errExit("acl_calc_mask");

                /* Update the file ACL */

                if (acl_valid(acl) == -1)
                    errExit("acl_valid");

                if (acl_set_file(argv[j], type, acl) == -1)
                    errExit("acl_set_file");
            }

            if (acl_free(acl) == -1)
                errExit("acl_free");
        } else {
            fatal("Bad logic!");
        }
    }

    exit(EXIT_SUCCESS);
}
Esempio n. 9
0
static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
{
	acl_t result;
	int i;

	result = acl_init(acl->count);
	if (result == NULL) {
		DEBUG(10, ("acl_init failed\n"));
		return NULL;
	}

	for (i=0; i<acl->count; i++) {
		const struct smb_acl_entry *entry = &acl->acl[i];
		acl_entry_t e;
		acl_tag_t tag;

		if (acl_create_entry(&result, &e) != 0) {
			DEBUG(1, ("acl_create_entry failed: %s\n",
				  strerror(errno)));
			goto fail;
		}

		switch (entry->a_type) {
		case SMB_ACL_USER:
			tag = ACL_USER;
			break;
		case SMB_ACL_USER_OBJ:
			tag = ACL_USER_OBJ;
			break;
		case SMB_ACL_GROUP:
			tag = ACL_GROUP;
			break;
		case SMB_ACL_GROUP_OBJ:
			tag = ACL_GROUP_OBJ;
			break;
		case SMB_ACL_OTHER:
			tag = ACL_OTHER;
			break;
		case SMB_ACL_MASK:
			tag = ACL_MASK;
			break;
		default:
			DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
			goto fail;
		}

		if (acl_set_tag_type(e, tag) != 0) {
			DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
				   tag, strerror(errno)));
			goto fail;
		}

		switch (entry->a_type) {
		case SMB_ACL_USER:
			if (acl_set_qualifier(e, &entry->uid) != 0) {
				DEBUG(1, ("acl_set_qualifiier failed: %s\n",
					  strerror(errno)));
				goto fail;
			}
			break;
		case SMB_ACL_GROUP:
			if (acl_set_qualifier(e, &entry->gid) != 0) {
				DEBUG(1, ("acl_set_qualifiier failed: %s\n",
					  strerror(errno)));
				goto fail;
			}
			break;
		default: 	/* Shut up, compiler! :-) */
			break;
		}

		if (smb_acl_set_mode(e, entry->a_perm) != 0) {
			goto fail;
		}
	}

	if (acl_valid(result) != 0) {
		DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
			  strerror(errno)));
		goto fail;
	}

	return result;

 fail:
	if (result != NULL) {
		acl_free(result);
	}
	return NULL;
}
Esempio n. 10
0
void dump_acl(const acl_t acl)
{
	DEBUG("acl valid: %d\n", acl_valid(acl) == 0 ? 1 : 0);
	walk_acl(acl, dump_acl_callback, NULL);
}
Esempio n. 11
0
/*
 * acl_calc_mask() (23.4.2): calculate and set the permissions
 * associated with the ACL_MASK ACL entry.  If the ACL already
 * contains an ACL_MASK entry, its permissions shall be
 * overwritten; if not, one shall be added.
 */
int
acl_calc_mask(acl_t *acl_p)
{
	struct acl	*acl_int, *acl_int_new;
	acl_t		acl_new;
	int		i, mask_mode, mask_num;

	/*
	 * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL.
	 * Since one of the primary reasons to use this function would be
	 * to calculate the appropriate mask to obtain a valid ACL, we only
	 * perform sanity checks here and validate the ACL prior to
	 * returning.
	 */
	if (acl_p == NULL || *acl_p == NULL) {
		errno = EINVAL;
		return (-1);
	}

	if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) {
		errno = EINVAL;
		return (-1);
	}
	_acl_brand_as(*acl_p, ACL_BRAND_POSIX);

	acl_int = &(*acl_p)->ats_acl;
	if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
		errno = EINVAL;
		return (-1);
	}

	acl_new = acl_dup(*acl_p);
	if (acl_new == NULL)
		return (-1);
	acl_int_new = &acl_new->ats_acl;

	mask_mode = 0;
	mask_num = -1;

	/* gather permissions and find a mask entry */
	for (i = 0; i < acl_int_new->acl_cnt; i++) {
		switch(acl_int_new->acl_entry[i].ae_tag) {
		case ACL_USER:
		case ACL_GROUP:
		case ACL_GROUP_OBJ:
			mask_mode |=
			    acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
			break;
		case ACL_MASK:
			mask_num = i;
			break;
		}
	}

	/* if a mask entry already exists, overwrite the perms */
	if (mask_num != -1)
		acl_int_new->acl_entry[mask_num].ae_perm = mask_mode;
	else {
		/* if no mask exists, check acl_cnt... */
		if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) {
			errno = ENOMEM;
			acl_free(acl_new);
			return (-1);
		}
		/* ...and add the mask entry */
		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK;
		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id =
		    ACL_UNDEFINED_ID;
		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm =
		    mask_mode;
		acl_int_new->acl_cnt++;
	}

	if (acl_valid(acl_new) == -1) {
		errno = EINVAL;
		acl_free(acl_new);
		return (-1);
	}

	**acl_p = *acl_new;
	acl_free(acl_new);

	return (0);
}