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