示例#1
0
文件: acl-util.c 项目: dankor/systemd
int calc_acl_mask_if_needed(acl_t *acl_p) {
        acl_entry_t i;
        int r;
        bool need = false;

        assert(acl_p);

        for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
             r > 0;
             r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
                acl_tag_t tag;

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

                if (tag == ACL_MASK)
                        return 0;

                if (IN_SET(tag, ACL_USER, ACL_GROUP))
                        need = true;
        }
        if (r < 0)
                return -errno;

        if (need && acl_calc_mask(acl_p) < 0)
                return -errno;

        return need;
}
示例#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;
}
示例#3
0
static acl_t
_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
{
	acl_t acl_new, acl_old;
	acl_entry_t entry, entry_new;
	acl_permset_t perm;
	acl_tag_t tag;
	int entry_id, have_mask_entry;

	assert(_acl_brand(aclp) == ACL_BRAND_POSIX);

	acl_old = acl_dup(aclp);
	if (acl_old == NULL)
		return (NULL);

	assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);

	have_mask_entry = 0;
	acl_new = acl_init(ACL_MAX_ENTRIES);
	if (acl_new == NULL)
		return (NULL);
	tag = ACL_UNDEFINED_TAG;

	/* only save the default user/group/other entries */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;

		assert(_entry_brand(entry) == ACL_BRAND_POSIX);

		if (acl_get_tag_type(entry, &tag) == -1)
			return (NULL);

		switch(tag) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_OTHER:
			if (acl_get_tag_type(entry, &tag) == -1)
				return (NULL);
			if (acl_get_permset(entry, &perm) == -1)
				return (NULL);
			if (acl_create_entry(&acl_new, &entry_new) == -1)
				return (NULL);
			if (acl_set_tag_type(entry_new, tag) == -1)
				return (NULL);
			if (acl_set_permset(entry_new, perm) == -1)
				return (NULL);
			if (acl_copy_entry(entry_new, entry) == -1)
				return (NULL);
			assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
			break;
		case ACL_MASK:
			have_mask_entry = 1;
			break;
		default:
			break;
		}
	}

	assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);

	if (have_mask_entry && recalculate_mask) {
		if (acl_calc_mask(&acl_new) == -1)
			return (NULL);
	}

	return (acl_new);
}
示例#4
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;
}
示例#5
0
文件: remove.c 项目: genua/anoubis_os
/*
 * remove extended entries
 */
