Пример #1
0
/* 
 *   deletes an access acl or directory default acl if one exists
 */ 
static int 
acl_delete_file(const char *path, acl_type_t type)
{
	int error = 0;

	/* converts access ACL to a minimal ACL */
	if (type == ACL_TYPE_ACCESS) {
		acl_t acl;
		acl_entry_t entry;
		acl_tag_t tag;

		acl = acl_get_file(path, ACL_TYPE_ACCESS);
		if (!acl)
			return -1;
		error = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
		while (error == 1) {
			acl_get_tag_type(entry, &tag);
			switch(tag) {
				case ACL_USER:
				case ACL_GROUP:
				case ACL_MASK:
					acl_delete_entry(acl, entry);
					break;
			 }
			error = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
		}
		if (!error)
			error = acl_set_file(path, ACL_TYPE_ACCESS, acl);
	} else
		error = acl_delete_def_file(path);
	return(error);
}
static int flush_acl(acl_t acl) {
    acl_entry_t i;
    int found;
    bool changed = false;

    assert(acl);

    for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
            found > 0;
            found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {

        acl_tag_t tag;

        if (acl_get_tag_type(i, &tag) < 0)
            return -errno;

        if (tag != ACL_USER)
            continue;

        if (acl_delete_entry(acl, i) < 0)
            return -errno;

        changed = true;
    }

    if (found < 0)
        return -errno;

    return changed;
}
Пример #3
0
/**
* removes entry in ptr from acl
* acl: ptr to acl to modify
* entry: ptr to entry to remove
* returns: status
**/
_BOOL acl_remove(acl_t * acl, acl_entry_t *entry,acl_entry_in *entry_in){
  if(acl==NULL || entry==NULL){errno = EINVAL; return FALSE;}

  #ifdef POSIXLY_CORRECT
  if(entry_in->no_perm){
    errno = EINVAL;
    return FALSE;
  }
  acl_permset_t permset;
  if(acl_get_permset(*entry,&permset)!=ACL_OK)
    return FALSE;
  int verify_bits = 0;
  verify_bits += ((entry_in->permset.nibble)&READ&&acl_get_perm(permset,ACL_READ)|| !(entry_in->permset.nibble&READ)) ? 1 : 0;
  verify_bits += ((entry_in->permset.nibble&WRITE)&&acl_get_perm(permset,ACL_WRITE)|| !(entry_in->permset.nibble&WRITE)) ? 1 : 0;
  verify_bits += ((entry_in->permset.nibble&EXEC)&&acl_get_perm(permset,ACL_EXECUTE)|| !(entry_in->permset.nibble&EXEC)) ? 1 : 0;
  if(verify_bits!=VERIFIED_BITS){errno = EINVAL; return FALSE;}
  #else
  if(!entry_in->no_perm){
    errno = EINVAL;
    return FALSE;
  }
  #endif

  if(acl_delete_entry(*acl,*entry)!=ACL_OK)
    return FALSE;

  return TRUE;

}
Пример #4
0
static int
remove_extended_entries(
	acl_t acl)
{
	acl_entry_t ent, group_obj;
	acl_permset_t mask_permset, group_obj_permset;
	acl_tag_t tag;
	int error;
	
	/*
	 * Removing the ACL_MASK entry from the ACL results in
	 * increased permissions for the owning group if the
	 * ACL_GROUP_OBJ entry contains permissions not contained
	 * in the ACL_MASK entry. We remove these permissions from
	 * the ACL_GROUP_OBJ entry to avoid that.
	 *
	 * After removing the ACL, the file owner and the owning group
	 * therefore have the same permissions as before.
	 */

	ent = find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID);
	group_obj = find_entry(acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID);
	if (ent && group_obj) {
		if (!acl_get_permset(ent, &mask_permset) &&
		    !acl_get_permset(group_obj, &group_obj_permset)) {
			if (!acl_get_perm(mask_permset, ACL_READ))
				acl_delete_perm(group_obj_permset, ACL_READ);
			if (!acl_get_perm(mask_permset, ACL_WRITE))
				acl_delete_perm(group_obj_permset, ACL_WRITE);
			if (!acl_get_perm(mask_permset, ACL_EXECUTE))
				acl_delete_perm(group_obj_permset, ACL_EXECUTE);
		}
	}

	error = acl_get_entry(acl, ACL_FIRST_ENTRY, &ent);
	while (error == 1) {
		acl_get_tag_type(ent, &tag);
		switch(tag) {
			case ACL_USER:
			case ACL_GROUP:
			case ACL_MASK:
				acl_delete_entry(acl, ent);
				break;
			default:
				break;
		}
	
		error = acl_get_entry(acl, ACL_NEXT_ENTRY, &ent);
	}
	if (error < 0)
		return -1;
	return 0;
}
Пример #5
0
/*
 * remove ACL entries from an ACL
 */
