1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <errno.h>
33#include <stdio.h>
34#include <assert.h>
35#include <sys/acl.h>
36#include <sys/stat.h>
37
38#include "acl_support.h"
39
40/*
41 * These routines from sys/kern/subr_acl_nfs4.c are used by both kernel
42 * and libc.
43 */
44void	acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp);
45void	acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int file_owner_id,
46	    int canonical_six);
47
48static acl_t
49_nfs4_acl_strip_np(const acl_t aclp, int canonical_six)
50{
51	acl_t newacl;
52	mode_t mode = 0;
53
54	newacl = acl_init(ACL_MAX_ENTRIES);
55	if (newacl == NULL) {
56		errno = ENOMEM;
57		return (NULL);
58	}
59
60	_acl_brand_as(newacl, ACL_BRAND_NFS4);
61
62	acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl));
63	acl_nfs4_trivial_from_mode_libc(&(newacl->ats_acl), mode, canonical_six);
64
65	return (newacl);
66}
67
68static acl_t
69_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
70{
71	acl_t acl_new, acl_old;
72	acl_entry_t entry, entry_new;
73	acl_permset_t perm;
74	acl_tag_t tag;
75	int entry_id, have_mask_entry;
76
77	assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
78
79	acl_old = acl_dup(aclp);
80	if (acl_old == NULL)
81		return (NULL);
82
83	assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);
84
85	have_mask_entry = 0;
86	acl_new = acl_init(ACL_MAX_ENTRIES);
87	if (acl_new == NULL) {
88		acl_free(acl_old);
89		return (NULL);
90	}
91	tag = ACL_UNDEFINED_TAG;
92
93	/* only save the default user/group/other entries */
94	entry_id = ACL_FIRST_ENTRY;
95	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
96		entry_id = ACL_NEXT_ENTRY;
97
98		assert(_entry_brand(entry) == ACL_BRAND_POSIX);
99
100		if (acl_get_tag_type(entry, &tag) == -1)
101			goto fail;
102
103		switch(tag) {
104		case ACL_USER_OBJ:
105		case ACL_GROUP_OBJ:
106		case ACL_OTHER:
107			if (acl_get_tag_type(entry, &tag) == -1)
108				goto fail;
109			if (acl_get_permset(entry, &perm) == -1)
110				goto fail;
111			if (acl_create_entry(&acl_new, &entry_new) == -1)
112				goto fail;
113			if (acl_set_tag_type(entry_new, tag) == -1)
114				goto fail;
115			if (acl_set_permset(entry_new, perm) == -1)
116				goto fail;
117			if (acl_copy_entry(entry_new, entry) == -1)
118				goto fail;
119			assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
120			break;
121		case ACL_MASK:
122			have_mask_entry = 1;
123			break;
124		default:
125			break;
126		}
127	}
128
129	assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);
130
131	if (have_mask_entry && recalculate_mask) {
132		if (acl_calc_mask(&acl_new) == -1)
133			goto fail;
134	}
135
136	return (acl_new);
137
138fail:
139	acl_free(acl_new);
140	acl_free(acl_old);
141
142	return (NULL);
143}
144
145acl_t
146acl_strip_np(const acl_t aclp, int recalculate_mask)
147{
148	switch (_acl_brand(aclp)) {
149	case ACL_BRAND_NFS4:
150		return (_nfs4_acl_strip_np(aclp, 0));
151
152	case ACL_BRAND_POSIX:
153		return (_posix1e_acl_strip_np(aclp, recalculate_mask));
154
155	default:
156		errno = EINVAL;
157		return (NULL);
158	}
159}
160
161/*
162 * Return 1, if ACL is trivial, 0 otherwise.
163 *
164 * ACL is trivial, iff its meaning could be fully expressed using just file
165 * mode.  In other words, ACL is trivial iff it doesn't have "+" to the right
166 * of the mode bits in "ls -l" output ;-)
167 */
168int
169acl_is_trivial_np(const acl_t aclp, int *trivialp)
170{
171	acl_t tmpacl;
172	int differs;
173
174	if (aclp == NULL || trivialp == NULL) {
175		errno = EINVAL;
176		return (-1);
177	}
178
179	switch (_acl_brand(aclp)) {
180	case ACL_BRAND_POSIX:
181		if (aclp->ats_acl.acl_cnt == 3)
182			*trivialp = 1;
183		else
184			*trivialp = 0;
185
186		return (0);
187
188	case ACL_BRAND_NFS4:
189		/*
190		 * If the ACL has more than canonical six entries,
191		 * it's non trivial by definition.
192		 */
193		if (aclp->ats_acl.acl_cnt > 6) {
194			*trivialp = 0;
195			return (0);
196		}
197
198		/*
199		 * Calculate trivial ACL - using acl_strip_np(3) - and compare
200		 * with the original.
201		 */
202		tmpacl = _nfs4_acl_strip_np(aclp, 0);
203		if (tmpacl == NULL)
204			return (-1);
205
206		differs = _acl_differs(aclp, tmpacl);
207		acl_free(tmpacl);
208
209		if (differs == 0) {
210			*trivialp = 1;
211			return (0);
212		}
213
214		/*
215		 * Try again with an old-style, "canonical six" trivial ACL.
216		 */
217		tmpacl = _nfs4_acl_strip_np(aclp, 1);
218		if (tmpacl == NULL)
219			return (-1);
220
221		differs = _acl_differs(aclp, tmpacl);
222		acl_free(tmpacl);
223
224		if (differs)
225			*trivialp = 0;
226		else
227			*trivialp = 1;
228
229		return (0);
230
231	default:
232		errno = EINVAL;
233		return (-1);
234	}
235}
236