void
remove_ext(acl_t *prev_acl)
{
	acl_t acl_new, acl_old;
	acl_entry_t entry, entry_new;
	acl_permset_t perm;
	acl_tag_t tag;
	int entry_id, have_mask_entry;

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

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

	have_mask_entry = 0;
	acl_new = acl_init(ACL_MAX_ENTRIES);
	if (acl_new == NULL)
		err(1, "acl_init() failed");

	tag = ACL_UNDEFINED_TAG;

	/* only save the default user/group/other entries */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;

		if (acl_get_tag_type(entry, &tag) == -1)
			err(1, "acl_get_tag_type() failed");

		switch(tag) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_OTHER:
			if (acl_get_tag_type(entry, &tag) == -1)
				err(1, "acl_get_tag_type() failed");
			if (acl_get_permset(entry, &perm) == -1)
				err(1, "acl_get_permset() failed");
			if (acl_create_entry(&acl_new, &entry_new) == -1)
				err(1, "acl_create_entry() failed");
			if (acl_set_tag_type(entry_new, tag) == -1)
				err(1, "acl_set_tag_type() failed");
			if (acl_set_permset(entry_new, perm) == -1)
				err(1, "acl_get_permset() failed");
			if (acl_copy_entry(entry_new, entry) == -1)
				err(1, "acl_copy_entry() failed");
			break;
		case ACL_MASK:
			have_mask_entry = 1;
			break;
		default:
			break;
		}
	}
	if (have_mask_entry && n_flag == 0) {
		if (acl_calc_mask(&acl_new) == -1)
			err(1, "acl_calc_mask() failed");
	} else {
		have_mask = 1;
	}

	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;
	}
}
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;
}
MateVFSResult 
file_set_acl (const char             *path,
	      const MateVFSFileInfo *info,
              MateVFSContext        *context)
{
#ifdef HAVE_SOLARIS_ACL
	GList           *acls;
	GList           *entry;
	guint            len;
	MateVFSResult   re;
	aclent_t        *new_aclp;
	aclent_t        *taclp;
	guint            aclp_i;
	gboolean         changed;

	if (info->acl == NULL) 
		return MATE_VFS_ERROR_BAD_PARAMETERS;

	acls = mate_vfs_acl_get_ace_list (info->acl);
	if (acls == NULL) return MATE_VFS_OK;

	changed = fixup_acl (info->acl, acls);	
	if (changed) {
		mate_vfs_acl_free_ace_list (acls);

		acls = mate_vfs_acl_get_ace_list (info->acl);
		if (acls == NULL) return MATE_VFS_OK;
	}

	len = g_list_length (acls);
	if (len <= 0) return MATE_VFS_OK;

	new_aclp = (aclent_t *) malloc (len * sizeof(aclent_t));
	if (new_aclp == NULL) return MATE_VFS_ERROR_NO_MEMORY;
	memset (new_aclp, 0, len * sizeof(aclent_t));

	aclp_i = 0;
	taclp  = new_aclp;
	for (entry=acls; entry != NULL; entry = entry->next) {
		MateVFSACE *ace = MATE_VFS_ACE(entry->data);
		
		re = translate_ace_into_aclent (ace, taclp);
		if (re != MATE_VFS_OK) continue;

		aclp_i++;
		taclp++;
	}

	/* Sort it out
	 */
 	re = aclsort (aclp_i, 0, (aclent_t *)new_aclp);
	if (re == -1) {
		g_free (new_aclp);
		return MATE_VFS_ERROR_INTERNAL;
	}		

	/* Commit it to the file system
	 */
	re = acl (path, SETACL, aclp_i, (aclent_t *)new_aclp); 
 	if (re < 0) {
		int err = errno;

		g_free (new_aclp);
		return aclerrno_to_vfserror(err);
	}

	g_free (new_aclp);
	return MATE_VFS_OK;
	
#elif defined(HAVE_POSIX_ACL)
	GList *acls;
	GList *entry;
	acl_t  acl_obj;
	acl_t  acl_obj_default;


	if (info->acl == NULL) 
		return MATE_VFS_ERROR_BAD_PARAMETERS;
	
	/* POSIX ACL object
	 */
	acl_obj_default = acl_get_file (path, ACL_TYPE_DEFAULT);     

	acl_obj = acl_get_file (path, ACL_TYPE_ACCESS);      
	if (acl_obj == NULL) return MATE_VFS_ERROR_GENERIC;

	/* Parse stored information
	 */
	acls = mate_vfs_acl_get_ace_list (info->acl);
	if (acls == NULL) return MATE_VFS_OK;

	for (entry=acls; entry != NULL; entry = entry->next) {
		MateVFSACE           *ace        = MATE_VFS_ACE(entry->data);
		gboolean               is_default = FALSE;
		const char            *id_str;
		MateVFSACLKind        kind;
		int                    id;

		int                    re;
		acl_tag_t              type;
		mode_t                 perms      = 0;
		acl_entry_t            new_entry  = NULL;
		acl_permset_t          permset    = NULL;
		
		id_str     = mate_vfs_ace_get_id (ace);
		kind       = mate_vfs_ace_get_kind (ace);
		is_default = mate_vfs_ace_get_inherit (ace);
		
		/* Perms
		 */
		if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_READ))
			perms |= CMD_PERM_READ;
		else if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_WRITE))
			perms |= CMD_PERM_WRITE;
		else if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_EXECUTE))
			perms |= CMD_PERM_EXECUTE;
		
		/* Type
		 */
		switch (kind) {
		case MATE_VFS_ACL_USER:
			id   = string_to_uid (id_str);
			type = ACL_USER;			
			break;

		case MATE_VFS_ACL_GROUP:
			id   = string_to_gid (id_str);
			type = ACL_GROUP;
			break;

		case MATE_VFS_ACL_OTHER:
			type = ACL_OTHER;
			break;

		default:
			return MATE_VFS_ERROR_NOT_SUPPORTED;			
		}

		/* Add the entry
		 */
		new_entry = find_entry (acl_obj, type, id);
		if (new_entry == NULL) {
			/* new */
			if (is_default)
				re = acl_create_entry (&acl_obj_default, &new_entry);
			else
				re = acl_create_entry (&acl_obj, &new_entry);
			if (re != 0) return aclerrno_to_vfserror (errno);
			
			/* e_tag */
			re = acl_set_tag_type (new_entry, type);
			if (re != 0) return aclerrno_to_vfserror (errno);
			
			/* e_id */
			re = acl_set_qualifier (new_entry, &id);
			if (re != 0) return aclerrno_to_vfserror (errno);
		}

		/* e_perm */
		re = acl_get_permset (new_entry, &permset);
		if (re != 0) return aclerrno_to_vfserror (errno);
		set_permset (permset, perms);

		/* Fix it up
		 */
		if (is_default && (acl_obj_default != NULL)) {
			if (! find_entry (acl_obj_default, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
				clone_entry (acl_obj, ACL_USER_OBJ, &acl_obj_default, ACL_USER_OBJ);
			}
			
			if (! find_entry (acl_obj_default, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
				clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj_default, ACL_GROUP_OBJ);
			}
			
			if (! find_entry (acl_obj_default, ACL_OTHER, ACL_UNDEFINED_ID)) {
				clone_entry (acl_obj, ACL_OTHER, &acl_obj_default, ACL_OTHER);
			}			
		}
		
		if (acl_equiv_mode (acl_obj, NULL) != 0) {

			if (! find_entry (acl_obj, ACL_MASK, ACL_UNDEFINED_ID)) {                       
				clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj, ACL_MASK);
			}

			if (is_default)
				re = acl_calc_mask (&acl_obj_default);
			else 
				re = acl_calc_mask (&acl_obj);

			if (re != 0) return aclerrno_to_vfserror (errno);
		}
	}
		
	mate_vfs_acl_free_ace_list (acls);
	return MATE_VFS_OK;