int
remove_acl(acl_t acl, acl_t *prev_acl, const char *filename)
{
	acl_entry_t	entry;
	acl_t		acl_new;
	acl_tag_t	tag;
	int		carried_error, entry_id, acl_brand, prev_acl_brand;

	carried_error = 0;

	acl_get_brand_np(acl, &acl_brand);
	acl_get_brand_np(*prev_acl, &prev_acl_brand);

	if (branding_mismatch(acl_brand, prev_acl_brand)) {
		warnx("%s: branding mismatch; existing ACL is %s, "
		    "entry to be removed is %s", filename,
		    brand_name(prev_acl_brand), brand_name(acl_brand));
		return (-1);
	}

	carried_error = 0;

	acl_new = acl_dup(*prev_acl);
	if (acl_new == NULL)
		err(1, "%s: acl_dup() failed", filename);

	tag = ACL_UNDEFINED_TAG;

	/* find and delete the entry */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;
		if (acl_get_tag_type(entry, &tag) == -1)
			err(1, "%s: acl_get_tag_type() failed", filename);
		if (tag == ACL_MASK)
			have_mask++;
		if (acl_delete_entry(acl_new, entry) == -1) {
			carried_error++;
			warnx("%s: cannot remove non-existent ACL entry",
			    filename);
		}
	}

	acl_free(*prev_acl);
	*prev_acl = acl_new;

	if (carried_error)
		return (-1);

	return (0);
}
Пример #6
0
/*
 * remove ACL entries from an ACL
 */
int
remove_acl(acl_t acl, acl_t *prev_acl)
{
	acl_entry_t entry;
	acl_t acl_new;
	acl_tag_t tag;
	int carried_error, entry_id;

	carried_error = 0;

	if (acl_type == ACL_TYPE_ACCESS)
		acl_new = acl_dup(prev_acl[ACCESS_ACL]);
	else
		acl_new = acl_dup(prev_acl[DEFAULT_ACL]);

	if (acl_new == NULL)
		err(1, "acl_dup() failed");

	tag = ACL_UNDEFINED_TAG;

	/* find and delete the entry */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;
		if (acl_get_tag_type(entry, &tag) == -1)
			err(1, "acl_get_tag_type() failed");
		if (tag == ACL_MASK)
			have_mask++;
		if (acl_delete_entry(acl_new, entry) == -1) {
			carried_error++;
			warnx("cannot remove non-existent acl entry");
		}
	}

	if (acl_type == ACL_TYPE_ACCESS) {
		acl_free(prev_acl[ACCESS_ACL]);
		prev_acl[ACCESS_ACL] = acl_new;
	} else {
		acl_free(prev_acl[DEFAULT_ACL]);
		prev_acl[DEFAULT_ACL] = acl_new;
	}

	if (carried_error)
		return (-1);

	return (0);
}
Пример #7
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;
}
Пример #8
0
static int set_facl(const char* filename, uid_t uid, int add)
{
	int get;
	acl_t acl;
	acl_entry_t entry = NULL;
	acl_entry_t e;
	acl_permset_t permset;
	int ret;

	/* don't touch ACLs for root */
	if (uid == 0)
		return 0;

	/* read current record */
	acl = acl_get_file(filename, ACL_TYPE_ACCESS);
	if (!acl)
		return -1;

	/* locate ACL_USER entry for uid */
	get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e);
	while (get == 1) {
		acl_tag_t t;

		acl_get_tag_type(e, &t);
		if (t == ACL_USER) {
			uid_t *u;

			u = (uid_t*)acl_get_qualifier(e);
			if (u == NULL) {
				ret = -1;
				goto out;
			}
			if (*u == uid) {
				entry = e;
				acl_free(u);
				break;
			}
			acl_free(u);
		}

		get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e);
	}

	/* remove ACL_USER entry for uid */
	if (!add) {
		if (entry == NULL) {
			ret = 0;
			goto out;
		}
		acl_delete_entry(acl, entry);
		goto update;
	}

	/* create ACL_USER entry for uid */
	if (entry == NULL) {
		ret = acl_create_entry(&acl, &entry);
		if (ret != 0)
			goto out;
		acl_set_tag_type(entry, ACL_USER);
		acl_set_qualifier(entry, &uid);
	}

	/* add permissions for uid */
	acl_get_permset(entry, &permset);
	acl_add_perm(permset, ACL_READ|ACL_WRITE);
