xref: /netbsd-src/lib/libc/posix1e/acl_to_text.c (revision 9aa2a9c323eb12a08584c70d6ea91d316703d3fe)
1*9aa2a9c3Schristos /*-
2*9aa2a9c3Schristos  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*9aa2a9c3Schristos  *
4*9aa2a9c3Schristos  * Copyright (c) 1999-2002 Robert N. M. Watson
5*9aa2a9c3Schristos  * All rights reserved.
6*9aa2a9c3Schristos  *
7*9aa2a9c3Schristos  * Redistribution and use in source and binary forms, with or without
8*9aa2a9c3Schristos  * modification, are permitted provided that the following conditions
9*9aa2a9c3Schristos  * are met:
10*9aa2a9c3Schristos  * 1. Redistributions of source code must retain the above copyright
11*9aa2a9c3Schristos  *    notice, this list of conditions and the following disclaimer.
12*9aa2a9c3Schristos  * 2. Redistributions in binary form must reproduce the above copyright
13*9aa2a9c3Schristos  *    notice, this list of conditions and the following disclaimer in the
14*9aa2a9c3Schristos  *    documentation and/or other materials provided with the distribution.
15*9aa2a9c3Schristos  *
16*9aa2a9c3Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*9aa2a9c3Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*9aa2a9c3Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*9aa2a9c3Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*9aa2a9c3Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*9aa2a9c3Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*9aa2a9c3Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*9aa2a9c3Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*9aa2a9c3Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*9aa2a9c3Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*9aa2a9c3Schristos  * SUCH DAMAGE.
27*9aa2a9c3Schristos  */
28*9aa2a9c3Schristos /*
29*9aa2a9c3Schristos  * acl_to_text - return a text string with a text representation of the acl
30*9aa2a9c3Schristos  * in it.
31*9aa2a9c3Schristos  */
32*9aa2a9c3Schristos 
33*9aa2a9c3Schristos #include <sys/cdefs.h>
34*9aa2a9c3Schristos #if 0
35*9aa2a9c3Schristos __FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_to_text.c 326193 2017-11-25 17:12:48Z pfg $");
36*9aa2a9c3Schristos #else
37*9aa2a9c3Schristos __RCSID("$NetBSD: acl_to_text.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
38*9aa2a9c3Schristos #endif
39*9aa2a9c3Schristos 
40*9aa2a9c3Schristos #include "namespace.h"
41*9aa2a9c3Schristos #include <sys/types.h>
42*9aa2a9c3Schristos #include <sys/acl.h>
43*9aa2a9c3Schristos #include <errno.h>
44*9aa2a9c3Schristos #include <stdio.h>
45*9aa2a9c3Schristos #include <stdlib.h>
46*9aa2a9c3Schristos #include <string.h>
47*9aa2a9c3Schristos 
48*9aa2a9c3Schristos #include "acl_support.h"
49*9aa2a9c3Schristos 
50*9aa2a9c3Schristos /*
51*9aa2a9c3Schristos  * acl_to_text - generate a text form of an acl
52*9aa2a9c3Schristos  * spec says nothing about output ordering, so leave in acl order
53*9aa2a9c3Schristos  *
54*9aa2a9c3Schristos  * This function will not produce nice results if it is called with
55*9aa2a9c3Schristos  * a non-POSIX.1e semantics ACL.
56*9aa2a9c3Schristos  */
57*9aa2a9c3Schristos 
58*9aa2a9c3Schristos char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags);
59*9aa2a9c3Schristos 
60*9aa2a9c3Schristos static char *
_posix1e_acl_to_text(acl_t acl,ssize_t * len_p,int flags)61*9aa2a9c3Schristos _posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags)
62*9aa2a9c3Schristos {
63*9aa2a9c3Schristos 	struct acl	*acl_int;
64*9aa2a9c3Schristos 	char		*buf, *tmpbuf;
65*9aa2a9c3Schristos 	char		 name_buf[MAXLOGNAME];
66*9aa2a9c3Schristos 	char		 perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
67*9aa2a9c3Schristos 			 effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
68*9aa2a9c3Schristos 	size_t		 i;
69*9aa2a9c3Schristos 	int		 error, len;
70*9aa2a9c3Schristos 	uid_t		 ae_id;
71*9aa2a9c3Schristos 	acl_tag_t	 ae_tag;
72*9aa2a9c3Schristos 	acl_perm_t	 ae_perm, effective_perm, mask_perm;
73*9aa2a9c3Schristos 
74*9aa2a9c3Schristos 	buf = strdup("");
75*9aa2a9c3Schristos 	if (buf == NULL)
76*9aa2a9c3Schristos 		return(NULL);
77*9aa2a9c3Schristos 
78*9aa2a9c3Schristos 	acl_int = &acl->ats_acl;
79*9aa2a9c3Schristos 
80*9aa2a9c3Schristos 	mask_perm = ACL_PERM_BITS;	/* effective is regular if no mask */
81*9aa2a9c3Schristos 	for (i = 0; i < acl_int->acl_cnt; i++)
82*9aa2a9c3Schristos 		if (acl_int->acl_entry[i].ae_tag == ACL_MASK)
83*9aa2a9c3Schristos 			mask_perm = acl_int->acl_entry[i].ae_perm;
84*9aa2a9c3Schristos 
85*9aa2a9c3Schristos 	for (i = 0; i < acl_int->acl_cnt; i++) {
86*9aa2a9c3Schristos 		ae_tag = acl_int->acl_entry[i].ae_tag;
87*9aa2a9c3Schristos 		ae_id = acl_int->acl_entry[i].ae_id;
88*9aa2a9c3Schristos 		ae_perm = acl_int->acl_entry[i].ae_perm;
89*9aa2a9c3Schristos 
90*9aa2a9c3Schristos 		switch(ae_tag) {
91*9aa2a9c3Schristos 		case ACL_USER_OBJ:
92*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
93*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
94*9aa2a9c3Schristos 			if (error)
95*9aa2a9c3Schristos 				goto error_label;
96*9aa2a9c3Schristos 			len = asprintf(&tmpbuf, "%suser::%s\n", buf,
97*9aa2a9c3Schristos 			    perm_buf);
98*9aa2a9c3Schristos 			if (len == -1)
99*9aa2a9c3Schristos 				goto error_label;
100*9aa2a9c3Schristos 			free(buf);
101*9aa2a9c3Schristos 			buf = tmpbuf;
102*9aa2a9c3Schristos 			break;
103*9aa2a9c3Schristos 
104*9aa2a9c3Schristos 		case ACL_USER:
105*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
106*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
107*9aa2a9c3Schristos 			if (error)
108*9aa2a9c3Schristos 				goto error_label;
109*9aa2a9c3Schristos 
110*9aa2a9c3Schristos 			error = _posix1e_acl_id_to_name(ae_tag, ae_id,
111*9aa2a9c3Schristos 			    MAXLOGNAME, name_buf, flags);
112*9aa2a9c3Schristos 			if (error)
113*9aa2a9c3Schristos 				goto error_label;
114*9aa2a9c3Schristos 
115*9aa2a9c3Schristos 			effective_perm = ae_perm & mask_perm;
116*9aa2a9c3Schristos 			if (effective_perm != ae_perm) {
117*9aa2a9c3Schristos 				error = _posix1e_acl_perm_to_string(
118*9aa2a9c3Schristos 				    effective_perm,
119*9aa2a9c3Schristos 				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
120*9aa2a9c3Schristos 				    effective_perm_buf);
121*9aa2a9c3Schristos 				if (error)
122*9aa2a9c3Schristos 					goto error_label;
123*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# "
124*9aa2a9c3Schristos 				    "effective: %s\n",
125*9aa2a9c3Schristos 				    buf, name_buf, perm_buf,
126*9aa2a9c3Schristos 				    effective_perm_buf);
127*9aa2a9c3Schristos 			} else {
128*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf,
129*9aa2a9c3Schristos 				    name_buf, perm_buf);
130*9aa2a9c3Schristos 			}
131*9aa2a9c3Schristos 			if (len == -1)
132*9aa2a9c3Schristos 				goto error_label;
133*9aa2a9c3Schristos 			free(buf);
134*9aa2a9c3Schristos 			buf = tmpbuf;
135*9aa2a9c3Schristos 			break;
136*9aa2a9c3Schristos 
137*9aa2a9c3Schristos 		case ACL_GROUP_OBJ:
138*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
139*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
140*9aa2a9c3Schristos 			if (error)
141*9aa2a9c3Schristos 				goto error_label;
142*9aa2a9c3Schristos 
143*9aa2a9c3Schristos 			effective_perm = ae_perm & mask_perm;
144*9aa2a9c3Schristos 			if (effective_perm != ae_perm) {
145*9aa2a9c3Schristos 				error = _posix1e_acl_perm_to_string(
146*9aa2a9c3Schristos 				    effective_perm,
147*9aa2a9c3Schristos 				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
148*9aa2a9c3Schristos 				    effective_perm_buf);
149*9aa2a9c3Schristos 				if (error)
150*9aa2a9c3Schristos 					goto error_label;
151*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%sgroup::%s\t\t# "
152*9aa2a9c3Schristos 				    "effective: %s\n",
153*9aa2a9c3Schristos 				    buf, perm_buf, effective_perm_buf);
154*9aa2a9c3Schristos 			} else {
155*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%sgroup::%s\n", buf,
156*9aa2a9c3Schristos 				    perm_buf);
157*9aa2a9c3Schristos 			}
158*9aa2a9c3Schristos 			if (len == -1)
159*9aa2a9c3Schristos 				goto error_label;
160*9aa2a9c3Schristos 			free(buf);
161*9aa2a9c3Schristos 			buf = tmpbuf;
162*9aa2a9c3Schristos 			break;
163*9aa2a9c3Schristos 
164*9aa2a9c3Schristos 		case ACL_GROUP:
165*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
166*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
167*9aa2a9c3Schristos 			if (error)
168*9aa2a9c3Schristos 				goto error_label;
169*9aa2a9c3Schristos 
170*9aa2a9c3Schristos 			error = _posix1e_acl_id_to_name(ae_tag, ae_id,
171*9aa2a9c3Schristos 			    MAXLOGNAME, name_buf, flags);
172*9aa2a9c3Schristos 			if (error)
173*9aa2a9c3Schristos 				goto error_label;
174*9aa2a9c3Schristos 
175*9aa2a9c3Schristos 			effective_perm = ae_perm & mask_perm;
176*9aa2a9c3Schristos 			if (effective_perm != ae_perm) {
177*9aa2a9c3Schristos 				error = _posix1e_acl_perm_to_string(
178*9aa2a9c3Schristos 				    effective_perm,
179*9aa2a9c3Schristos 				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
180*9aa2a9c3Schristos 				    effective_perm_buf);
181*9aa2a9c3Schristos 				if (error)
182*9aa2a9c3Schristos 					goto error_label;
183*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# "
184*9aa2a9c3Schristos 				    "effective: %s\n",
185*9aa2a9c3Schristos 				    buf, name_buf, perm_buf,
186*9aa2a9c3Schristos 				    effective_perm_buf);
187*9aa2a9c3Schristos 			} else {
188*9aa2a9c3Schristos 				len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf,
189*9aa2a9c3Schristos 				    name_buf, perm_buf);
190*9aa2a9c3Schristos 			}
191*9aa2a9c3Schristos 			if (len == -1)
192*9aa2a9c3Schristos 				goto error_label;
193*9aa2a9c3Schristos 			free(buf);
194*9aa2a9c3Schristos 			buf = tmpbuf;
195*9aa2a9c3Schristos 			break;
196*9aa2a9c3Schristos 
197*9aa2a9c3Schristos 		case ACL_MASK:
198*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
199*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
200*9aa2a9c3Schristos 			if (error)
201*9aa2a9c3Schristos 				goto error_label;
202*9aa2a9c3Schristos 
203*9aa2a9c3Schristos 			len = asprintf(&tmpbuf, "%smask::%s\n", buf,
204*9aa2a9c3Schristos 			    perm_buf);
205*9aa2a9c3Schristos 			if (len == -1)
206*9aa2a9c3Schristos 				goto error_label;
207*9aa2a9c3Schristos 			free(buf);
208*9aa2a9c3Schristos 			buf = tmpbuf;
209*9aa2a9c3Schristos 			break;
210*9aa2a9c3Schristos 
211*9aa2a9c3Schristos 		case ACL_OTHER:
212*9aa2a9c3Schristos 			error = _posix1e_acl_perm_to_string(ae_perm,
213*9aa2a9c3Schristos 			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
214*9aa2a9c3Schristos 			if (error)
215*9aa2a9c3Schristos 				goto error_label;
216*9aa2a9c3Schristos 
217*9aa2a9c3Schristos 			len = asprintf(&tmpbuf, "%sother::%s\n", buf,
218*9aa2a9c3Schristos 			    perm_buf);
219*9aa2a9c3Schristos 			if (len == -1)
220*9aa2a9c3Schristos 				goto error_label;
221*9aa2a9c3Schristos 			free(buf);
222*9aa2a9c3Schristos 			buf = tmpbuf;
223*9aa2a9c3Schristos 			break;
224*9aa2a9c3Schristos 
225*9aa2a9c3Schristos 		default:
226*9aa2a9c3Schristos 			errno = EINVAL;
227*9aa2a9c3Schristos 			goto error_label;
228*9aa2a9c3Schristos 		}
229*9aa2a9c3Schristos 	}
230*9aa2a9c3Schristos 
231*9aa2a9c3Schristos 	if (len_p) {
232*9aa2a9c3Schristos 		*len_p = strlen(buf);
233*9aa2a9c3Schristos 	}
234*9aa2a9c3Schristos 	return (buf);
235*9aa2a9c3Schristos 
236*9aa2a9c3Schristos error_label:
237*9aa2a9c3Schristos 	/* jump to here sets errno already, we just clean up */
238*9aa2a9c3Schristos 	if (buf) free(buf);
239*9aa2a9c3Schristos 	return (NULL);
240*9aa2a9c3Schristos }
241*9aa2a9c3Schristos 
242*9aa2a9c3Schristos char *
acl_to_text_np(acl_t acl,ssize_t * len_p,int flags)243*9aa2a9c3Schristos acl_to_text_np(acl_t acl, ssize_t *len_p, int flags)
244*9aa2a9c3Schristos {
245*9aa2a9c3Schristos 
246*9aa2a9c3Schristos 	if (acl == NULL) {
247*9aa2a9c3Schristos 		errno = EINVAL;
248*9aa2a9c3Schristos 		return(NULL);
249*9aa2a9c3Schristos 	}
250*9aa2a9c3Schristos 
251*9aa2a9c3Schristos 	switch (_acl_brand(acl)) {
252*9aa2a9c3Schristos 	case ACL_BRAND_POSIX:
253*9aa2a9c3Schristos 		return (_posix1e_acl_to_text(acl, len_p, flags));
254*9aa2a9c3Schristos 	case ACL_BRAND_NFS4:
255*9aa2a9c3Schristos 		return (_nfs4_acl_to_text_np(acl, len_p, flags));
256*9aa2a9c3Schristos 	default:
257*9aa2a9c3Schristos 		errno = EINVAL;
258*9aa2a9c3Schristos 		return (NULL);
259*9aa2a9c3Schristos 	}
260*9aa2a9c3Schristos }
261*9aa2a9c3Schristos 
262*9aa2a9c3Schristos char *
acl_to_text(acl_t acl,ssize_t * len_p)263*9aa2a9c3Schristos acl_to_text(acl_t acl, ssize_t *len_p)
264*9aa2a9c3Schristos {
265*9aa2a9c3Schristos 
266*9aa2a9c3Schristos 	return (acl_to_text_np(acl, len_p, 0));
267*9aa2a9c3Schristos }
268