1194955Strasz/*-
2194955Strasz * Copyright (c) 2008, 2009 Edward Tomasz Napiera��a <trasz@FreeBSD.org>
3194955Strasz * All rights reserved.
4194955Strasz *
5194955Strasz * Redistribution and use in source and binary forms, with or without
6194955Strasz * modification, are permitted provided that the following conditions
7194955Strasz * are met:
8194955Strasz * 1. Redistributions of source code must retain the above copyright
9194955Strasz *    notice, this list of conditions and the following disclaimer.
10194955Strasz * 2. Redistributions in binary form must reproduce the above copyright
11194955Strasz *    notice, this list of conditions and the following disclaimer in the
12194955Strasz *    documentation and/or other materials provided with the distribution.
13194955Strasz *
14194955Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15194955Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16194955Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17194955Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18194955Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19194955Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20194955Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21194955Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22194955Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23194955Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24194955Strasz * SUCH DAMAGE.
25194955Strasz */
26194955Strasz
27194955Strasz#include <sys/cdefs.h>
28194955Strasz__FBSDID("$FreeBSD$");
29194955Strasz
30194955Strasz#include <assert.h>
31194955Strasz#include <errno.h>
32194955Strasz#include <sys/acl.h>
33194955Strasz
34194955Strasz#include "acl_support.h"
35194955Strasz
36194955Strasz/*
37194955Strasz * An ugly detail of the implementation - fortunately not visible
38194955Strasz * to the API users - is the "branding": libc needs to keep track
39194955Strasz * of what "brand" ACL is: NFSv4, POSIX.1e or unknown.  It happens
40194955Strasz * automatically - for example, during acl_get_file(3) ACL gets
41194955Strasz * branded according to the "type" argument; during acl_set_permset
42194955Strasz * ACL, if its brand is unknown it gets branded as NFSv4 if any of the
43194955Strasz * NFSv4 permissions that are not valid for POSIX.1e ACL are set etc.
44194955Strasz * Branding information is used for printing out the ACL (acl_to_text(3)),
45194955Strasz * veryfying acl_set_whatever arguments (checking against setting
46194955Strasz * bits that are valid only for NFSv4 in ACL branded as POSIX.1e) etc.
47194955Strasz */
48194955Strasz
49194955Straszstatic acl_t
50194955Straszentry2acl(acl_entry_t entry)
51194955Strasz{
52194955Strasz	acl_t aclp;
53194955Strasz
54194955Strasz	aclp = (acl_t)(((long)entry >> _ACL_T_ALIGNMENT_BITS) << _ACL_T_ALIGNMENT_BITS);
55194955Strasz
56194955Strasz	return (aclp);
57194955Strasz}
58194955Strasz
59194955Strasz/*
60194955Strasz * Return brand of an ACL.
61194955Strasz */
62194955Straszint
63194955Strasz_acl_brand(const acl_t acl)
64194955Strasz{
65194955Strasz
66194955Strasz	return (acl->ats_brand);
67194955Strasz}
68194955Strasz
69194955Straszint
70194955Strasz_entry_brand(const acl_entry_t entry)
71194955Strasz{
72194955Strasz
73194955Strasz	return (_acl_brand(entry2acl(entry)));
74194955Strasz}
75194955Strasz
76194955Strasz/*
77194955Strasz * Return 1, iff branding ACL as "brand" is ok.
78194955Strasz */
79194955Straszint
80194955Strasz_acl_brand_may_be(const acl_t acl, int brand)
81194955Strasz{
82194955Strasz
83194955Strasz	if (_acl_brand(acl) == ACL_BRAND_UNKNOWN)
84194955Strasz		return (1);
85194955Strasz
86194955Strasz	if (_acl_brand(acl) == brand)
87194955Strasz		return (1);
88194955Strasz
89194955Strasz	return (0);
90194955Strasz}
91194955Strasz
92194955Straszint
93194955Strasz_entry_brand_may_be(const acl_entry_t entry, int brand)
94194955Strasz{
95194955Strasz
96194955Strasz	return (_acl_brand_may_be(entry2acl(entry), brand));
97194955Strasz}
98194955Strasz
99194955Strasz/*
100194955Strasz * Brand ACL as "brand".
101194955Strasz */
102194955Straszvoid
103194955Strasz_acl_brand_as(acl_t acl, int brand)
104194955Strasz{
105194955Strasz
106194955Strasz	assert(_acl_brand_may_be(acl, brand));
107194955Strasz
108194955Strasz	acl->ats_brand = brand;
109194955Strasz}
110194955Strasz
111194955Straszvoid
112194955Strasz_entry_brand_as(const acl_entry_t entry, int brand)
113194955Strasz{
114194955Strasz
115194955Strasz	_acl_brand_as(entry2acl(entry), brand);
116194955Strasz}
117194955Strasz
118194955Straszint
119194955Strasz_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type)
120194955Strasz{
121194955Strasz
122194955Strasz	switch (_acl_brand(acl)) {
123194955Strasz	case ACL_BRAND_NFS4:
124194955Strasz		if (type == ACL_TYPE_NFS4)
125194955Strasz			return (0);
126194955Strasz		break;
127194955Strasz
128194955Strasz	case ACL_BRAND_POSIX:
129194955Strasz		if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT)
130194955Strasz			return (0);
131194955Strasz		break;
132208034Strasz
133208034Strasz	case ACL_BRAND_UNKNOWN:
134208034Strasz		return (0);
135194955Strasz	}
136194955Strasz
137194955Strasz	return (-1);
138194955Strasz}
139194955Strasz
140194955Straszvoid
141194955Strasz_acl_brand_from_type(acl_t acl, acl_type_t type)
142194955Strasz{
143194955Strasz
144194955Strasz	switch (type) {
145194955Strasz	case ACL_TYPE_NFS4:
146194955Strasz		_acl_brand_as(acl, ACL_BRAND_NFS4);
147194955Strasz		break;
148194955Strasz	case ACL_TYPE_ACCESS:
149194955Strasz	case ACL_TYPE_DEFAULT:
150194955Strasz		_acl_brand_as(acl, ACL_BRAND_POSIX);
151194955Strasz		break;
152194955Strasz	default:
153194955Strasz		/* XXX: What to do here? */
154194955Strasz		break;
155194955Strasz	}
156194955Strasz}
157194955Strasz
158194955Straszint
159194955Straszacl_get_brand_np(acl_t acl, int *brand_p)
160194955Strasz{
161194955Strasz
162194955Strasz	if (acl == NULL || brand_p == NULL) {
163194955Strasz		errno = EINVAL;
164194955Strasz		return (-1);
165194955Strasz	}
166194955Strasz	*brand_p = _acl_brand(acl);
167194955Strasz
168194955Strasz	return (0);
169194955Strasz}
170