#else
	return MATE_VFS_ERROR_NOT_SUPPORTED;
#endif
}
示例#8
0
文件: acl_posix.c 项目: ajlill/core
static int CheckPosixLinuxACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, acl_type_t acl_type, Attributes a,
                               const Promise *pp, PromiseResult *result)
{
    acl_t acl_existing;
    acl_t acl_new;
    acl_t acl_tmp;
    acl_entry_t ace_parsed;
    acl_entry_t ace_current;
    acl_permset_t perms;
    char *cf_ace;
    int retv;
    int has_mask;
    Rlist *rp;
    char *acl_type_str;

    acl_new = NULL;
    acl_existing = NULL;
    acl_tmp = NULL;
    has_mask = false;

    acl_type_str = acl_type == ACL_TYPE_ACCESS ? "Access" : "Default";

// read existing acl

    if ((acl_existing = acl_get_file(file_path, acl_type)) == NULL)
    {
        Log(LOG_LEVEL_VERBOSE, "No ACL for '%s' could be read. (acl_get_file: %s)", file_path, GetErrorStr());
        return false;
    }

// allocate memory for temp ace (it needs to reside in a temp acl)

    if ((acl_tmp = acl_init(1)) == NULL)
    {
        Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr());
        acl_free((void *) acl_existing);
        return false;
    }

    if (acl_create_entry(&acl_tmp, &ace_parsed) != 0)
    {
        Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_create_entry: %s)", GetErrorStr());
        acl_free((void *) acl_existing);
        acl_free((void *) acl_tmp);
        return false;
    }

