xref: /freebsd/bin/setfacl/remove.c (revision 39beb93c)
1 /*-
2  * Copyright (c) 2001 Chris D. Faulhaber
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/types.h>
31 #include <sys/acl.h>
32 #include <sys/stat.h>
33 
34 #include <err.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "setfacl.h"
39 
40 /*
41  * remove ACL entries from an ACL
42  */
43 int
44 remove_acl(acl_t acl, acl_t *prev_acl)
45 {
46 	acl_entry_t	entry;
47 	acl_t		acl_new;
48 	acl_tag_t	tag;
49 	int		carried_error, entry_id;
50 
51 	carried_error = 0;
52 
53 	if (acl_type == ACL_TYPE_ACCESS)
54 		acl_new = acl_dup(prev_acl[ACCESS_ACL]);
55 	else
56 		acl_new = acl_dup(prev_acl[DEFAULT_ACL]);
57 	if (acl_new == NULL)
58 		err(1, "acl_dup() failed");
59 
60 	tag = ACL_UNDEFINED_TAG;
61 
62 	/* find and delete the entry */
63 	entry_id = ACL_FIRST_ENTRY;
64 	while (acl_get_entry(acl, entry_id, &entry) == 1) {
65 		entry_id = ACL_NEXT_ENTRY;
66 		if (acl_get_tag_type(entry, &tag) == -1)
67 			err(1, "acl_get_tag_type() failed");
68 		if (tag == ACL_MASK)
69 			have_mask++;
70 		if (acl_delete_entry(acl_new, entry) == -1) {
71 			carried_error++;
72 			warnx("cannot remove non-existent acl entry");
73 		}
74 	}
75 
76 	if (acl_type == ACL_TYPE_ACCESS) {
77 		acl_free(prev_acl[ACCESS_ACL]);
78 		prev_acl[ACCESS_ACL] = acl_new;
79 	} else {
80 		acl_free(prev_acl[DEFAULT_ACL]);
81 		prev_acl[DEFAULT_ACL] = acl_new;
82 	}
83 
84 	if (carried_error)
85 		return (-1);
86 
87 	return (0);
88 }
89 
90 /*
91  * remove default entries
92  */
93 int
94 remove_default(acl_t *prev_acl)
95 {
96 
97 	if (prev_acl[1]) {
98 		acl_free(prev_acl[1]);
99 		prev_acl[1] = acl_init(ACL_MAX_ENTRIES);
100 		if (prev_acl[1] == NULL)
101 			err(1, "acl_init() failed");
102 	} else {
103 		warn("cannot remove default ACL");
104 		return (-1);
105 	}
106 	return (0);
107 }
108 
109 /*
110  * remove extended entries
111  */
112 void
113 remove_ext(acl_t *prev_acl)
114 {
115 	acl_t acl_new, acl_old;
116 	acl_entry_t entry, entry_new;
117 	acl_permset_t perm;
118 	acl_tag_t tag;
119 	int entry_id, have_mask_entry;
120 
121 	if (acl_type == ACL_TYPE_ACCESS)
122 		acl_old = acl_dup(prev_acl[ACCESS_ACL]);
123 	else
124 		acl_old = acl_dup(prev_acl[DEFAULT_ACL]);
125 	if (acl_old == NULL)
126 		err(1, "acl_dup() failed");
127 
128 	have_mask_entry = 0;
129 	acl_new = acl_init(ACL_MAX_ENTRIES);
130 	if (acl_new == NULL)
131 		err(1, "acl_init() failed");
132 	tag = ACL_UNDEFINED_TAG;
133 
134 	/* only save the default user/group/other entries */
135 	entry_id = ACL_FIRST_ENTRY;
136 	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
137 		entry_id = ACL_NEXT_ENTRY;
138 
139 		if (acl_get_tag_type(entry, &tag) == -1)
140 			err(1, "acl_get_tag_type() failed");
141 
142 		switch(tag) {
143 		case ACL_USER_OBJ:
144 		case ACL_GROUP_OBJ:
145 		case ACL_OTHER:
146 			if (acl_get_tag_type(entry, &tag) == -1)
147 				err(1, "acl_get_tag_type() failed");
148 			if (acl_get_permset(entry, &perm) == -1)
149 				err(1, "acl_get_permset() failed");
150 			if (acl_create_entry(&acl_new, &entry_new) == -1)
151 				err(1, "acl_create_entry() failed");
152 			if (acl_set_tag_type(entry_new, tag) == -1)
153 				err(1, "acl_set_tag_type() failed");
154 			if (acl_set_permset(entry_new, perm) == -1)
155 				err(1, "acl_get_permset() failed");
156 			if (acl_copy_entry(entry_new, entry) == -1)
157 				err(1, "acl_copy_entry() failed");
158 			break;
159 		case ACL_MASK:
160 			have_mask_entry = 1;
161 			break;
162 		default:
163 			break;
164 		}
165 	}
166 	if (have_mask_entry && n_flag == 0) {
167 		if (acl_calc_mask(&acl_new) == -1)
168 			err(1, "acl_calc_mask() failed");
169 	} else {
170 		have_mask = 1;
171 	}
172 
173 	if (acl_type == ACL_TYPE_ACCESS) {
174 		acl_free(prev_acl[ACCESS_ACL]);
175 		prev_acl[ACCESS_ACL] = acl_new;
176 	} else {
177 		acl_free(prev_acl[DEFAULT_ACL]);
178 		prev_acl[DEFAULT_ACL] = acl_new;
179 	}
180 }
181