opensolaris_acl.c revision 216084
1192800Strasz/*-
2192800Strasz * Copyright (c) 2008, 2009 Edward Tomasz Napiera��a <trasz@FreeBSD.org>
3192800Strasz * All rights reserved.
4192800Strasz *
5192800Strasz * Redistribution and use in source and binary forms, with or without
6192800Strasz * modification, are permitted provided that the following conditions
7192800Strasz * are met:
8192800Strasz * 1. Redistributions of source code must retain the above copyright
9192800Strasz *    notice, this list of conditions and the following disclaimer.
10192800Strasz * 2. Redistributions in binary form must reproduce the above copyright
11192800Strasz *    notice, this list of conditions and the following disclaimer in the
12192800Strasz *    documentation and/or other materials provided with the distribution.
13192800Strasz *
14192804Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15192804Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16192804Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17192804Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18192804Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19192804Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20192804Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21192804Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22192804Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23192804Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24192804Strasz * SUCH DAMAGE.
25192800Strasz */
26192800Strasz
27192800Strasz#include <sys/cdefs.h>
28192800Strasz__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_acl.c 216084 2010-11-30 21:04:05Z trasz $");
29192800Strasz
30192800Strasz#include <sys/param.h>
31192800Strasz#include <sys/systm.h>
32192800Strasz#include <sys/types.h>
33192800Strasz#include <sys/malloc.h>
34192800Strasz#include <sys/errno.h>
35192800Strasz#include <sys/zfs_acl.h>
36192800Strasz#include <sys/acl.h>
37192800Strasz
38192800Straszstruct zfs2bsd {
39192800Strasz	uint32_t	zb_zfs;
40192800Strasz	int		zb_bsd;
41192800Strasz};
42192800Strasz
43192800Straszstruct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA},
44192800Strasz			{ACE_WRITE_DATA, ACL_WRITE_DATA},
45192800Strasz			{ACE_EXECUTE, ACL_EXECUTE},
46192800Strasz			{ACE_APPEND_DATA, ACL_APPEND_DATA},
47192800Strasz			{ACE_DELETE_CHILD, ACL_DELETE_CHILD},
48192800Strasz			{ACE_DELETE, ACL_DELETE},
49192800Strasz			{ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
50192800Strasz			{ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
51192800Strasz			{ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
52192800Strasz			{ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
53192800Strasz			{ACE_READ_ACL, ACL_READ_ACL},
54192800Strasz			{ACE_WRITE_ACL, ACL_WRITE_ACL},
55192800Strasz			{ACE_WRITE_OWNER, ACL_WRITE_OWNER},
56192800Strasz			{ACE_SYNCHRONIZE, ACL_SYNCHRONIZE},
57192800Strasz			{0, 0}};
58192800Strasz
59192800Straszstruct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE,
60192800Strasz			    ACL_ENTRY_FILE_INHERIT},
61192800Strasz			{ACE_DIRECTORY_INHERIT_ACE,
62192800Strasz			    ACL_ENTRY_DIRECTORY_INHERIT},
63192800Strasz			{ACE_NO_PROPAGATE_INHERIT_ACE,
64192800Strasz			    ACL_ENTRY_NO_PROPAGATE_INHERIT},
65192800Strasz			{ACE_INHERIT_ONLY_ACE,
66192800Strasz			    ACL_ENTRY_INHERIT_ONLY},
67192800Strasz			{ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
68192800Strasz			    ACL_ENTRY_SUCCESSFUL_ACCESS},
69192800Strasz			{ACE_FAILED_ACCESS_ACE_FLAG,
70192800Strasz			    ACL_ENTRY_FAILED_ACCESS},
71192800Strasz			{0, 0}};
72192800Strasz
73192800Straszstatic int
74192800Strasz_bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table)
75192800Strasz{
76192800Strasz	const struct zfs2bsd *tmp;
77192800Strasz	int bsd = 0;
78192800Strasz
79192800Strasz	for (tmp = table; tmp->zb_zfs != 0; tmp++) {
80192800Strasz		if (zfs & tmp->zb_zfs)
81192800Strasz			bsd |= tmp->zb_bsd;
82192800Strasz	}
83192800Strasz
84192800Strasz	return (bsd);
85192800Strasz}
86192800Strasz
87192800Straszstatic uint32_t
88192800Strasz_zfs_from_bsd(int bsd, const struct zfs2bsd *table)
89192800Strasz{
90192800Strasz	const struct zfs2bsd *tmp;
91192800Strasz	uint32_t zfs = 0;
92192800Strasz
93192800Strasz	for (tmp = table; tmp->zb_bsd != 0; tmp++) {
94192800Strasz		if (bsd & tmp->zb_bsd)
95192800Strasz			zfs |= tmp->zb_zfs;
96192800Strasz	}
97192800Strasz
98192800Strasz	return (zfs);
99192800Strasz}
100192800Strasz
101192800Straszint
102192800Straszacl_from_aces(struct acl *aclp, const ace_t *aces, int nentries)
103192800Strasz{
104192800Strasz	int i;
105192800Strasz	struct acl_entry *entry;
106192800Strasz	const ace_t *ace;
107192800Strasz
108216084Strasz	if (nentries < 1) {
109216084Strasz		printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n");
110216084Strasz		return (EINVAL);
111216084Strasz	}
112192800Strasz
113192800Strasz	if (nentries > ACL_MAX_ENTRIES) {
114192800Strasz		/*
115192800Strasz		 * I believe it may happen only when moving a pool
116192800Strasz		 * from SunOS to FreeBSD.
117192800Strasz		 */
118192800Strasz		printf("acl_from_aces: ZFS ACL too big to fit "
119192800Strasz		    "into 'struct acl'; returning EINVAL.\n");
120192800Strasz		return (EINVAL);
121192800Strasz	}
122192800Strasz
123192800Strasz	bzero(aclp, sizeof(*aclp));
124192800Strasz	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
125192800Strasz	aclp->acl_cnt = nentries;
126192800Strasz
127192800Strasz	for (i = 0; i < nentries; i++) {
128192800Strasz		entry = &(aclp->acl_entry[i]);
129192800Strasz		ace = &(aces[i]);
130192800Strasz
131192800Strasz		if (ace->a_flags & ACE_OWNER)
132192800Strasz			entry->ae_tag = ACL_USER_OBJ;
133192800Strasz		else if (ace->a_flags & ACE_GROUP)
134192800Strasz			entry->ae_tag = ACL_GROUP_OBJ;
135192800Strasz		else if (ace->a_flags & ACE_EVERYONE)
136192800Strasz			entry->ae_tag = ACL_EVERYONE;
137192800Strasz		else if (ace->a_flags & ACE_IDENTIFIER_GROUP)
138192800Strasz			entry->ae_tag = ACL_GROUP;
139192800Strasz		else
140192800Strasz			entry->ae_tag = ACL_USER;
141192800Strasz
142192800Strasz		if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP)
143192800Strasz			entry->ae_id = ace->a_who;
144192800Strasz		else
145192800Strasz			entry->ae_id = ACL_UNDEFINED_ID;
146192800Strasz
147192800Strasz		entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms);
148192800Strasz		entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags);
149192800Strasz
150192800Strasz		switch (ace->a_type) {
151192800Strasz		case ACE_ACCESS_ALLOWED_ACE_TYPE:
152192800Strasz			entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
153192800Strasz			break;
154192800Strasz		case ACE_ACCESS_DENIED_ACE_TYPE:
155192800Strasz			entry->ae_entry_type = ACL_ENTRY_TYPE_DENY;
156192800Strasz			break;
157192800Strasz		case ACE_SYSTEM_AUDIT_ACE_TYPE:
158192800Strasz			entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
159192800Strasz			break;
160192800Strasz		case ACE_SYSTEM_ALARM_ACE_TYPE:
161192800Strasz			entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
162192800Strasz			break;
163192800Strasz		default:
164192800Strasz			panic("acl_from_aces: a_type is 0x%x", ace->a_type);
165192800Strasz		}
166192800Strasz	}
167192800Strasz
168192800Strasz	return (0);
169192800Strasz}
170192800Strasz
171192800Straszvoid
172192800Straszaces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp)
173192800Strasz{
174192800Strasz	int i;
175192800Strasz	const struct acl_entry *entry;
176192800Strasz	ace_t *ace;
177192800Strasz
178192800Strasz	bzero(aces, sizeof(*aces) * aclp->acl_cnt);
179192800Strasz
180192800Strasz	*nentries = aclp->acl_cnt;
181192800Strasz
182192800Strasz	for (i = 0; i < aclp->acl_cnt; i++) {
183192800Strasz		entry = &(aclp->acl_entry[i]);
184192800Strasz		ace = &(aces[i]);
185192800Strasz
186192800Strasz		ace->a_who = entry->ae_id;
187192800Strasz
188192800Strasz		if (entry->ae_tag == ACL_USER_OBJ)
189192800Strasz			ace->a_flags = ACE_OWNER;
190192800Strasz		else if (entry->ae_tag == ACL_GROUP_OBJ)
191192800Strasz			ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP);
192192800Strasz		else if (entry->ae_tag == ACL_GROUP)
193192800Strasz			ace->a_flags = ACE_IDENTIFIER_GROUP;
194192800Strasz		else if (entry->ae_tag == ACL_EVERYONE)
195192800Strasz			ace->a_flags = ACE_EVERYONE;
196192800Strasz		else /* ACL_USER */
197192800Strasz			ace->a_flags = 0;
198192800Strasz
199192800Strasz		ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms);
200192800Strasz		ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags);
201192800Strasz
202192800Strasz		switch (entry->ae_entry_type) {
203192800Strasz		case ACL_ENTRY_TYPE_ALLOW:
204192800Strasz			ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
205192800Strasz			break;
206192800Strasz		case ACL_ENTRY_TYPE_DENY:
207192800Strasz			ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
208192800Strasz			break;
209192800Strasz		case ACL_ENTRY_TYPE_ALARM:
210192800Strasz			ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
211192800Strasz			break;
212192800Strasz		case ACL_ENTRY_TYPE_AUDIT:
213192800Strasz			ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
214192800Strasz			break;
215192800Strasz		default:
216192800Strasz			panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type);
217192800Strasz		}
218192800Strasz	}
219192800Strasz}
220