192108Sphk/*-
292108Sphk * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
392108Sphk *
492108Sphk * Copyright (c) 2001-2002 Chris D. Faulhaber
592108Sphk * All rights reserved.
692108Sphk *
792108Sphk * Redistribution and use in source and binary forms, with or without
892108Sphk * modification, are permitted provided that the following conditions
992108Sphk * are met:
1092108Sphk * 1. Redistributions of source code must retain the above copyright
1192108Sphk *    notice, this list of conditions and the following disclaimer.
1292108Sphk * 2. Redistributions in binary form must reproduce the above copyright
1392108Sphk *    notice, this list of conditions and the following disclaimer in the
1492108Sphk *    documentation and/or other materials provided with the distribution.
1592108Sphk *
1692108Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1792108Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1892108Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1992108Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2092108Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2192108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2292108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2392108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2492108Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2592108Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2692108Sphk * SUCH DAMAGE.
2792108Sphk */
2892108Sphk
2992108Sphk#include <sys/cdefs.h>
3092108Sphk#if 0
3192108Sphk__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_delete_entry.c 326193 2017-11-25 17:12:48Z pfg $");
3292108Sphk#else
3392108Sphk__RCSID("$NetBSD: acl_delete_entry.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
3492108Sphk#endif
3592108Sphk
3692108Sphk#include "namespace.h"
3792108Sphk#include <sys/types.h>
3892108Sphk#include <sys/acl.h>
3992108Sphk#include <errno.h>
4092108Sphk#include <string.h>
4192108Sphk#include <stdio.h>
4292108Sphk
4392108Sphk#include "acl_support.h"
4492108Sphk
4592108Sphkstatic int
4692108Sphk_entry_matches(const acl_entry_t a, const acl_entry_t b)
4792108Sphk{
4892108Sphk	/*
4992108Sphk	 * There is a semantical difference here between NFSv4 and POSIX
5092108Sphk	 * draft ACLs.  In POSIX, there may be only one entry for the particular
5192108Sphk	 * user or group.  In NFSv4 ACL, there may be any number of them.  We're
5292108Sphk	 * trying to be more specific here in that case.
5392108Sphk	 */
5492108Sphk	switch (_entry_brand(a)) {
5592108Sphk	case ACL_BRAND_NFS4:
5692108Sphk		if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type)
5792108Sphk			return (0);
5892108Sphk
5992108Sphk		/* If ae_ids matter, compare them as well. */
6092108Sphk		if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
6192108Sphk			if (a->ae_id != b->ae_id)
6292108Sphk				return (0);
6392108Sphk		}
6492108Sphk
6592108Sphk		return (1);
6692108Sphk
6792108Sphk	default:
6892108Sphk		if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id))
6992108Sphk			return (1);
7092108Sphk	}
7192108Sphk
7292108Sphk	return (0);
7392108Sphk}
7492108Sphk
7592108Sphk/*
7692108Sphk * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
7792108Sphk * from acl.
7892108Sphk */
7992108Sphkint
8092108Sphkacl_delete_entry(acl_t acl, acl_entry_t entry_d)
8192108Sphk{
8292108Sphk	struct acl_entry entry_int;
8392108Sphk	size_t i, j;
8492108Sphk	int found = 0;
8592108Sphk
8692108Sphk	if (acl == NULL || entry_d == NULL) {
8792108Sphk		errno = EINVAL;
8892108Sphk		return (-1);
8992108Sphk	}
9092108Sphk
9192108Sphk	if (_entry_brand(entry_d) != _acl_brand(acl)) {
9292108Sphk		errno = EINVAL;
9392108Sphk		return (-1);
9492108Sphk	}
9592108Sphk
9692108Sphk	if ((acl->ats_acl.acl_cnt < 1) ||
9792108Sphk	    (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
9892108Sphk		errno = EINVAL;
9992108Sphk		return (-1);
10092108Sphk	}
10192108Sphk
10292108Sphk	/* Use a local copy to prevent deletion of more than this entry */
10392108Sphk	entry_int = *entry_d;
10492108Sphk
10592108Sphk	for (i = 0; i < acl->ats_acl.acl_cnt;) {
10692108Sphk		if (_entry_matches(&(acl->ats_acl.acl_entry[i]), &entry_int)) {
10792108Sphk			/* ...shift the remaining entries... */
10892108Sphk			for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
10992108Sphk				acl->ats_acl.acl_entry[j] =
11092108Sphk				    acl->ats_acl.acl_entry[j+1];
11192108Sphk			/* ...drop the count and zero the unused entry... */
11292108Sphk			acl->ats_acl.acl_cnt--;
11392108Sphk			bzero(&acl->ats_acl.acl_entry[j],
11492108Sphk			    sizeof(struct acl_entry));
11592108Sphk			acl->ats_cur_entry = 0;
11692108Sphk
11792108Sphk			/* Continue with the loop to remove all matching entries. */
11892108Sphk			found = 1;
11992108Sphk		} else
12092108Sphk			i++;
12192108Sphk	}
12292108Sphk
12392108Sphk	if (found)
12492108Sphk		return (0);
12592108Sphk
12692108Sphk	errno = EINVAL;
12792108Sphk	return (-1);
12892108Sphk}
12992108Sphk
13092108Sphkint
13192108Sphkacl_delete_entry_np(acl_t acl, int offset)
13292108Sphk{
13392108Sphk	struct acl *acl_int;
13492108Sphk	size_t i;
13592108Sphk
13692108Sphk	if (acl == NULL) {
13792108Sphk		errno = EINVAL;
13892108Sphk		return (-1);
13992108Sphk	}
14092108Sphk
14192108Sphk	acl_int = &acl->ats_acl;
14292108Sphk
14392108Sphk	if (offset < 0 || (size_t)offset >= acl_int->acl_cnt) {
14492108Sphk		errno = EINVAL;
14592108Sphk		return (-1);
14692108Sphk	}
14792108Sphk
14892108Sphk	if ((acl->ats_acl.acl_cnt < 1) ||
14992108Sphk	    (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
15092108Sphk		errno = EINVAL;
15192108Sphk		return (-1);
15292108Sphk	}
15392108Sphk
15492108Sphk	/* ...shift the remaining entries... */
15592108Sphk	for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i)
15692108Sphk		acl->ats_acl.acl_entry[i] =
15792108Sphk		    acl->ats_acl.acl_entry[i+1];
15892108Sphk	/* ...drop the count and zero the unused entry... */
15992108Sphk	acl->ats_acl.acl_cnt--;
16092108Sphk	bzero(&acl->ats_acl.acl_entry[i],
16192108Sphk	    sizeof(struct acl_entry));
16292108Sphk	acl->ats_cur_entry = 0;
16392108Sphk
16492108Sphk	return (0);
16592108Sphk}
16692108Sphk