1139969Simp/*-
274465Srwatson * Copyright (c) 2001 Chris D. Faulhaber
374465Srwatson * All rights reserved.
474465Srwatson *
574465Srwatson * Redistribution and use in source and binary forms, with or without
674465Srwatson * modification, are permitted provided that the following conditions
774465Srwatson * are met:
874465Srwatson * 1. Redistributions of source code must retain the above copyright
974465Srwatson *    notice, this list of conditions and the following disclaimer.
1074465Srwatson * 2. Redistributions in binary form must reproduce the above copyright
1174465Srwatson *    notice, this list of conditions and the following disclaimer in the
1274465Srwatson *    documentation and/or other materials provided with the distribution.
1374465Srwatson *
1474465Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1574465Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1674465Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17204819Sjoel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18204819Sjoel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19204819Sjoel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20204819Sjoel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21204819Sjoel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22204819Sjoel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23204819Sjoel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24204819Sjoel * SUCH DAMAGE.
2574465Srwatson */
2674465Srwatson
2799110Sobrien#include <sys/cdefs.h>
2899110Sobrien__FBSDID("$FreeBSD$");
2999110Sobrien
3074465Srwatson#include <sys/types.h>
3174465Srwatson#include <sys/acl.h>
3274465Srwatson#include <sys/stat.h>
3374465Srwatson
3474465Srwatson#include <err.h>
3574465Srwatson#include <stdio.h>
3674465Srwatson#include <string.h>
3774465Srwatson
3874465Srwatson#include "setfacl.h"
3974465Srwatson
4087254Sjedgar/*
4187254Sjedgar * remove ACL entries from an ACL
4287254Sjedgar */
4374465Srwatsonint
44196936Straszremove_acl(acl_t acl, acl_t *prev_acl, const char *filename)
4574465Srwatson{
4675928Sjedgar	acl_entry_t	entry;
4775928Sjedgar	acl_t		acl_new;
4875928Sjedgar	acl_tag_t	tag;
49196936Strasz	int		carried_error, entry_id, acl_brand, prev_acl_brand;
5074465Srwatson
5174465Srwatson	carried_error = 0;
5274465Srwatson
53196936Strasz	acl_get_brand_np(acl, &acl_brand);
54196936Strasz	acl_get_brand_np(*prev_acl, &prev_acl_brand);
55196936Strasz
56201016Strasz	if (branding_mismatch(acl_brand, prev_acl_brand)) {
57196936Strasz		warnx("%s: branding mismatch; existing ACL is %s, "
58196936Strasz		    "entry to be removed is %s", filename,
59201016Strasz		    brand_name(prev_acl_brand), brand_name(acl_brand));
60196936Strasz		return (-1);
61196936Strasz	}
62196936Strasz
63196936Strasz	carried_error = 0;
64196936Strasz
65196936Strasz	acl_new = acl_dup(*prev_acl);
6687254Sjedgar	if (acl_new == NULL)
67196936Strasz		err(1, "%s: acl_dup() failed", filename);
6874465Srwatson
6975928Sjedgar	tag = ACL_UNDEFINED_TAG;
7075928Sjedgar
7174465Srwatson	/* find and delete the entry */
7275928Sjedgar	entry_id = ACL_FIRST_ENTRY;
7375928Sjedgar	while (acl_get_entry(acl, entry_id, &entry) == 1) {
7475928Sjedgar		entry_id = ACL_NEXT_ENTRY;
7575928Sjedgar		if (acl_get_tag_type(entry, &tag) == -1)
76196936Strasz			err(1, "%s: acl_get_tag_type() failed", filename);
7775928Sjedgar		if (tag == ACL_MASK)
7874465Srwatson			have_mask++;
7975928Sjedgar		if (acl_delete_entry(acl_new, entry) == -1) {
8074465Srwatson			carried_error++;
81196936Strasz			warnx("%s: cannot remove non-existent ACL entry",
82196936Strasz			    filename);
8374465Srwatson		}
8474465Srwatson	}
8574465Srwatson
86196936Strasz	acl_free(*prev_acl);
87196936Strasz	*prev_acl = acl_new;
88196936Strasz
89196936Strasz	if (carried_error)
90196936Strasz		return (-1);
91196936Strasz
92196936Strasz	return (0);
93196936Strasz}
94196936Strasz
95196936Straszint
96196936Straszremove_by_number(uint entry_number, acl_t *prev_acl, const char *filename)
97196936Strasz{
98196936Strasz	acl_entry_t	entry;
99196936Strasz	acl_t		acl_new;
100196936Strasz	acl_tag_t	tag;
101196936Strasz	int		carried_error, entry_id;
102196936Strasz	uint		i;
103196936Strasz
104196936Strasz	carried_error = 0;
105196936Strasz
106196936Strasz	acl_new = acl_dup(*prev_acl);
107196936Strasz	if (acl_new == NULL)
108196936Strasz		err(1, "%s: acl_dup() failed", filename);
109196936Strasz
110196936Strasz	tag = ACL_UNDEFINED_TAG;
111196936Strasz
112196936Strasz	/*
113196936Strasz	 * Find out whether we're removing the mask entry,
114196936Strasz	 * to behave the same as the routine above.
115196936Strasz	 *
116196936Strasz	 * XXX: Is this loop actually needed?
117196936Strasz	 */
118196936Strasz	entry_id = ACL_FIRST_ENTRY;
119196936Strasz	i = 0;
120196936Strasz	while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
121196936Strasz		entry_id = ACL_NEXT_ENTRY;
122196936Strasz		if (i != entry_number)
123196936Strasz			continue;
124196936Strasz		if (acl_get_tag_type(entry, &tag) == -1)
125196936Strasz			err(1, "%s: acl_get_tag_type() failed", filename);
126196936Strasz		if (tag == ACL_MASK)
127196936Strasz			have_mask++;
12874465Srwatson	}
12974465Srwatson
130196936Strasz	if (acl_delete_entry_np(acl_new, entry_number) == -1) {
131196936Strasz		carried_error++;
132196936Strasz		warn("%s: acl_delete_entry_np() failed", filename);
133196936Strasz	}
134196936Strasz
135196936Strasz	acl_free(*prev_acl);
136196936Strasz	*prev_acl = acl_new;
137196936Strasz
13874465Srwatson	if (carried_error)
13987254Sjedgar		return (-1);
14074465Srwatson
14187254Sjedgar	return (0);
14274465Srwatson}
14374465Srwatson
14487254Sjedgar/*
14587254Sjedgar * remove default entries
14687254Sjedgar */
14774465Srwatsonint
148196936Straszremove_default(acl_t *prev_acl, const char *filename)
14974465Srwatson{
15074465Srwatson
151196936Strasz	acl_free(*prev_acl);
152196936Strasz	*prev_acl = acl_init(ACL_MAX_ENTRIES);
153196936Strasz	if (*prev_acl == NULL)
154196936Strasz		err(1, "%s: acl_init() failed", filename);
155196936Strasz
15687254Sjedgar	return (0);
15774465Srwatson}
15874465Srwatson
15987254Sjedgar/*
16087254Sjedgar * remove extended entries
16187254Sjedgar */
16274465Srwatsonvoid
163196936Straszremove_ext(acl_t *prev_acl, const char *filename)
16474465Srwatson{
165196936Strasz	acl_t acl_new;
16674465Srwatson
167196936Strasz	acl_new = acl_strip_np(*prev_acl, !n_flag);
16887254Sjedgar	if (acl_new == NULL)
169196936Strasz		err(1, "%s: acl_strip_np() failed", filename);
17074465Srwatson
171196936Strasz	acl_free(*prev_acl);
172196936Strasz	*prev_acl = acl_new;
17374465Srwatson}
174