// copy existing aces if we are appending

    if (method == ACL_METHOD_APPEND)
    {
        if ((acl_new = acl_dup(acl_existing)) == NULL)
        {
            Log(LOG_LEVEL_ERR, "Error copying existing ACL (acl_dup: %s)", GetErrorStr());
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            return false;
        }
    }
    else                        // overwrite existing acl
    {
        if ((acl_new = acl_init(5)) == NULL)    // TODO: Always OK with 5 here ?
        {
            Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr());
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            return false;
        }
    }

    for (rp = aces; rp != NULL; rp = rp->next)
    {
        cf_ace = RlistScalarValue(rp);

        if (!ParseEntityPosixLinux(&cf_ace, ace_parsed, &has_mask))
        {
            Log(LOG_LEVEL_ERR, "Error parsing entity in 'cf_ace'.");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        // check if an ACE with this entity-type and id already exist in the Posix Linux ACL

        ace_current = FindACE(acl_new, ace_parsed);

        // create new entry in ACL if it did not exist

        if (ace_current == NULL)
        {
            if (acl_create_entry(&acl_new, &ace_current) != 0)
            {
                Log(LOG_LEVEL_ERR, "Failed to allocate ace (acl_create_entry: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            // copy parsed entity-type and id

            if (acl_copy_entry(ace_current, ace_parsed) != 0)
            {
                Log(LOG_LEVEL_ERR, "Error copying Linux entry in 'cf_ace' (acl_copy_entry: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            // clear ace_current's permissions to avoid ace_parsed from last
            // loop iteration to be taken into account when applying mode below
            if ((acl_get_permset(ace_current, &perms) != 0))
            {
                Log(LOG_LEVEL_ERR, "Error obtaining permset for 'ace_current' (acl_get_permset: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            if (acl_clear_perms(perms) != 0)
            {
                Log(LOG_LEVEL_ERR, "Error clearing permset for 'ace_current'. (acl_clear_perms: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }
        }

        // mode string should be prefixed with an entry seperator

        if (*cf_ace != ':')
        {
            Log(LOG_LEVEL_ERR, "No separator before mode-string in 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        cf_ace += 1;

        if (acl_get_permset(ace_current, &perms) != 0)
        {
            Log(LOG_LEVEL_ERR, "Error obtaining permset for 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        if (!ParseModePosixLinux(cf_ace, perms))
        {
            Log(LOG_LEVEL_ERR, "Error parsing mode-string in 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        // only allow permissions exist on posix acls, so we do
        // not check what follows next
    }

// if no mask exists, calculate one (or both?): run acl_calc_mask and add one
    if (!has_mask)
    {
        if (acl_calc_mask(&acl_new) != 0)
        {
            Log(LOG_LEVEL_ERR, "Error calculating new acl mask");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }
    }

    if ((retv = ACLEquals(acl_existing, acl_new)) == -1)
    {
        Log(LOG_LEVEL_ERR, "Error while comparing existing and new ACL, unable to repair.");
        acl_free((void *) acl_existing);
        acl_free((void *) acl_tmp);
        acl_free((void *) acl_new);
        return false;
    }

    if (retv == 1)              // existing and new acl differ, update existing
    {

        switch (a.transaction.action)
        {
        case cfa_warn:

            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "%s ACL on file '%s' needs to be updated", acl_type_str, file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN);
            break;

        case cfa_fix:

            if (!DONTDO)
            {
                if ((retv = acl_set_file(file_path, acl_type, acl_new)) != 0)
                {
                    Log(LOG_LEVEL_ERR, "Error setting new %s ACL on file '%s' (acl_set_file: %s), are required ACEs present ?",
                          acl_type_str, file_path, GetErrorStr());
                    acl_free((void *) acl_existing);
                    acl_free((void *) acl_tmp);
                    acl_free((void *) acl_new);
                    return false;
                }
            }

            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "%s ACL on '%s' successfully changed.", acl_type_str, file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE);

            break;

        default:
            ProgrammingError("CFEngine: internal error: illegal file action");
        }

    }
    else
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "'%s' ACL on '%s' needs no modification.", acl_type_str, file_path);
    }

    acl_free((void *) acl_existing);
    acl_free((void *) acl_new);
    acl_free((void *) acl_tmp);
    return true;
}
示例#9
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;
}
示例#10
0
/* set the appropriate mask the given ACL's */
int
set_acl_mask(acl_t *prev_acl, const char *filename)
{
	acl_entry_t entry;
	acl_t acl;
	acl_tag_t tag;
	int entry_id;

	entry = NULL;

	/*
	 * ... if a mask entry is specified, then the permissions of the mask
	 * entry in the resulting ACL shall be set to the permissions in the
	 * specified ACL mask entry.
	 */
	if (have_mask)
		return (0);

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

	if (n_flag == 0) {
		/*
		 * If no mask entry is specified and the -n option is not
		 * specified, then the permissions of the resulting ACL mask
		 * entry shall be set to the union of the permissions
		 * associated with all entries which belong to the file group
		 * class in the resulting ACL
		 */
		if (acl_calc_mask(&acl)) {
			warn("%s: acl_calc_mask() failed", filename);
			acl_free(acl);
			return (-1);
		}
	} else {
		/*
		 * If no mask entry is specified and the -n option is
		 * specified, then the permissions of the resulting ACL
		 * mask entry shall remain unchanged ...
		 */

		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) {
				acl_free(acl);
				return (0);
			}
		}

		/*
		 * If no mask entry is specified, the -n option is specified,
		 * and no ACL mask entry exists in the ACL associated with the
		 * file, then write an error message to standard error and
		 * continue with the next file.
		 */
		warnx("%s: warning: no mask entry", filename);
		acl_free(acl);
		return (0);
	}

	acl_free(*prev_acl);
	*prev_acl = acl_dup(acl);
	acl_free(acl);

	return (0);
}
示例#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);
}