update:
	/* update record */
	if (debug)
		printf("%c%u %s\n", add ? '+' : '-', uid, filename);
	acl_calc_mask(&acl);
	ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl);
	if (ret != 0)
		goto out;
out:
	acl_free(acl);
	return ret;
}
int devnode_acl(const char *path,
                bool flush,
                bool del, uid_t old_uid,
                bool add, uid_t new_uid) {

    acl_t acl;
    int r = 0;
    bool changed = false;

    assert(path);

    acl = acl_get_file(path, ACL_TYPE_ACCESS);
    if (!acl)
        return -errno;

    if (flush) {

        r = flush_acl(acl);
        if (r < 0)
            goto finish;
        if (r > 0)
            changed = true;

    } else if (del && old_uid > 0) {
        acl_entry_t entry;

        r = acl_find_uid(acl, old_uid, &entry);
        if (r < 0)
            goto finish;

        if (r > 0) {
            if (acl_delete_entry(acl, entry) < 0) {
                r = -errno;
                goto finish;
            }

            changed = true;
        }
    }

    if (add && new_uid > 0) {
        acl_entry_t entry;
        acl_permset_t permset;
        int rd, wt;

        r = acl_find_uid(acl, new_uid, &entry);
        if (r < 0)
            goto finish;

        if (r == 0) {
            if (acl_create_entry(&acl, &entry) < 0) {
                r = -errno;
                goto finish;
            }

            if (acl_set_tag_type(entry, ACL_USER) < 0 ||
                    acl_set_qualifier(entry, &new_uid) < 0) {
                r = -errno;
                goto finish;
            }
        }

        if (acl_get_permset(entry, &permset) < 0) {
            r = -errno;
            goto finish;
        }

        rd = acl_get_perm(permset, ACL_READ);
        if (rd < 0) {
            r = -errno;
            goto finish;
        }

        wt = acl_get_perm(permset, ACL_WRITE);
        if (wt < 0) {
            r = -errno;
            goto finish;
        }

        if (!rd || !wt) {

            if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) {
                r = -errno;
                goto finish;
            }

            changed = true;
        }
    }

    if (!changed)
        goto finish;

    if (acl_calc_mask(&acl) < 0) {
        r = -errno;
        goto finish;
    }

    if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) {
        r = -errno;
        goto finish;
    }

    r = 0;

