acl_to_text.c revision 91034
119370Spst/*-
2130803Smarcel * Copyright (c) 1999-2002 Robert N. M. Watson
398944Sobrien * All rights reserved.
419370Spst *
519370Spst * Redistribution and use in source and binary forms, with or without
619370Spst * modification, are permitted provided that the following conditions
798944Sobrien * are met:
819370Spst * 1. Redistributions of source code must retain the above copyright
998944Sobrien *    notice, this list of conditions and the following disclaimer.
1098944Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1198944Sobrien *    notice, this list of conditions and the following disclaimer in the
1298944Sobrien *    documentation and/or other materials provided with the distribution.
1319370Spst *
1498944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1598944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1698944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1798944Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1998944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2098944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2198944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2298944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419370Spst * SUCH DAMAGE.
2519370Spst *
2619370Spst * $FreeBSD: head/lib/libc/posix1e/acl_to_text.c 91034 2002-02-21 23:17:19Z jedgar $
2719370Spst */
2819370Spst/*
2919370Spst * acl_to_text - return a text string with a text representation of the acl
3019370Spst * in it.
3119370Spst */
3298944Sobrien
3319370Spst#include <sys/types.h>
3419370Spst#include "namespace.h"
3519370Spst#include <sys/acl.h>
36130803Smarcel#include "un-namespace.h"
3719370Spst#include <sys/errno.h>
3846283Sdfr#include <stdio.h>
3998944Sobrien#include <stdlib.h>
4046283Sdfr#include <string.h>
4119370Spst#include <utmp.h>
4298944Sobrien
4398944Sobrien#include "acl_support.h"
4498944Sobrien
4598944Sobrien/*
4698944Sobrien * acl_to_text - generate a text form of an acl
4798944Sobrien * spec says nothing about output ordering, so leave in acl order
4898944Sobrien *
4998944Sobrien * This function will not produce nice results if it is called with
50130803Smarcel * a non-POSIX.1e semantics ACL.
51130803Smarcel */
5298944Sobrienchar *
5398944Sobrienacl_to_text(acl_t acl, ssize_t *len_p)
5498944Sobrien{
5519370Spst	struct acl	*acl_int;
5698944Sobrien	char		*buf, *tmpbuf;
5719370Spst	char		 name_buf[UT_NAMESIZE+1];
5819370Spst	char		 perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
5919370Spst			 effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
6019370Spst	int		 i, error, len;
6119370Spst	uid_t		 ae_id;
6298944Sobrien	acl_tag_t	 ae_tag;
6319370Spst	acl_perm_t	 ae_perm, effective_perm, mask_perm;
6419370Spst
6519370Spst	buf = strdup("");
6698944Sobrien	if (buf == NULL)
6719370Spst		return(NULL);
6819370Spst
6919370Spst	if (acl == NULL) {
7098944Sobrien		errno = EINVAL;
7198944Sobrien		return(NULL);
7219370Spst	}
7398944Sobrien
7498944Sobrien	acl_int = &acl->ats_acl;
7598944Sobrien
7619370Spst	mask_perm = ACL_PERM_BITS;	/* effective is regular if no mask */
7719370Spst	for (i = 0; i < acl_int->acl_cnt; i++)
7819370Spst		if (acl_int->acl_entry[i].ae_tag == ACL_MASK)
79130803Smarcel			mask_perm = acl_int->acl_entry[i].ae_perm;
8098944Sobrien
8119370Spst	for (i = 0; i < acl_int->acl_cnt; i++) {
8298944Sobrien		ae_tag = acl_int->acl_entry[i].ae_tag;
8398944Sobrien		ae_id = acl_int->acl_entry[i].ae_id;
8419370Spst		ae_perm = acl_int->acl_entry[i].ae_perm;
8519370Spst
8619370Spst		switch(ae_tag) {
8719370Spst		case ACL_USER_OBJ:
8819370Spst			error = _posix1e_acl_perm_to_string(ae_perm,
8998944Sobrien			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
9098944Sobrien			if (error)
9119370Spst				goto error_label;
9298944Sobrien			len = asprintf(&tmpbuf, "%suser::%s\n", buf,
9398944Sobrien			    perm_buf);
9419370Spst			if (len == -1)
9519370Spst				goto error_label;
9698944Sobrien			free(buf);
9798944Sobrien			buf = tmpbuf;
9898944Sobrien			break;
9998944Sobrien
10098944Sobrien		case ACL_USER:
10198944Sobrien			error = _posix1e_acl_perm_to_string(ae_perm,
10219370Spst			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
103130803Smarcel			if (error)
10498944Sobrien				goto error_label;
10519370Spst
10698944Sobrien			error = _posix1e_acl_id_to_name(ae_tag, ae_id,
107130803Smarcel			    UT_NAMESIZE+1, name_buf);
108130803Smarcel			if (error)
109130803Smarcel				goto error_label;
11098944Sobrien
11119370Spst			effective_perm = ae_perm & mask_perm;
11219370Spst			if (effective_perm != ae_perm) {
11319370Spst				error = _posix1e_acl_perm_to_string(
11498944Sobrien				    effective_perm,
11598944Sobrien				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
11619370Spst				    effective_perm_buf);
11798944Sobrien				if (error)
11898944Sobrien					goto error_label;
11998944Sobrien				len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# "
12098944Sobrien				    "effective: %s\n",
12198944Sobrien				    buf, name_buf, perm_buf,
12219370Spst				    effective_perm_buf);
12398944Sobrien			} else {
12419370Spst				len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf,
12519370Spst				    name_buf, perm_buf);
12619370Spst			}
12719370Spst			if (len == -1)
12898944Sobrien				goto error_label;
12998944Sobrien			free(buf);
13019370Spst			buf = tmpbuf;
13119370Spst			break;
13298944Sobrien
13398944Sobrien		case ACL_GROUP_OBJ:
13419370Spst			error = _posix1e_acl_perm_to_string(ae_perm,
13519370Spst			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
13619370Spst			if (error)
137130803Smarcel				goto error_label;
13898944Sobrien
13919370Spst			effective_perm = ae_perm & mask_perm;
14098944Sobrien			if (effective_perm != ae_perm) {
14198944Sobrien				error = _posix1e_acl_perm_to_string(
14219370Spst				    effective_perm,
14319370Spst				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
14419370Spst				    effective_perm_buf);
14519370Spst				if (error)
14619370Spst					goto error_label;
14798944Sobrien				len = asprintf(&tmpbuf, "%sgroup::%s\t\t# "
14898944Sobrien				    "effective: %s\n",
14919370Spst				    buf, perm_buf, effective_perm_buf);
15098944Sobrien			} else {
15198944Sobrien				len = asprintf(&tmpbuf, "%sgroup::%s\n", buf,
15219370Spst				    perm_buf);
15319370Spst			}
15498944Sobrien			if (len == -1)
15598944Sobrien				goto error_label;
15698944Sobrien			free(buf);
15719370Spst			buf = tmpbuf;
15898944Sobrien			break;
15998944Sobrien
16098944Sobrien		case ACL_GROUP:
16198944Sobrien			error = _posix1e_acl_perm_to_string(ae_perm,
16219370Spst			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
16398944Sobrien			if (error)
16498944Sobrien				goto error_label;
16519370Spst
166130803Smarcel			error = _posix1e_acl_id_to_name(ae_tag, ae_id,
16798944Sobrien			    UT_NAMESIZE+1, name_buf);
16819370Spst			if (error)
16998944Sobrien				goto error_label;
170130803Smarcel
171130803Smarcel			effective_perm = ae_perm & mask_perm;
172130803Smarcel			if (effective_perm != ae_perm) {
17398944Sobrien				error = _posix1e_acl_perm_to_string(
17419370Spst				    effective_perm,
17519370Spst				    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
17619370Spst				    effective_perm_buf);
17798944Sobrien				if (error)
17819370Spst					goto error_label;
17919370Spst				len = asprintf(&tmpbuf, "%sgroup::%s\t\t# "
18098944Sobrien				    "effective: %s\n",
18198944Sobrien				    buf, perm_buf, effective_perm_buf);
18298944Sobrien			} else {
18398944Sobrien				len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf,
18498944Sobrien				    name_buf, perm_buf);
18519370Spst			}
18698944Sobrien			if (len == -1)
18719370Spst				goto error_label;
18819370Spst			free(buf);
18919370Spst			buf = tmpbuf;
19019370Spst			break;
19198944Sobrien
19219370Spst		case ACL_MASK:
19346283Sdfr			error = _posix1e_acl_perm_to_string(ae_perm,
19498944Sobrien			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
19519370Spst			if (error)
19619370Spst				goto error_label;
19798944Sobrien
19898944Sobrien			len = asprintf(&tmpbuf, "%smask::%s\n", buf,
19998944Sobrien			    perm_buf);
20019370Spst			if (len == -1)
20119370Spst				goto error_label;
20219370Spst			free(buf);
20319370Spst			buf = tmpbuf;
20419370Spst			break;
20598944Sobrien
20619370Spst		case ACL_OTHER:
20798944Sobrien			error = _posix1e_acl_perm_to_string(ae_perm,
20898944Sobrien			    _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
20998944Sobrien			if (error)
21098944Sobrien				goto error_label;
21119370Spst
21298944Sobrien			len = asprintf(&tmpbuf, "%sother::%s\n", buf,
21398944Sobrien			    perm_buf);
21498944Sobrien			if (len == -1)
21519370Spst				goto error_label;
21698944Sobrien			free(buf);
21798944Sobrien			buf = tmpbuf;
21898944Sobrien			break;
21919370Spst
22098944Sobrien		default:
22198944Sobrien			errno = EINVAL;
22298944Sobrien			goto error_label;
22398944Sobrien		}
22419370Spst	}
22519370Spst
22698944Sobrien	if (len_p) {
22719370Spst		*len_p = strlen(buf);
22819370Spst	}
22998944Sobrien	return (buf);
23019370Spst
23198944Sobrienerror_label:
23298944Sobrien	/* jump to here sets errno already, we just clean up */
23319370Spst	if (buf) free(buf);
23419370Spst	return (NULL);
23519370Spst}
23619370Spst