xref: /freebsd/bin/setfacl/remove.c (revision 32cd3ee5901ea33d41ff550e5f40ce743c8d4165)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2001 Chris D. Faulhaber
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/acl.h>
31 #include <sys/stat.h>
32 
33 #include <err.h>
34 
35 #include "setfacl.h"
36 
37 /*
38  * remove ACL entries from an ACL
39  */
40 int
41 remove_acl(acl_t acl, acl_t *prev_acl, const char *filename)
42 {
43 	acl_entry_t	entry;
44 	acl_t		acl_new;
45 	acl_tag_t	tag;
46 	int		carried_error, entry_id, acl_brand, prev_acl_brand;
47 
48 	carried_error = 0;
49 
50 	acl_get_brand_np(acl, &acl_brand);
51 	acl_get_brand_np(*prev_acl, &prev_acl_brand);
52 
53 	if (branding_mismatch(acl_brand, prev_acl_brand)) {
54 		warnx("%s: branding mismatch; existing ACL is %s, "
55 		    "entry to be removed is %s", filename,
56 		    brand_name(prev_acl_brand), brand_name(acl_brand));
57 		return (-1);
58 	}
59 
60 	carried_error = 0;
61 
62 	acl_new = acl_dup(*prev_acl);
63 	if (acl_new == NULL)
64 		err(1, "%s: acl_dup() failed", filename);
65 
66 	tag = ACL_UNDEFINED_TAG;
67 
68 	/* find and delete the entry */
69 	entry_id = ACL_FIRST_ENTRY;
70 	while (acl_get_entry(acl, entry_id, &entry) == 1) {
71 		entry_id = ACL_NEXT_ENTRY;
72 		if (acl_get_tag_type(entry, &tag) == -1)
73 			err(1, "%s: acl_get_tag_type() failed", filename);
74 		if (tag == ACL_MASK)
75 			have_mask = true;
76 		if (acl_delete_entry(acl_new, entry) == -1) {
77 			carried_error++;
78 			warnx("%s: cannot remove non-existent ACL entry",
79 			    filename);
80 		}
81 	}
82 
83 	acl_free(*prev_acl);
84 	*prev_acl = acl_new;
85 
86 	if (carried_error)
87 		return (-1);
88 
89 	return (0);
90 }
91 
92 int
93 remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename)
94 {
95 	acl_entry_t	entry;
96 	acl_t		acl_new;
97 	acl_tag_t	tag;
98 	int		carried_error, entry_id;
99 	uint		i;
100 
101 	carried_error = 0;
102 
103 	acl_new = acl_dup(*prev_acl);
104 	if (acl_new == NULL)
105 		err(1, "%s: acl_dup() failed", filename);
106 
107 	tag = ACL_UNDEFINED_TAG;
108 
109 	/*
110 	 * Find out whether we're removing the mask entry,
111 	 * to behave the same as the routine above.
112 	 *
113 	 * XXX: Is this loop actually needed?
114 	 */
115 	entry_id = ACL_FIRST_ENTRY;
116 	i = 0;
117 	while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
118 		entry_id = ACL_NEXT_ENTRY;
119 		if (i != entry_number)
120 			continue;
121 		if (acl_get_tag_type(entry, &tag) == -1)
122 			err(1, "%s: acl_get_tag_type() failed", filename);
123 		if (tag == ACL_MASK)
124 			have_mask = true;
125 	}
126 
127 	if (acl_delete_entry_np(acl_new, entry_number) == -1) {
128 		carried_error++;
129 		warn("%s: acl_delete_entry_np() failed", filename);
130 	}
131 
132 	acl_free(*prev_acl);
133 	*prev_acl = acl_new;
134 
135 	if (carried_error)
136 		return (-1);
137 
138 	return (0);
139 }
140 
141 /*
142  * remove default entries
143  */
144 int
145 remove_default(acl_t *prev_acl, const char *filename)
146 {
147 
148 	acl_free(*prev_acl);
149 	*prev_acl = acl_init(ACL_MAX_ENTRIES);
150 	if (*prev_acl == NULL)
151 		err(1, "%s: acl_init() failed", filename);
152 
153 	return (0);
154 }
155 
156 /*
157  * remove extended entries
158  */
159 void
160 remove_ext(acl_t *prev_acl, const char *filename)
161 {
162 	acl_t acl_new;
163 
164 	acl_new = acl_strip_np(*prev_acl, !n_flag);
165 	if (acl_new == NULL)
166 		err(1, "%s: acl_strip_np() failed", filename);
167 
168 	acl_free(*prev_acl);
169 	*prev_acl = acl_new;
170 }
171