finish:
    acl_free(acl);

    return r;
}
Пример #10
0
int
do_set(
	const char *path_p,
	const struct stat *st,
	const seq_t seq)
{
	acl_t old_acl = NULL, old_default_acl = NULL;
	acl_t acl = NULL, default_acl = NULL;
	acl_t *xacl, *old_xacl;
	acl_entry_t ent;
	cmd_t cmd;
	int which_entry;
	int errors = 0, error;
	char *acl_text;
	int acl_modified = 0, default_acl_modified = 0;
	int acl_mask_provided = 0, default_acl_mask_provided = 0;

	/* Execute the commands in seq (read ACLs on demand) */
	error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd);
	if (error == 0)
		return 0;
	while (error == 1) {
		if (cmd->c_type == ACL_TYPE_ACCESS) {
			xacl = &acl;
			old_xacl = &old_acl;
			acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				acl_mask_provided = 1;
		} else {
			xacl = &default_acl;
			old_xacl = &old_default_acl;
			default_acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				default_acl_mask_provided = 1;
		}

		RETRIEVE_ACL(cmd->c_type);

		/* Check for `X', and replace with `x' as appropriate. */
		if (cmd->c_perm & CMD_PERM_COND_EXECUTE) {
			cmd->c_perm &= ~CMD_PERM_COND_EXECUTE;
			if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl))
				cmd->c_perm |= CMD_PERM_EXECUTE;
		}

		switch(cmd->c_cmd) {
			case CMD_ENTRY_REPLACE:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (!ent) {
					if (acl_create_entry(xacl, &ent) != 0)
						goto fail;
					acl_set_tag_type(ent, cmd->c_tag);
					if (cmd->c_id != ACL_UNDEFINED_ID)
						acl_set_qualifier(ent,
								  &cmd->c_id);
				}
				set_perm(ent, cmd->c_perm, ~cmd->c_perm);
				break;

			case CMD_ENTRY_ADD:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, cmd->c_perm, 0);
				break;

			case CMD_ENTRY_SUBTRACT:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, 0, cmd->c_perm);
				break;

			case CMD_REMOVE_ENTRY:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					acl_delete_entry(*xacl, ent);
				else
					/* ignore */;
				break;

			case CMD_REMOVE_EXTENDED_ACL:
				remove_extended_entries(acl);
				break;

			case CMD_REMOVE_ACL:
				acl_free(*xacl);
				*xacl = acl_init(5);
				if (!*xacl)
					goto fail;
				break;

			default:
				errno = EINVAL;
				goto fail;
		}

		error = seq_get_cmd(seq, SEQ_NEXT_CMD, &cmd);
	}

	if (error < 0)
		goto fail;

	/* Try to fill in missing entries */
	if (default_acl && acl_entries(default_acl) != 0) {
		xacl = &acl;
		old_xacl = &old_acl;
	
		if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_USER_OBJ,
			            &default_acl, ACL_USER_OBJ);
		}
		if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_GROUP_OBJ,
			            &default_acl, ACL_GROUP_OBJ);
		}
		if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_OTHER,
			            &default_acl, ACL_OTHER);
		}
	}

	/* update mask entries and check if ACLs are valid */
	if (acl && acl_modified) {
		if (acl_equiv_mode(acl, NULL) != 0) {
			if (!acl_mask_provided &&
			    !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID))
				clone_entry(acl, ACL_GROUP_OBJ,
				            &acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!acl_mask_provided || opt_recalculate == 1))
				acl_calc_mask(&acl);
		}

		error = acl_check(acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed access ACL "
				"`%s': %s at entry %d\n"), progname, path_p,
				acl_text, acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	if (default_acl && acl_entries(default_acl) != 0 &&
	    default_acl_modified) {
		if (acl_equiv_mode(default_acl, NULL) != 0) {
			if (!default_acl_mask_provided &&
			    !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID))
				clone_entry(default_acl, ACL_GROUP_OBJ,
				            &default_acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!default_acl_mask_provided ||
			     opt_recalculate == 1))
				acl_calc_mask(&default_acl);
		}

		error = acl_check(default_acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(default_acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed default ACL "
			                  "`%s': %s at entry %d\n"),
				progname, path_p, acl_text,
				acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	/* Only directores can have default ACLs */
	if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) {
		/* In recursive mode, ignore default ACLs for files */
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* check which ACLs have changed */
	if (acl && old_acl && acl_cmp(old_acl, acl) == 0) {
		acl_free(acl);
		acl = NULL;
	}
	if ((default_acl && old_default_acl &&
	    acl_cmp(old_default_acl, default_acl) == 0)) {
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* update the file system */
	if (opt_test) {
		print_test(stdout, path_p, st,
		           acl, default_acl);
		goto cleanup;
	}
	if (acl) {
		if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) {
			if (errno == ENOSYS || errno == ENOTSUP) {
				int saved_errno = errno;
				mode_t mode;

				if (acl_equiv_mode(acl, &mode) != 0) {
					errno = saved_errno;
					goto fail;
				} else if (chmod(path_p, mode) != 0)
					goto fail;
			} else
				goto fail;
		}
	}
	if (default_acl) {
		if (S_ISDIR(st->st_mode)) {
			if (acl_entries(default_acl) == 0) {
				if (acl_delete_def_file(path_p) != 0 &&
				    errno != ENOSYS && errno != ENOTSUP)
					goto fail;
			} else {
				if (acl_set_file(path_p, ACL_TYPE_DEFAULT,
						 default_acl) != 0)
					goto fail;
			}
		} else {
			if (acl_entries(default_acl) != 0) {
				fprintf(stderr, gettext(
						"%s: %s: Only directories "
						"can have default ACLs\n"),
					progname, path_p);
				errors++;
				goto cleanup;
			}
		}
	}

	error = 0;

cleanup:
	if (acl)
		acl_free(acl);
	if (old_acl)
		acl_free(old_acl);
	if (default_acl)
		acl_free(default_acl);
	if (old_default_acl)
		acl_free(old_default_acl);
	return errors;
	
fail:
	fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
	errors++;
	goto cleanup;
}
Пример #11
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);
}
Пример #12
0
int
modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags,
	   int position, int inheritance_level, 
	   unsigned flag_new_acl, const char* path) {

	unsigned cpos = 0;
	acl_entry_t newent = NULL;
	int dmatch = 0;
	acl_entry_t rentry = NULL;
	unsigned retval = 0;
	acl_t oacl = *oaclp;
	
/* Add the inherited flag if requested by the user*/
	if (modifier && (optflags & ACL_INHERIT_FLAG)) {
		acl_flagset_t mflags;

		acl_get_flagset_np(modifier, &mflags);
		acl_add_flag_np(mflags, ACL_ENTRY_INHERITED);
		acl_set_flagset_np(modifier, mflags);
	}

	if (optflags & ACL_SET_FLAG) {
		if (position != -1) {
            if (0 != acl_create_entry_np(&oacl, &newent, position)) {
				// err(1, "acl_create_entry() failed");
                fprintf(stderr, "chmod: acl_create_entry() failed: %s\n", strerror(errno));
                pthread_exit(NULL);
            }
			acl_copy_entry(newent, modifier);
		} else {
/* If an entry exists, add the new permissions to it, else add an
 * entry in the canonical position.
 */

/* First, check for a matching entry - if one exists, merge flags */
			dmatch = find_matching_entry(oacl, modifier, &rentry, 1);

			if (dmatch != MATCH_NONE) {
				if (dmatch == MATCH_EXACT)
/* Nothing to be done */
					goto ma_exit; 
				
				if (dmatch == MATCH_PARTIAL) {
					merge_entry_perms(rentry, modifier);
					goto ma_exit;
				}
			}
/* Insert the entry in canonical order */
			cpos = find_canonical_position(oacl, modifier);
            if (0!= acl_create_entry_np(&oacl, &newent, cpos)) {
				// err(1, "acl_create_entry() failed");
                fprintf(stderr, "chmod: acl_create_entry() failed: %s\n", strerror(errno));
                pthread_exit(NULL);
            }
			acl_copy_entry(newent, modifier);
		}
	} else if (optflags & ACL_DELETE_FLAG) {
		if (flag_new_acl) {
            fprintf(stderr, "chmod: No ACL present '%s'\n", path);
            // warnx("No ACL present '%s'", path);
			retval = 1;
		} else if (position != -1 ) {
			if (0 != acl_get_entry(oacl, position, &rentry)) {
                fprintf(stderr, "chmod: Invalid entry number '%s'\n", path);
                // warnx("Invalid entry number '%s'", path);
				retval = 1;
			} else {
				acl_delete_entry(oacl, rentry);
			}
		} else {
			unsigned match_found = 0, aindex;
			for (aindex = 0; 
			     acl_get_entry(oacl, rentry == NULL ? 
					   ACL_FIRST_ENTRY : 
					   ACL_NEXT_ENTRY, &rentry) == 0;
			     aindex++)	{
				unsigned cmp;
				cmp = compare_acl_entries(rentry, modifier);
				if ((cmp == MATCH_EXACT) || 
				    (cmp == MATCH_PARTIAL)) {
					match_found++;
					if (cmp == MATCH_EXACT)
						acl_delete_entry(oacl, rentry);
					else {
						int valid_perms;
/* In the event of a partial match, remove the specified perms from the 
 * entry */
						subtract_from_entry(rentry, modifier, &valid_perms);
						/* if no perms survived then delete the entry */
						if (valid_perms == 0)
							acl_delete_entry(oacl, rentry);
					}
				}
			}
			if (0 == match_found) {
                fprintf(stderr, "chmod: Entry not found when attempting delete '%s'\n",path);
                // warnx("Entry not found when attempting delete '%s'",path);
				retval = 1;
			}
		}
	} else if (optflags & ACL_REWRITE_FLAG) {
		acl_entry_t rentry;
		
		if (-1 == position) {
			chmod_usage();
		}
		if (0 == flag_new_acl) {
			if (0 != acl_get_entry(oacl, position,
                            &rentry)) {
				// err(1, "Invalid entry number '%s'", path);
                fprintf(stderr, "chmod: Invalid entry number '%s': %s\n", path, strerror(errno));
                pthread_exit(NULL);
            }
			
            if (0 != acl_delete_entry(oacl, rentry)) {
				// err(1, "Unable to delete entry '%s'", path);
                fprintf(stderr, "chmod: Unable to delete entry '%s': %s\n", path, strerror(errno));
                pthread_exit(NULL);
            }
		}
        if (0!= acl_create_entry_np(&oacl, &newent, position)) {
			// err(1, "acl_create_entry() failed");
            fprintf(stderr, "chmod: acl_create_entry() failed: %s\n", strerror(errno));
            pthread_exit(NULL);
        }
		acl_copy_entry(newent, modifier);
	}
ma_exit:
	*oaclp = oacl;
	return retval;
}