xref: /freebsd/tests/sys/acl/acl-api-test.c (revision f8b88be850a51eb982a476b27b74686a445e9a38)
1*f8b88be8SGleb Popov /*-
2*f8b88be8SGleb Popov  * Copyright (c) 2021 Gleb Popov
3*f8b88be8SGleb Popov  * All rights reserved.
4*f8b88be8SGleb Popov  *
5*f8b88be8SGleb Popov  * Redistribution and use in source and binary forms, with or without
6*f8b88be8SGleb Popov  * modification, are permitted provided that the following conditions
7*f8b88be8SGleb Popov  * are met:
8*f8b88be8SGleb Popov  * 1. Redistributions of source code must retain the above copyright
9*f8b88be8SGleb Popov  *    notice, this list of conditions and the following disclaimer.
10*f8b88be8SGleb Popov  * 2. Redistributions in binary form must reproduce the above copyright
11*f8b88be8SGleb Popov  *    notice, this list of conditions and the following disclaimer in the
12*f8b88be8SGleb Popov  *    documentation and/or other materials provided with the distribution.
13*f8b88be8SGleb Popov  *
14*f8b88be8SGleb Popov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*f8b88be8SGleb Popov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*f8b88be8SGleb Popov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*f8b88be8SGleb Popov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*f8b88be8SGleb Popov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*f8b88be8SGleb Popov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*f8b88be8SGleb Popov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*f8b88be8SGleb Popov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*f8b88be8SGleb Popov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*f8b88be8SGleb Popov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*f8b88be8SGleb Popov  * SUCH DAMAGE.
25*f8b88be8SGleb Popov  */
26*f8b88be8SGleb Popov 
27*f8b88be8SGleb Popov #include <sys/param.h>
28*f8b88be8SGleb Popov #include <sys/acl.h>
29*f8b88be8SGleb Popov #include <sys/stat.h>
30*f8b88be8SGleb Popov 
31*f8b88be8SGleb Popov #include <stdlib.h>
32*f8b88be8SGleb Popov #include <errno.h>
33*f8b88be8SGleb Popov 
34*f8b88be8SGleb Popov #include <atf-c.h>
35*f8b88be8SGleb Popov 
36*f8b88be8SGleb Popov /* Compatibility shim to make it possible to run this test on Linux
37*f8b88be8SGleb Popov  * gcc -I/path/to/atf/include -L/path/to/atf/lib -latf-c -lacl acl-api-test.c
38*f8b88be8SGleb Popov  */
39*f8b88be8SGleb Popov #ifdef __linux__
40*f8b88be8SGleb Popov #include <acl/libacl.h>
41*f8b88be8SGleb Popov #define acl_from_mode_np acl_from_mode
42*f8b88be8SGleb Popov #define acl_equiv_mode_np acl_equiv_mode
43*f8b88be8SGleb Popov #define acl_cmp_np acl_cmp
44*f8b88be8SGleb Popov #endif
45*f8b88be8SGleb Popov 
46*f8b88be8SGleb Popov static const mode_t all_modes[] = {
47*f8b88be8SGleb Popov 	S_IRUSR,
48*f8b88be8SGleb Popov 	S_IWUSR,
49*f8b88be8SGleb Popov 	S_IXUSR,
50*f8b88be8SGleb Popov 	S_IRGRP,
51*f8b88be8SGleb Popov 	S_IWGRP,
52*f8b88be8SGleb Popov 	S_IXGRP,
53*f8b88be8SGleb Popov 	S_IROTH,
54*f8b88be8SGleb Popov 	S_IWOTH,
55*f8b88be8SGleb Popov 	S_IXOTH
56*f8b88be8SGleb Popov };
57*f8b88be8SGleb Popov 
gen_random_mode(void)58*f8b88be8SGleb Popov static mode_t gen_random_mode(void)
59*f8b88be8SGleb Popov {
60*f8b88be8SGleb Popov 	mode_t mode = 0;
61*f8b88be8SGleb Popov 
62*f8b88be8SGleb Popov 	for (unsigned i = 0; i < sizeof(all_modes) / sizeof(mode_t); i++) {
63*f8b88be8SGleb Popov 		if (rand() % 2)
64*f8b88be8SGleb Popov 			mode |= all_modes[i];
65*f8b88be8SGleb Popov 	}
66*f8b88be8SGleb Popov 
67*f8b88be8SGleb Popov 	return (mode);
68*f8b88be8SGleb Popov }
69*f8b88be8SGleb Popov 
70*f8b88be8SGleb Popov /* Generate a random mode_t, produce an acl_t from it,
71*f8b88be8SGleb Popov  * then use acl_equiv_mode_np to produce a mode_t again.
72*f8b88be8SGleb Popov  * The call should succeed and mode_t's should be equal
73*f8b88be8SGleb Popov  */
74*f8b88be8SGleb Popov ATF_TC_WITHOUT_HEAD(acl_mode_roundup);
ATF_TC_BODY(acl_mode_roundup,tc)75*f8b88be8SGleb Popov ATF_TC_BODY(acl_mode_roundup, tc)
76*f8b88be8SGleb Popov {
77*f8b88be8SGleb Popov 	int num_tests = 100;
78*f8b88be8SGleb Popov 
79*f8b88be8SGleb Popov 	while (num_tests--) {
80*f8b88be8SGleb Popov 		mode_t src_mode, equiv_mode;
81*f8b88be8SGleb Popov 		acl_t acl;
82*f8b88be8SGleb Popov 
83*f8b88be8SGleb Popov 		src_mode = gen_random_mode();
84*f8b88be8SGleb Popov 
85*f8b88be8SGleb Popov 		acl = acl_from_mode_np(src_mode);
86*f8b88be8SGleb Popov 		ATF_REQUIRE(acl != NULL);
87*f8b88be8SGleb Popov 
88*f8b88be8SGleb Popov 		ATF_CHECK_EQ(0, acl_equiv_mode_np(acl, &equiv_mode));
89*f8b88be8SGleb Popov 		ATF_CHECK_EQ(src_mode, equiv_mode);
90*f8b88be8SGleb Popov 
91*f8b88be8SGleb Popov 		acl_free(acl);
92*f8b88be8SGleb Popov 	}
93*f8b88be8SGleb Popov }
94*f8b88be8SGleb Popov 
95*f8b88be8SGleb Popov /* Successfull acl_equiv_mode_np calls are tested in acl_mode_roundup.
96*f8b88be8SGleb Popov  * Here some specific cases are tested.
97*f8b88be8SGleb Popov  */
98*f8b88be8SGleb Popov ATF_TC_WITHOUT_HEAD(acl_equiv_mode_test);
ATF_TC_BODY(acl_equiv_mode_test,tc)99*f8b88be8SGleb Popov ATF_TC_BODY(acl_equiv_mode_test, tc)
100*f8b88be8SGleb Popov {
101*f8b88be8SGleb Popov 	acl_t acl;
102*f8b88be8SGleb Popov 	acl_entry_t entry;
103*f8b88be8SGleb Popov 	mode_t mode;
104*f8b88be8SGleb Popov 	int uid = 0;
105*f8b88be8SGleb Popov 
106*f8b88be8SGleb Popov 	acl = acl_init(1);
107*f8b88be8SGleb Popov 	ATF_REQUIRE(acl != NULL);
108*f8b88be8SGleb Popov 
109*f8b88be8SGleb Popov 	/* empty acl maps to 0000 UNIX mode */
110*f8b88be8SGleb Popov 	ATF_CHECK_EQ(0, acl_equiv_mode_np(acl, &mode));
111*f8b88be8SGleb Popov 	ATF_CHECK_EQ(0, mode);
112*f8b88be8SGleb Popov 
113*f8b88be8SGleb Popov #ifndef __linux__
114*f8b88be8SGleb Popov 	/* NFS-branded acl's can't be converted to UNIX mode */
115*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_create_entry(&acl, &entry));
116*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_EVERYONE));
117*f8b88be8SGleb Popov 	ATF_CHECK_EQ(1, acl_equiv_mode_np(acl, &mode));
118*f8b88be8SGleb Popov #endif
119*f8b88be8SGleb Popov 
120*f8b88be8SGleb Popov 	/* acl's with qualified user entries can't be converted to UNIX mode */
121*f8b88be8SGleb Popov 	acl_free(acl);
122*f8b88be8SGleb Popov 	acl = acl_init(1);
123*f8b88be8SGleb Popov 	ATF_REQUIRE(acl != NULL);
124*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_create_entry(&acl, &entry));
125*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_USER));
126*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_set_qualifier(entry, &uid));
127*f8b88be8SGleb Popov 	ATF_CHECK_EQ(1, acl_equiv_mode_np(acl, &mode));
128*f8b88be8SGleb Popov 
129*f8b88be8SGleb Popov 	/* passing NULL causes EINVAL */
130*f8b88be8SGleb Popov 	ATF_CHECK_ERRNO(EINVAL, acl_equiv_mode_np(NULL, &mode));
131*f8b88be8SGleb Popov }
132*f8b88be8SGleb Popov 
133*f8b88be8SGleb Popov ATF_TC_WITHOUT_HEAD(acl_cmp_test);
ATF_TC_BODY(acl_cmp_test,tc)134*f8b88be8SGleb Popov ATF_TC_BODY(acl_cmp_test, tc)
135*f8b88be8SGleb Popov {
136*f8b88be8SGleb Popov 	acl_t empty_acl, acl1, acl2;
137*f8b88be8SGleb Popov 	acl_entry_t entry;
138*f8b88be8SGleb Popov 	acl_permset_t perms;
139*f8b88be8SGleb Popov 
140*f8b88be8SGleb Popov 	empty_acl = acl_init(1);
141*f8b88be8SGleb Popov 	ATF_REQUIRE(empty_acl != NULL);
142*f8b88be8SGleb Popov 
143*f8b88be8SGleb Popov 	acl1 = acl_init(3);
144*f8b88be8SGleb Popov 	ATF_REQUIRE(acl1 != NULL);
145*f8b88be8SGleb Popov 
146*f8b88be8SGleb Popov 	/* first, check that two empty acls are equal */
147*f8b88be8SGleb Popov 	ATF_CHECK_EQ(0, acl_cmp_np(acl1, empty_acl));
148*f8b88be8SGleb Popov 
149*f8b88be8SGleb Popov 	/* now create an entry and compare against empty acl */
150*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_create_entry(&acl1, &entry));
151*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_USER_OBJ));
152*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_get_permset(entry, &perms));
153*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_clear_perms(perms));
154*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_add_perm(perms, ACL_READ));
155*f8b88be8SGleb Popov 	ATF_CHECK_EQ(1, acl_cmp_np(empty_acl, acl1));
156*f8b88be8SGleb Popov 
157*f8b88be8SGleb Popov 	/* make a dup of non-empty acl and check that they are equal */
158*f8b88be8SGleb Popov 	acl2 = acl_dup(acl1);
159*f8b88be8SGleb Popov 	ATF_REQUIRE(acl2 != NULL);
160*f8b88be8SGleb Popov 	ATF_CHECK_EQ(0, acl_cmp_np(acl1, acl2));
161*f8b88be8SGleb Popov 
162*f8b88be8SGleb Popov 	/* change the tag type and compare */
163*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(1, acl_get_entry(acl1, ACL_FIRST_ENTRY, &entry));
164*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_GROUP_OBJ));
165*f8b88be8SGleb Popov 	ATF_CHECK_EQ(1, acl_cmp_np(acl1, acl2));
166*f8b88be8SGleb Popov 
167*f8b88be8SGleb Popov 	/* change the permset and compare */
168*f8b88be8SGleb Popov 	acl_free(acl2);
169*f8b88be8SGleb Popov 	acl2 = acl_dup(acl1);
170*f8b88be8SGleb Popov 	ATF_REQUIRE(acl2 != NULL);
171*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(1, acl_get_entry(acl1, ACL_FIRST_ENTRY, &entry));
172*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_get_permset(entry, &perms));
173*f8b88be8SGleb Popov 	ATF_REQUIRE_EQ(0, acl_clear_perms(perms));
174*f8b88be8SGleb Popov 	ATF_CHECK_EQ(1, acl_cmp_np(acl1, acl2));
175*f8b88be8SGleb Popov 
176*f8b88be8SGleb Popov 	/* check that passing NULL yields EINVAL */
177*f8b88be8SGleb Popov 	ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(NULL, NULL));
178*f8b88be8SGleb Popov 	ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(acl1, NULL));
179*f8b88be8SGleb Popov 	ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(NULL, acl1));
180*f8b88be8SGleb Popov 
181*f8b88be8SGleb Popov 	acl_free(empty_acl);
182*f8b88be8SGleb Popov 	acl_free(acl1);
183*f8b88be8SGleb Popov 	acl_free(acl2);
184*f8b88be8SGleb Popov }
185*f8b88be8SGleb Popov 
ATF_TP_ADD_TCS(tp)186*f8b88be8SGleb Popov ATF_TP_ADD_TCS(tp)
187*f8b88be8SGleb Popov {
188*f8b88be8SGleb Popov 
189*f8b88be8SGleb Popov 	ATF_TP_ADD_TC(tp, acl_mode_roundup);
190*f8b88be8SGleb Popov 	ATF_TP_ADD_TC(tp, acl_equiv_mode_test);
191*f8b88be8SGleb Popov 	ATF_TP_ADD_TC(tp, acl_cmp_test);
192*f8b88be8SGleb Popov 
193*f8b88be8SGleb Popov 	return (atf_no_error());
194*f8b88be8SGleb Popov }
195