174432Sjedgar/*
290781Sjedgar * Copyright (c) 2001-2002 Chris D. Faulhaber
374432Sjedgar * All rights reserved.
474432Sjedgar *
574432Sjedgar * Redistribution and use in source and binary forms, with or without
674432Sjedgar * modification, are permitted provided that the following conditions
774432Sjedgar * are met:
874432Sjedgar * 1. Redistributions of source code must retain the above copyright
974432Sjedgar *    notice, this list of conditions and the following disclaimer.
1074432Sjedgar * 2. Redistributions in binary form must reproduce the above copyright
1174432Sjedgar *    notice, this list of conditions and the following disclaimer in the
1274432Sjedgar *    documentation and/or other materials provided with the distribution.
1374432Sjedgar *
1474432Sjedgar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1574432Sjedgar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1674432Sjedgar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1774432Sjedgar * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1874432Sjedgar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1974432Sjedgar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2074432Sjedgar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2174432Sjedgar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2274432Sjedgar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2374432Sjedgar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2474432Sjedgar * SUCH DAMAGE.
2574432Sjedgar */
2674432Sjedgar
2792986Sobrien#include <sys/cdefs.h>
2892986Sobrien__FBSDID("$FreeBSD$");
2992986Sobrien
3074432Sjedgar#include <sys/types.h>
3175185Stmm#include "namespace.h"
3274432Sjedgar#include <sys/acl.h>
3375185Stmm#include "un-namespace.h"
3474432Sjedgar#include <errno.h>
3574432Sjedgar#include <string.h>
36194955Strasz#include <stdio.h>
3774432Sjedgar
38194955Strasz#include "acl_support.h"
39194955Strasz
40194955Straszstatic int
41194955Strasz_entry_matches(const acl_entry_t a, const acl_entry_t b)
42194955Strasz{
43194955Strasz	/*
44194955Strasz	 * There is a semantical difference here between NFSv4 and POSIX
45194955Strasz	 * draft ACLs.  In POSIX, there may be only one entry for the particular
46194955Strasz	 * user or group.  In NFSv4 ACL, there may be any number of them.  We're
47194955Strasz	 * trying to be more specific here in that case.
48194955Strasz	 */
49194955Strasz	switch (_entry_brand(a)) {
50194955Strasz	case ACL_BRAND_NFS4:
51194955Strasz		if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type)
52194955Strasz			return (0);
53194955Strasz
54194955Strasz		/* If ae_ids matter, compare them as well. */
55194955Strasz		if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
56194955Strasz			if (a->ae_id != b->ae_id)
57194955Strasz				return (0);
58194955Strasz		}
59194955Strasz
60194955Strasz		return (1);
61194955Strasz
62194955Strasz	default:
63194955Strasz		if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id))
64194955Strasz			return (1);
65194955Strasz	}
66194955Strasz
67194955Strasz	return (0);
68194955Strasz}
69194955Strasz
7075928Sjedgar/*
7175928Sjedgar * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
7275928Sjedgar * from acl.
7375928Sjedgar */
7474432Sjedgarint
7574432Sjedgaracl_delete_entry(acl_t acl, acl_entry_t entry_d)
7674432Sjedgar{
7775928Sjedgar	struct acl *acl_int;
78200992Smarkus	struct acl_entry entry_int;
79194955Strasz	int i, j, found = 0;
8074432Sjedgar
8190781Sjedgar	if (acl == NULL || entry_d == NULL) {
8274432Sjedgar		errno = EINVAL;
8390781Sjedgar		return (-1);
8474432Sjedgar	}
8575928Sjedgar
8675928Sjedgar	acl_int = &acl->ats_acl;
8775928Sjedgar
88194955Strasz	if (_entry_brand(entry_d) != _acl_brand(acl)) {
89194955Strasz		errno = EINVAL;
90194955Strasz		return (-1);
91194955Strasz	}
92194955Strasz
9375928Sjedgar	if ((acl->ats_acl.acl_cnt < 1) ||
9475928Sjedgar	    (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
9575928Sjedgar		errno = EINVAL;
9690781Sjedgar		return (-1);
9775928Sjedgar	}
98200992Smarkus
99200992Smarkus	/* Use a local copy to prevent deletion of more than this entry */
100200992Smarkus	entry_int = *entry_d;
101200992Smarkus
102194955Strasz	for (i = 0; i < acl->ats_acl.acl_cnt;) {
103200992Smarkus		if (_entry_matches(&(acl->ats_acl.acl_entry[i]), &entry_int)) {
10474432Sjedgar			/* ...shift the remaining entries... */
105194955Strasz			for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
106194955Strasz				acl->ats_acl.acl_entry[j] =
107194955Strasz				    acl->ats_acl.acl_entry[j+1];
10874432Sjedgar			/* ...drop the count and zero the unused entry... */
10975928Sjedgar			acl->ats_acl.acl_cnt--;
110194955Strasz			bzero(&acl->ats_acl.acl_entry[j],
11175928Sjedgar			    sizeof(struct acl_entry));
11275928Sjedgar			acl->ats_cur_entry = 0;
113194955Strasz
114194955Strasz			/* Continue with the loop to remove all maching entries. */
115194955Strasz			found = 1;
116194955Strasz		} else
117194955Strasz			i++;
11874432Sjedgar	}
11974432Sjedgar
120194955Strasz	if (found)
121194955Strasz		return (0);
12274432Sjedgar
12374432Sjedgar	errno = EINVAL;
12490781Sjedgar	return (-1);
12574432Sjedgar}
126194955Strasz
127194955Straszint
128194955Straszacl_delete_entry_np(acl_t acl, int offset)
129194955Strasz{
130194955Strasz	struct acl *acl_int;
131194955Strasz	int i;
132194955Strasz
133194955Strasz	if (acl == NULL) {
134194955Strasz		errno = EINVAL;
135194955Strasz		return (-1);
136194955Strasz	}
137194955Strasz
138194955Strasz	acl_int = &acl->ats_acl;
139194955Strasz
140194955Strasz	if (offset < 0 || offset >= acl_int->acl_cnt) {
141194955Strasz		errno = EINVAL;
142194955Strasz		return (-1);
143194955Strasz	}
144194955Strasz
145194955Strasz	if ((acl->ats_acl.acl_cnt < 1) ||
146194955Strasz	    (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
147194955Strasz		errno = EINVAL;
148194955Strasz		return (-1);
149194955Strasz	}
150194955Strasz
151194955Strasz	/* ...shift the remaining entries... */
152194955Strasz	for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i)
153194955Strasz		acl->ats_acl.acl_entry[i] =
154194955Strasz		    acl->ats_acl.acl_entry[i+1];
155194955Strasz	/* ...drop the count and zero the unused entry... */
156194955Strasz	acl->ats_acl.acl_cnt--;
157194955Strasz	bzero(&acl->ats_acl.acl_entry[i],
158194955Strasz	    sizeof(struct acl_entry));
159194955Strasz	acl->ats_cur_entry = 0;
160194955Strasz
161194955Strasz	return (0);
162194955Strasz}
163