Home | History | Annotate | Line # | Download | only in common
nfs_commonacl.c revision 1.1.1.2
      1      1.1  dholland /*	$NetBSD: nfs_commonacl.c,v 1.1.1.2 2016/11/18 07:49:12 pgoyette Exp $	*/
      2      1.1  dholland /*-
      3      1.1  dholland  * Copyright (c) 2009 Rick Macklem, University of Guelph
      4      1.1  dholland  * All rights reserved.
      5      1.1  dholland  *
      6      1.1  dholland  * Redistribution and use in source and binary forms, with or without
      7      1.1  dholland  * modification, are permitted provided that the following conditions
      8      1.1  dholland  * are met:
      9      1.1  dholland  * 1. Redistributions of source code must retain the above copyright
     10      1.1  dholland  *    notice, this list of conditions and the following disclaimer.
     11      1.1  dholland  * 2. Redistributions in binary form must reproduce the above copyright
     12      1.1  dholland  *    notice, this list of conditions and the following disclaimer in the
     13      1.1  dholland  *    documentation and/or other materials provided with the distribution.
     14      1.1  dholland  *
     15      1.1  dholland  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16      1.1  dholland  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17      1.1  dholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18      1.1  dholland  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19      1.1  dholland  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20      1.1  dholland  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21      1.1  dholland  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22      1.1  dholland  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23      1.1  dholland  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24      1.1  dholland  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25      1.1  dholland  * SUCH DAMAGE.
     26      1.1  dholland  *
     27      1.1  dholland  */
     28      1.1  dholland 
     29      1.1  dholland #include <sys/cdefs.h>
     30  1.1.1.2  pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfs/nfs_commonacl.c 297793 2016-04-10 23:07:00Z pfg "); */
     31      1.1  dholland __RCSID("$NetBSD: nfs_commonacl.c,v 1.1.1.2 2016/11/18 07:49:12 pgoyette Exp $");
     32      1.1  dholland 
     33      1.1  dholland #ifndef APPLEKEXT
     34      1.1  dholland #include <fs/nfs/nfsport.h>
     35      1.1  dholland 
     36      1.1  dholland extern int nfsrv_useacl;
     37      1.1  dholland #endif
     38      1.1  dholland 
     39      1.1  dholland static int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
     40      1.1  dholland     enum vtype type, acl_perm_t *permp);
     41      1.1  dholland 
     42      1.1  dholland /*
     43      1.1  dholland  * Handle xdr for an ace.
     44      1.1  dholland  */
     45      1.1  dholland APPLESTATIC int
     46      1.1  dholland nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
     47      1.1  dholland     int *aceerrp, int *acesizep, NFSPROC_T *p)
     48      1.1  dholland {
     49      1.1  dholland 	u_int32_t *tl;
     50      1.1  dholland 	int len, gotid = 0, owner = 0, error = 0, aceerr = 0;
     51      1.1  dholland 	u_char *name, namestr[NFSV4_SMALLSTR + 1];
     52      1.1  dholland 	u_int32_t flag, mask, acetype;
     53      1.1  dholland 	gid_t gid;
     54      1.1  dholland 	uid_t uid;
     55      1.1  dholland 
     56      1.1  dholland 	*aceerrp = 0;
     57      1.1  dholland 	acep->ae_flags = 0;
     58      1.1  dholland 	NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
     59      1.1  dholland 	acetype = fxdr_unsigned(u_int32_t, *tl++);
     60      1.1  dholland 	flag = fxdr_unsigned(u_int32_t, *tl++);
     61      1.1  dholland 	mask = fxdr_unsigned(u_int32_t, *tl++);
     62      1.1  dholland 	len = fxdr_unsigned(int, *tl);
     63      1.1  dholland 	if (len < 0) {
     64      1.1  dholland 		error = NFSERR_BADXDR;
     65      1.1  dholland 		goto nfsmout;
     66      1.1  dholland 	} else if (len == 0) {
     67      1.1  dholland 		/* Netapp filers return a 0 length who for nil users */
     68      1.1  dholland 		acep->ae_tag = ACL_UNDEFINED_TAG;
     69      1.1  dholland 		acep->ae_id = ACL_UNDEFINED_ID;
     70      1.1  dholland 		acep->ae_perm = (acl_perm_t)0;
     71      1.1  dholland 		acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
     72      1.1  dholland 		if (acesizep)
     73      1.1  dholland 			*acesizep = 4 * NFSX_UNSIGNED;
     74      1.1  dholland 		error = 0;
     75      1.1  dholland 		goto nfsmout;
     76      1.1  dholland 	}
     77      1.1  dholland 	if (len > NFSV4_SMALLSTR)
     78      1.1  dholland 		name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
     79      1.1  dholland 	else
     80      1.1  dholland 		name = namestr;
     81      1.1  dholland 	error = nfsrv_mtostr(nd, name, len);
     82      1.1  dholland 	if (error) {
     83      1.1  dholland 		if (len > NFSV4_SMALLSTR)
     84      1.1  dholland 			free(name, M_NFSSTRING);
     85      1.1  dholland 		goto nfsmout;
     86      1.1  dholland 	}
     87      1.1  dholland 	if (len == 6) {
     88      1.1  dholland 		if (!NFSBCMP(name, "OWNER@", 6)) {
     89      1.1  dholland 			acep->ae_tag = ACL_USER_OBJ;
     90      1.1  dholland 			acep->ae_id = ACL_UNDEFINED_ID;
     91      1.1  dholland 			owner = 1;
     92      1.1  dholland 			gotid = 1;
     93      1.1  dholland 		} else if (!NFSBCMP(name, "GROUP@", 6)) {
     94      1.1  dholland 			acep->ae_tag = ACL_GROUP_OBJ;
     95      1.1  dholland 			acep->ae_id = ACL_UNDEFINED_ID;
     96      1.1  dholland 			gotid = 1;
     97      1.1  dholland 		}
     98      1.1  dholland 	} else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) {
     99      1.1  dholland 		acep->ae_tag = ACL_EVERYONE;
    100      1.1  dholland 		acep->ae_id = ACL_UNDEFINED_ID;
    101      1.1  dholland 		gotid = 1;
    102      1.1  dholland 	}
    103      1.1  dholland 	if (gotid == 0) {
    104      1.1  dholland 		if (flag & NFSV4ACE_IDENTIFIERGROUP) {
    105      1.1  dholland 			acep->ae_tag = ACL_GROUP;
    106      1.1  dholland 			aceerr = nfsv4_strtogid(nd, name, len, &gid, p);
    107      1.1  dholland 			if (aceerr == 0)
    108      1.1  dholland 				acep->ae_id = (uid_t)gid;
    109      1.1  dholland 		} else {
    110      1.1  dholland 			acep->ae_tag = ACL_USER;
    111      1.1  dholland 			aceerr = nfsv4_strtouid(nd, name, len, &uid, p);
    112      1.1  dholland 			if (aceerr == 0)
    113      1.1  dholland 				acep->ae_id = uid;
    114      1.1  dholland 		}
    115      1.1  dholland 	}
    116      1.1  dholland 	if (len > NFSV4_SMALLSTR)
    117      1.1  dholland 		free(name, M_NFSSTRING);
    118      1.1  dholland 
    119      1.1  dholland 	if (aceerr == 0) {
    120      1.1  dholland 		/*
    121      1.1  dholland 		 * Handle the flags.
    122      1.1  dholland 		 */
    123      1.1  dholland 		flag &= ~NFSV4ACE_IDENTIFIERGROUP;
    124      1.1  dholland 		if (flag & NFSV4ACE_FILEINHERIT) {
    125      1.1  dholland 			flag &= ~NFSV4ACE_FILEINHERIT;
    126      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_FILE_INHERIT;
    127      1.1  dholland 		}
    128      1.1  dholland 		if (flag & NFSV4ACE_DIRECTORYINHERIT) {
    129      1.1  dholland 			flag &= ~NFSV4ACE_DIRECTORYINHERIT;
    130      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT;
    131      1.1  dholland 		}
    132      1.1  dholland 		if (flag & NFSV4ACE_NOPROPAGATEINHERIT) {
    133      1.1  dholland 			flag &= ~NFSV4ACE_NOPROPAGATEINHERIT;
    134      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT;
    135      1.1  dholland 		}
    136      1.1  dholland 		if (flag & NFSV4ACE_INHERITONLY) {
    137      1.1  dholland 			flag &= ~NFSV4ACE_INHERITONLY;
    138      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
    139      1.1  dholland 		}
    140      1.1  dholland 		if (flag & NFSV4ACE_SUCCESSFULACCESS) {
    141      1.1  dholland 			flag &= ~NFSV4ACE_SUCCESSFULACCESS;
    142      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS;
    143      1.1  dholland 		}
    144      1.1  dholland 		if (flag & NFSV4ACE_FAILEDACCESS) {
    145      1.1  dholland 			flag &= ~NFSV4ACE_FAILEDACCESS;
    146      1.1  dholland 			acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS;
    147      1.1  dholland 		}
    148      1.1  dholland 		/*
    149      1.1  dholland 		 * Set ae_entry_type.
    150      1.1  dholland 		 */
    151      1.1  dholland 		if (acetype == NFSV4ACE_ALLOWEDTYPE)
    152      1.1  dholland 			acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
    153      1.1  dholland 		else if (acetype == NFSV4ACE_DENIEDTYPE)
    154      1.1  dholland 			acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
    155      1.1  dholland 		else if (acetype == NFSV4ACE_AUDITTYPE)
    156      1.1  dholland 			acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
    157      1.1  dholland 		else if (acetype == NFSV4ACE_ALARMTYPE)
    158      1.1  dholland 			acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
    159      1.1  dholland 		else
    160      1.1  dholland 			aceerr = NFSERR_ATTRNOTSUPP;
    161      1.1  dholland 	}
    162      1.1  dholland 
    163      1.1  dholland 	/*
    164      1.1  dholland 	 * Now, check for unsupported flag bits.
    165      1.1  dholland 	 */
    166      1.1  dholland 	if (aceerr == 0 && flag != 0)
    167      1.1  dholland 		aceerr = NFSERR_ATTRNOTSUPP;
    168      1.1  dholland 
    169      1.1  dholland 	/*
    170      1.1  dholland 	 * And turn the mask into perm bits.
    171      1.1  dholland 	 */
    172      1.1  dholland 	if (aceerr == 0)
    173      1.1  dholland 		aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG,
    174      1.1  dholland 		    &acep->ae_perm);
    175      1.1  dholland 	*aceerrp = aceerr;
    176      1.1  dholland 	if (acesizep)
    177      1.1  dholland 		*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
    178      1.1  dholland 	error = 0;
    179      1.1  dholland nfsmout:
    180      1.1  dholland 	NFSEXITCODE(error);
    181      1.1  dholland 	return (error);
    182      1.1  dholland }
    183      1.1  dholland 
    184      1.1  dholland /*
    185      1.1  dholland  * Turn an NFSv4 ace mask into R/W/X flag bits.
    186      1.1  dholland  */
    187      1.1  dholland static int
    188      1.1  dholland nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
    189      1.1  dholland     enum vtype type, acl_perm_t *permp)
    190      1.1  dholland {
    191      1.1  dholland 	acl_perm_t perm = 0x0;
    192      1.1  dholland 	int error = 0;
    193      1.1  dholland 
    194      1.1  dholland 	if (mask & NFSV4ACE_READDATA) {
    195      1.1  dholland 		mask &= ~NFSV4ACE_READDATA;
    196      1.1  dholland 		perm |= ACL_READ_DATA;
    197      1.1  dholland 	}
    198      1.1  dholland 	if (mask & NFSV4ACE_LISTDIRECTORY) {
    199      1.1  dholland 		mask &= ~NFSV4ACE_LISTDIRECTORY;
    200      1.1  dholland 		perm |= ACL_LIST_DIRECTORY;
    201      1.1  dholland 	}
    202      1.1  dholland 	if (mask & NFSV4ACE_WRITEDATA) {
    203      1.1  dholland 		mask &= ~NFSV4ACE_WRITEDATA;
    204      1.1  dholland 		perm |= ACL_WRITE_DATA;
    205      1.1  dholland 	}
    206      1.1  dholland 	if (mask & NFSV4ACE_ADDFILE) {
    207      1.1  dholland 		mask &= ~NFSV4ACE_ADDFILE;
    208      1.1  dholland 		perm |= ACL_ADD_FILE;
    209      1.1  dholland 	}
    210      1.1  dholland 	if (mask & NFSV4ACE_APPENDDATA) {
    211      1.1  dholland 		mask &= ~NFSV4ACE_APPENDDATA;
    212      1.1  dholland 		perm |= ACL_APPEND_DATA;
    213      1.1  dholland 	}
    214      1.1  dholland 	if (mask & NFSV4ACE_ADDSUBDIRECTORY) {
    215      1.1  dholland 		mask &= ~NFSV4ACE_ADDSUBDIRECTORY;
    216      1.1  dholland 		perm |= ACL_ADD_SUBDIRECTORY;
    217      1.1  dholland 	}
    218      1.1  dholland 	if (mask & NFSV4ACE_READNAMEDATTR) {
    219      1.1  dholland 		mask &= ~NFSV4ACE_READNAMEDATTR;
    220      1.1  dholland 		perm |= ACL_READ_NAMED_ATTRS;
    221      1.1  dholland 	}
    222      1.1  dholland 	if (mask & NFSV4ACE_WRITENAMEDATTR) {
    223      1.1  dholland 		mask &= ~NFSV4ACE_WRITENAMEDATTR;
    224      1.1  dholland 		perm |= ACL_WRITE_NAMED_ATTRS;
    225      1.1  dholland 	}
    226      1.1  dholland 	if (mask & NFSV4ACE_EXECUTE) {
    227      1.1  dholland 		mask &= ~NFSV4ACE_EXECUTE;
    228      1.1  dholland 		perm |= ACL_EXECUTE;
    229      1.1  dholland 	}
    230      1.1  dholland 	if (mask & NFSV4ACE_SEARCH) {
    231      1.1  dholland 		mask &= ~NFSV4ACE_SEARCH;
    232      1.1  dholland 		perm |= ACL_EXECUTE;
    233      1.1  dholland 	}
    234      1.1  dholland 	if (mask & NFSV4ACE_DELETECHILD) {
    235      1.1  dholland 		mask &= ~NFSV4ACE_DELETECHILD;
    236      1.1  dholland 		perm |= ACL_DELETE_CHILD;
    237      1.1  dholland 	}
    238      1.1  dholland 	if (mask & NFSV4ACE_READATTRIBUTES) {
    239      1.1  dholland 		mask &= ~NFSV4ACE_READATTRIBUTES;
    240      1.1  dholland 		perm |= ACL_READ_ATTRIBUTES;
    241      1.1  dholland 	}
    242      1.1  dholland 	if (mask & NFSV4ACE_WRITEATTRIBUTES) {
    243      1.1  dholland 		mask &= ~NFSV4ACE_WRITEATTRIBUTES;
    244      1.1  dholland 		perm |= ACL_WRITE_ATTRIBUTES;
    245      1.1  dholland 	}
    246      1.1  dholland 	if (mask & NFSV4ACE_DELETE) {
    247      1.1  dholland 		mask &= ~NFSV4ACE_DELETE;
    248      1.1  dholland 		perm |= ACL_DELETE;
    249      1.1  dholland 	}
    250      1.1  dholland 	if (mask & NFSV4ACE_READACL) {
    251      1.1  dholland 		mask &= ~NFSV4ACE_READACL;
    252      1.1  dholland 		perm |= ACL_READ_ACL;
    253      1.1  dholland 	}
    254      1.1  dholland 	if (mask & NFSV4ACE_WRITEACL) {
    255      1.1  dholland 		mask &= ~NFSV4ACE_WRITEACL;
    256      1.1  dholland 		perm |= ACL_WRITE_ACL;
    257      1.1  dholland 	}
    258      1.1  dholland 	if (mask & NFSV4ACE_WRITEOWNER) {
    259      1.1  dholland 		mask &= ~NFSV4ACE_WRITEOWNER;
    260      1.1  dholland 		perm |= ACL_WRITE_OWNER;
    261      1.1  dholland 	}
    262      1.1  dholland 	if (mask & NFSV4ACE_SYNCHRONIZE) {
    263      1.1  dholland 		mask &= ~NFSV4ACE_SYNCHRONIZE;
    264      1.1  dholland 		perm |= ACL_SYNCHRONIZE;
    265      1.1  dholland 	}
    266      1.1  dholland 	if (mask != 0) {
    267      1.1  dholland 		error = NFSERR_ATTRNOTSUPP;
    268      1.1  dholland 		goto out;
    269      1.1  dholland 	}
    270      1.1  dholland 	*permp = perm;
    271      1.1  dholland 
    272      1.1  dholland out:
    273      1.1  dholland 	NFSEXITCODE(error);
    274      1.1  dholland 	return (error);
    275      1.1  dholland }
    276      1.1  dholland 
    277      1.1  dholland /* local functions */
    278      1.1  dholland static int nfsrv_buildace(struct nfsrv_descript *, u_char *, int,
    279      1.1  dholland     enum vtype, int, int, struct acl_entry *);
    280      1.1  dholland 
    281      1.1  dholland /*
    282      1.1  dholland  * This function builds an NFS ace.
    283      1.1  dholland  */
    284      1.1  dholland static int
    285      1.1  dholland nfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen,
    286      1.1  dholland     enum vtype type, int group, int owner, struct acl_entry *ace)
    287      1.1  dholland {
    288      1.1  dholland 	u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype;
    289      1.1  dholland 	int full_len;
    290      1.1  dholland 
    291      1.1  dholland 	full_len = NFSM_RNDUP(namelen);
    292      1.1  dholland 	NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len);
    293      1.1  dholland 
    294      1.1  dholland 	/*
    295      1.1  dholland 	 * Fill in the ace type.
    296      1.1  dholland 	 */
    297      1.1  dholland 	if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW)
    298      1.1  dholland 		acetype = NFSV4ACE_ALLOWEDTYPE;
    299      1.1  dholland 	else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY)
    300      1.1  dholland 		acetype = NFSV4ACE_DENIEDTYPE;
    301      1.1  dholland 	else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT)
    302      1.1  dholland 		acetype = NFSV4ACE_AUDITTYPE;
    303      1.1  dholland 	else
    304      1.1  dholland 		acetype = NFSV4ACE_ALARMTYPE;
    305      1.1  dholland 	*tl++ = txdr_unsigned(acetype);
    306      1.1  dholland 
    307      1.1  dholland 	/*
    308      1.1  dholland 	 * Set the flag bits from the ACL.
    309      1.1  dholland 	 */
    310      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT)
    311      1.1  dholland 		aceflag |= NFSV4ACE_FILEINHERIT;
    312      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT)
    313      1.1  dholland 		aceflag |= NFSV4ACE_DIRECTORYINHERIT;
    314      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)
    315      1.1  dholland 		aceflag |= NFSV4ACE_NOPROPAGATEINHERIT;
    316      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY)
    317      1.1  dholland 		aceflag |= NFSV4ACE_INHERITONLY;
    318      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS)
    319      1.1  dholland 		aceflag |= NFSV4ACE_SUCCESSFULACCESS;
    320      1.1  dholland 	if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS)
    321      1.1  dholland 		aceflag |= NFSV4ACE_FAILEDACCESS;
    322      1.1  dholland 	if (group)
    323      1.1  dholland 		aceflag |= NFSV4ACE_IDENTIFIERGROUP;
    324      1.1  dholland 	*tl++ = txdr_unsigned(aceflag);
    325      1.1  dholland 	if (type == VDIR) {
    326      1.1  dholland 		if (ace->ae_perm & ACL_LIST_DIRECTORY)
    327      1.1  dholland 			acemask |= NFSV4ACE_LISTDIRECTORY;
    328      1.1  dholland 		if (ace->ae_perm & ACL_ADD_FILE)
    329      1.1  dholland 			acemask |= NFSV4ACE_ADDFILE;
    330      1.1  dholland 		if (ace->ae_perm & ACL_ADD_SUBDIRECTORY)
    331      1.1  dholland 			acemask |= NFSV4ACE_ADDSUBDIRECTORY;
    332      1.1  dholland 		if (ace->ae_perm & ACL_READ_NAMED_ATTRS)
    333      1.1  dholland 			acemask |= NFSV4ACE_READNAMEDATTR;
    334      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS)
    335      1.1  dholland 			acemask |= NFSV4ACE_WRITENAMEDATTR;
    336      1.1  dholland 		if (ace->ae_perm & ACL_EXECUTE)
    337      1.1  dholland 			acemask |= NFSV4ACE_SEARCH;
    338      1.1  dholland 		if (ace->ae_perm & ACL_DELETE_CHILD)
    339      1.1  dholland 			acemask |= NFSV4ACE_DELETECHILD;
    340      1.1  dholland 		if (ace->ae_perm & ACL_READ_ATTRIBUTES)
    341      1.1  dholland 			acemask |= NFSV4ACE_READATTRIBUTES;
    342      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_ATTRIBUTES)
    343      1.1  dholland 			acemask |= NFSV4ACE_WRITEATTRIBUTES;
    344      1.1  dholland 		if (ace->ae_perm & ACL_DELETE)
    345      1.1  dholland 			acemask |= NFSV4ACE_DELETE;
    346      1.1  dholland 		if (ace->ae_perm & ACL_READ_ACL)
    347      1.1  dholland 			acemask |= NFSV4ACE_READACL;
    348      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_ACL)
    349      1.1  dholland 			acemask |= NFSV4ACE_WRITEACL;
    350      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_OWNER)
    351      1.1  dholland 			acemask |= NFSV4ACE_WRITEOWNER;
    352  1.1.1.2  pgoyette 		if (ace->ae_perm & ACL_SYNCHRONIZE)
    353  1.1.1.2  pgoyette 			acemask |= NFSV4ACE_SYNCHRONIZE;
    354      1.1  dholland 	} else {
    355      1.1  dholland 		if (ace->ae_perm & ACL_READ_DATA)
    356      1.1  dholland 			acemask |= NFSV4ACE_READDATA;
    357      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_DATA)
    358      1.1  dholland 			acemask |= NFSV4ACE_WRITEDATA;
    359      1.1  dholland 		if (ace->ae_perm & ACL_APPEND_DATA)
    360      1.1  dholland 			acemask |= NFSV4ACE_APPENDDATA;
    361      1.1  dholland 		if (ace->ae_perm & ACL_READ_NAMED_ATTRS)
    362      1.1  dholland 			acemask |= NFSV4ACE_READNAMEDATTR;
    363      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS)
    364      1.1  dholland 			acemask |= NFSV4ACE_WRITENAMEDATTR;
    365      1.1  dholland 		if (ace->ae_perm & ACL_EXECUTE)
    366      1.1  dholland 			acemask |= NFSV4ACE_EXECUTE;
    367      1.1  dholland 		if (ace->ae_perm & ACL_READ_ATTRIBUTES)
    368      1.1  dholland 			acemask |= NFSV4ACE_READATTRIBUTES;
    369      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_ATTRIBUTES)
    370      1.1  dholland 			acemask |= NFSV4ACE_WRITEATTRIBUTES;
    371      1.1  dholland 		if (ace->ae_perm & ACL_DELETE)
    372      1.1  dholland 			acemask |= NFSV4ACE_DELETE;
    373      1.1  dholland 		if (ace->ae_perm & ACL_READ_ACL)
    374      1.1  dholland 			acemask |= NFSV4ACE_READACL;
    375      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_ACL)
    376      1.1  dholland 			acemask |= NFSV4ACE_WRITEACL;
    377      1.1  dholland 		if (ace->ae_perm & ACL_WRITE_OWNER)
    378      1.1  dholland 			acemask |= NFSV4ACE_WRITEOWNER;
    379      1.1  dholland 		if (ace->ae_perm & ACL_SYNCHRONIZE)
    380      1.1  dholland 			acemask |= NFSV4ACE_SYNCHRONIZE;
    381      1.1  dholland 	}
    382      1.1  dholland 	*tl++ = txdr_unsigned(acemask);
    383      1.1  dholland 	*tl++ = txdr_unsigned(namelen);
    384      1.1  dholland 	if (full_len - namelen)
    385      1.1  dholland 		*(tl + (namelen / NFSX_UNSIGNED)) = 0x0;
    386      1.1  dholland 	NFSBCOPY(name, (caddr_t)tl, namelen);
    387      1.1  dholland 	return (full_len + 4 * NFSX_UNSIGNED);
    388      1.1  dholland }
    389      1.1  dholland 
    390      1.1  dholland /*
    391      1.1  dholland  * Build an NFSv4 ACL.
    392      1.1  dholland  */
    393      1.1  dholland APPLESTATIC int
    394      1.1  dholland nfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, enum vtype type,
    395      1.1  dholland     NFSPROC_T *p)
    396      1.1  dholland {
    397      1.1  dholland 	int i, entrycnt = 0, retlen;
    398      1.1  dholland 	u_int32_t *entrycntp;
    399      1.1  dholland 	int isowner, isgroup, namelen, malloced;
    400      1.1  dholland 	u_char *name, namestr[NFSV4_SMALLSTR];
    401      1.1  dholland 
    402      1.1  dholland 	NFSM_BUILD(entrycntp, u_int32_t *, NFSX_UNSIGNED);
    403      1.1  dholland 	retlen = NFSX_UNSIGNED;
    404      1.1  dholland 	/*
    405      1.1  dholland 	 * Loop through the acl entries, building each one.
    406      1.1  dholland 	 */
    407      1.1  dholland 	for (i = 0; i < aclp->acl_cnt; i++) {
    408      1.1  dholland 		isowner = isgroup = malloced = 0;
    409      1.1  dholland 		switch (aclp->acl_entry[i].ae_tag) {
    410      1.1  dholland 		case ACL_USER_OBJ:
    411      1.1  dholland 			isowner = 1;
    412      1.1  dholland 			name = "OWNER@";
    413      1.1  dholland 			namelen = 6;
    414      1.1  dholland 			break;
    415      1.1  dholland 		case ACL_GROUP_OBJ:
    416      1.1  dholland 			isgroup = 1;
    417      1.1  dholland 			name = "GROUP@";
    418      1.1  dholland 			namelen = 6;
    419      1.1  dholland 			break;
    420      1.1  dholland 		case ACL_EVERYONE:
    421      1.1  dholland 			name = "EVERYONE@";
    422      1.1  dholland 			namelen = 9;
    423      1.1  dholland 			break;
    424      1.1  dholland 		case ACL_USER:
    425      1.1  dholland 			name = namestr;
    426      1.1  dholland 			nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name,
    427      1.1  dholland 			    &namelen, p);
    428      1.1  dholland 			if (name != namestr)
    429      1.1  dholland 				malloced = 1;
    430      1.1  dholland 			break;
    431      1.1  dholland 		case ACL_GROUP:
    432      1.1  dholland 			isgroup = 1;
    433      1.1  dholland 			name = namestr;
    434      1.1  dholland 			nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name,
    435      1.1  dholland 			    &namelen, p);
    436      1.1  dholland 			if (name != namestr)
    437      1.1  dholland 				malloced = 1;
    438      1.1  dholland 			break;
    439      1.1  dholland 		default:
    440      1.1  dholland 			continue;
    441  1.1.1.2  pgoyette 		}
    442      1.1  dholland 		retlen += nfsrv_buildace(nd, name, namelen, type, isgroup,
    443      1.1  dholland 		    isowner, &aclp->acl_entry[i]);
    444      1.1  dholland 		entrycnt++;
    445      1.1  dholland 		if (malloced)
    446      1.1  dholland 			free(name, M_NFSSTRING);
    447      1.1  dholland 	}
    448      1.1  dholland 	*entrycntp = txdr_unsigned(entrycnt);
    449      1.1  dholland 	return (retlen);
    450      1.1  dholland }
    451      1.1  dholland 
    452      1.1  dholland /*
    453      1.1  dholland  * Set an NFSv4 acl.
    454      1.1  dholland  */
    455      1.1  dholland APPLESTATIC int
    456      1.1  dholland nfsrv_setacl(vnode_t vp, NFSACL_T *aclp, struct ucred *cred,
    457      1.1  dholland     NFSPROC_T *p)
    458      1.1  dholland {
    459      1.1  dholland 	int error;
    460      1.1  dholland 
    461      1.1  dholland 	if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) {
    462      1.1  dholland 		error = NFSERR_ATTRNOTSUPP;
    463      1.1  dholland 		goto out;
    464      1.1  dholland 	}
    465      1.1  dholland 	/*
    466      1.1  dholland 	 * With NFSv4 ACLs, chmod(2) may need to add additional entries.
    467      1.1  dholland 	 * Make sure it has enough room for that - splitting every entry
    468      1.1  dholland 	 * into two and appending "canonical six" entries at the end.
    469      1.1  dholland 	 * Cribbed out of kern/vfs_acl.c - Rick M.
    470      1.1  dholland 	 */
    471      1.1  dholland 	if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) {
    472      1.1  dholland 		error = NFSERR_ATTRNOTSUPP;
    473      1.1  dholland 		goto out;
    474      1.1  dholland 	}
    475      1.1  dholland 	error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p);
    476      1.1  dholland 
    477      1.1  dholland out:
    478      1.1  dholland 	NFSEXITCODE(error);
    479      1.1  dholland 	return (error);
    480      1.1  dholland }
    481      1.1  dholland 
    482      1.1  dholland /*
    483      1.1  dholland  * Compare two NFSv4 acls.
    484      1.1  dholland  * Return 0 if they are the same, 1 if not the same.
    485      1.1  dholland  */
    486      1.1  dholland APPLESTATIC int
    487      1.1  dholland nfsrv_compareacl(NFSACL_T *aclp1, NFSACL_T *aclp2)
    488      1.1  dholland {
    489      1.1  dholland 	int i;
    490      1.1  dholland 	struct acl_entry *acep1, *acep2;
    491      1.1  dholland 
    492      1.1  dholland 	if (aclp1->acl_cnt != aclp2->acl_cnt)
    493      1.1  dholland 		return (1);
    494      1.1  dholland 	acep1 = aclp1->acl_entry;
    495      1.1  dholland 	acep2 = aclp2->acl_entry;
    496      1.1  dholland 	for (i = 0; i < aclp1->acl_cnt; i++) {
    497      1.1  dholland 		if (acep1->ae_tag != acep2->ae_tag)
    498      1.1  dholland 			return (1);
    499      1.1  dholland 		switch (acep1->ae_tag) {
    500      1.1  dholland 		case ACL_GROUP:
    501      1.1  dholland 		case ACL_USER:
    502      1.1  dholland 			if (acep1->ae_id != acep2->ae_id)
    503      1.1  dholland 				return (1);
    504      1.1  dholland 			/* fall through */
    505      1.1  dholland 		case ACL_USER_OBJ:
    506      1.1  dholland 		case ACL_GROUP_OBJ:
    507      1.1  dholland 		case ACL_OTHER:
    508      1.1  dholland 			if (acep1->ae_perm != acep2->ae_perm)
    509      1.1  dholland 				return (1);
    510  1.1.1.2  pgoyette 		}
    511      1.1  dholland 		acep1++;
    512      1.1  dholland 		acep2++;
    513      1.1  dholland 	}
    514      1.1  dholland 	return (0);
    515      1.1  dholland }
    516