xref: /freebsd-src/sys/fs/nfs/nfs_commonacl.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
19ec7b004SRick Macklem /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d63027b6SPedro F. Giffuni  *
49ec7b004SRick Macklem  * Copyright (c) 2009 Rick Macklem, University of Guelph
59ec7b004SRick Macklem  * All rights reserved.
69ec7b004SRick Macklem  *
79ec7b004SRick Macklem  * Redistribution and use in source and binary forms, with or without
89ec7b004SRick Macklem  * modification, are permitted provided that the following conditions
99ec7b004SRick Macklem  * are met:
109ec7b004SRick Macklem  * 1. Redistributions of source code must retain the above copyright
119ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer.
129ec7b004SRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
139ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer in the
149ec7b004SRick Macklem  *    documentation and/or other materials provided with the distribution.
159ec7b004SRick Macklem  *
169ec7b004SRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179ec7b004SRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189ec7b004SRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199ec7b004SRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209ec7b004SRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219ec7b004SRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229ec7b004SRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239ec7b004SRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249ec7b004SRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259ec7b004SRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269ec7b004SRick Macklem  * SUCH DAMAGE.
279ec7b004SRick Macklem  *
289ec7b004SRick Macklem  */
299ec7b004SRick Macklem 
309ec7b004SRick Macklem #include <sys/cdefs.h>
319ec7b004SRick Macklem #include <fs/nfs/nfsport.h>
329ec7b004SRick Macklem 
339ec7b004SRick Macklem extern int nfsrv_useacl;
349ec7b004SRick Macklem 
359ec7b004SRick Macklem static int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
36*ba8cc6d7SMateusz Guzik     __enum_uint8(vtype) type, acl_perm_t *permp);
379ec7b004SRick Macklem 
389ec7b004SRick Macklem /*
399ec7b004SRick Macklem  * Handle xdr for an ace.
409ec7b004SRick Macklem  */
41b9cc3262SRyan Moeller int
nfsrv_dissectace(struct nfsrv_descript * nd,struct acl_entry * acep,bool server,int * aceerrp,int * acesizep,NFSPROC_T * p)429ec7b004SRick Macklem nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
43a91a5784SRick Macklem     bool server, int *aceerrp, int *acesizep, NFSPROC_T *p)
449ec7b004SRick Macklem {
459ec7b004SRick Macklem 	u_int32_t *tl;
469ec7b004SRick Macklem 	int len, gotid = 0, owner = 0, error = 0, aceerr = 0;
479ec7b004SRick Macklem 	u_char *name, namestr[NFSV4_SMALLSTR + 1];
489ec7b004SRick Macklem 	u_int32_t flag, mask, acetype;
499ec7b004SRick Macklem 	gid_t gid;
509ec7b004SRick Macklem 	uid_t uid;
519ec7b004SRick Macklem 
529ec7b004SRick Macklem 	*aceerrp = 0;
539ec7b004SRick Macklem 	acep->ae_flags = 0;
549ec7b004SRick Macklem 	NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
559ec7b004SRick Macklem 	acetype = fxdr_unsigned(u_int32_t, *tl++);
569ec7b004SRick Macklem 	flag = fxdr_unsigned(u_int32_t, *tl++);
579ec7b004SRick Macklem 	mask = fxdr_unsigned(u_int32_t, *tl++);
589ec7b004SRick Macklem 	len = fxdr_unsigned(int, *tl);
59db0ac6deSCy Schubert 	/*
60db0ac6deSCy Schubert 	 * The RFCs do not specify a limit to the length of the "who", but
61db0ac6deSCy Schubert 	 * NFSV4_OPAQUELIMIT (1024) should be sufficient.
62db0ac6deSCy Schubert 	 */
63db0ac6deSCy Schubert 	if (len < 0 || len > NFSV4_OPAQUELIMIT) {
64a9285ae5SZack Kirsch 		error = NFSERR_BADXDR;
65a9285ae5SZack Kirsch 		goto nfsmout;
669ec7b004SRick Macklem 	} else if (len == 0) {
679ec7b004SRick Macklem 		/* Netapp filers return a 0 length who for nil users */
689ec7b004SRick Macklem 		acep->ae_tag = ACL_UNDEFINED_TAG;
699ec7b004SRick Macklem 		acep->ae_id = ACL_UNDEFINED_ID;
709ec7b004SRick Macklem 		acep->ae_perm = (acl_perm_t)0;
71ff392a1dSEdward Tomasz Napierala 		acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
729ec7b004SRick Macklem 		if (acesizep)
739ec7b004SRick Macklem 			*acesizep = 4 * NFSX_UNSIGNED;
74a9285ae5SZack Kirsch 		error = 0;
75a9285ae5SZack Kirsch 		goto nfsmout;
769ec7b004SRick Macklem 	}
779ec7b004SRick Macklem 	if (len > NFSV4_SMALLSTR)
789ec7b004SRick Macklem 		name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
799ec7b004SRick Macklem 	else
809ec7b004SRick Macklem 		name = namestr;
819ec7b004SRick Macklem 	error = nfsrv_mtostr(nd, name, len);
829ec7b004SRick Macklem 	if (error) {
839ec7b004SRick Macklem 		if (len > NFSV4_SMALLSTR)
849ec7b004SRick Macklem 			free(name, M_NFSSTRING);
85a9285ae5SZack Kirsch 		goto nfsmout;
869ec7b004SRick Macklem 	}
879ec7b004SRick Macklem 	if (len == 6) {
889ec7b004SRick Macklem 		if (!NFSBCMP(name, "OWNER@", 6)) {
899ec7b004SRick Macklem 			acep->ae_tag = ACL_USER_OBJ;
909ec7b004SRick Macklem 			acep->ae_id = ACL_UNDEFINED_ID;
919ec7b004SRick Macklem 			owner = 1;
929ec7b004SRick Macklem 			gotid = 1;
939ec7b004SRick Macklem 		} else if (!NFSBCMP(name, "GROUP@", 6)) {
949ec7b004SRick Macklem 			acep->ae_tag = ACL_GROUP_OBJ;
959ec7b004SRick Macklem 			acep->ae_id = ACL_UNDEFINED_ID;
969ec7b004SRick Macklem 			gotid = 1;
979ec7b004SRick Macklem 		}
989ec7b004SRick Macklem 	} else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) {
999ec7b004SRick Macklem 		acep->ae_tag = ACL_EVERYONE;
1009ec7b004SRick Macklem 		acep->ae_id = ACL_UNDEFINED_ID;
1019ec7b004SRick Macklem 		gotid = 1;
1029ec7b004SRick Macklem 	}
1039ec7b004SRick Macklem 	if (gotid == 0) {
1049ec7b004SRick Macklem 		if (flag & NFSV4ACE_IDENTIFIERGROUP) {
1059ec7b004SRick Macklem 			acep->ae_tag = ACL_GROUP;
1062df8bd90SEdward Tomasz Napierala 			aceerr = nfsv4_strtogid(nd, name, len, &gid);
1079ec7b004SRick Macklem 			if (aceerr == 0)
1089ec7b004SRick Macklem 				acep->ae_id = (uid_t)gid;
1099ec7b004SRick Macklem 		} else {
1109ec7b004SRick Macklem 			acep->ae_tag = ACL_USER;
1110658ac39SEdward Tomasz Napierala 			aceerr = nfsv4_strtouid(nd, name, len, &uid);
1129ec7b004SRick Macklem 			if (aceerr == 0)
1139ec7b004SRick Macklem 				acep->ae_id = uid;
1149ec7b004SRick Macklem 		}
1159ec7b004SRick Macklem 	}
1169ec7b004SRick Macklem 	if (len > NFSV4_SMALLSTR)
1179ec7b004SRick Macklem 		free(name, M_NFSSTRING);
1189ec7b004SRick Macklem 
1199ec7b004SRick Macklem 	if (aceerr == 0) {
1209ec7b004SRick Macklem 		/*
1219ec7b004SRick Macklem 		 * Handle the flags.
1229ec7b004SRick Macklem 		 */
1239ec7b004SRick Macklem 		flag &= ~NFSV4ACE_IDENTIFIERGROUP;
1249ec7b004SRick Macklem 		if (flag & NFSV4ACE_FILEINHERIT) {
1259ec7b004SRick Macklem 			flag &= ~NFSV4ACE_FILEINHERIT;
1269ec7b004SRick Macklem 			acep->ae_flags |= ACL_ENTRY_FILE_INHERIT;
1279ec7b004SRick Macklem 		}
1289ec7b004SRick Macklem 		if (flag & NFSV4ACE_DIRECTORYINHERIT) {
1299ec7b004SRick Macklem 			flag &= ~NFSV4ACE_DIRECTORYINHERIT;
1309ec7b004SRick Macklem 			acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT;
1319ec7b004SRick Macklem 		}
1329ec7b004SRick Macklem 		if (flag & NFSV4ACE_NOPROPAGATEINHERIT) {
1339ec7b004SRick Macklem 			flag &= ~NFSV4ACE_NOPROPAGATEINHERIT;
134ff392a1dSEdward Tomasz Napierala 			acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT;
1359ec7b004SRick Macklem 		}
1369ec7b004SRick Macklem 		if (flag & NFSV4ACE_INHERITONLY) {
1379ec7b004SRick Macklem 			flag &= ~NFSV4ACE_INHERITONLY;
138ff392a1dSEdward Tomasz Napierala 			acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
1399ec7b004SRick Macklem 		}
1409ec7b004SRick Macklem 		if (flag & NFSV4ACE_SUCCESSFULACCESS) {
1419ec7b004SRick Macklem 			flag &= ~NFSV4ACE_SUCCESSFULACCESS;
1429ec7b004SRick Macklem 			acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS;
1439ec7b004SRick Macklem 		}
1449ec7b004SRick Macklem 		if (flag & NFSV4ACE_FAILEDACCESS) {
1459ec7b004SRick Macklem 			flag &= ~NFSV4ACE_FAILEDACCESS;
1469ec7b004SRick Macklem 			acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS;
1479ec7b004SRick Macklem 		}
1489ec7b004SRick Macklem 		/*
149ff392a1dSEdward Tomasz Napierala 		 * Set ae_entry_type.
1509ec7b004SRick Macklem 		 */
1519ec7b004SRick Macklem 		if (acetype == NFSV4ACE_ALLOWEDTYPE)
152ff392a1dSEdward Tomasz Napierala 			acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
1539ec7b004SRick Macklem 		else if (acetype == NFSV4ACE_DENIEDTYPE)
154ff392a1dSEdward Tomasz Napierala 			acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
155a91a5784SRick Macklem 		else if (!server && acetype == NFSV4ACE_AUDITTYPE)
156ff392a1dSEdward Tomasz Napierala 			acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
157a91a5784SRick Macklem 		else if (!server && acetype == NFSV4ACE_ALARMTYPE)
158ff392a1dSEdward Tomasz Napierala 			acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
1599ec7b004SRick Macklem 		else
1609ec7b004SRick Macklem 			aceerr = NFSERR_ATTRNOTSUPP;
1619ec7b004SRick Macklem 	}
1629ec7b004SRick Macklem 
1639ec7b004SRick Macklem 	/*
1649ec7b004SRick Macklem 	 * Now, check for unsupported flag bits.
1659ec7b004SRick Macklem 	 */
1669ec7b004SRick Macklem 	if (aceerr == 0 && flag != 0)
1679ec7b004SRick Macklem 		aceerr = NFSERR_ATTRNOTSUPP;
1689ec7b004SRick Macklem 
1699ec7b004SRick Macklem 	/*
1709ec7b004SRick Macklem 	 * And turn the mask into perm bits.
1719ec7b004SRick Macklem 	 */
1729ec7b004SRick Macklem 	if (aceerr == 0)
1739ec7b004SRick Macklem 		aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG,
1749ec7b004SRick Macklem 		    &acep->ae_perm);
1759ec7b004SRick Macklem 	*aceerrp = aceerr;
1769ec7b004SRick Macklem 	if (acesizep)
1779ec7b004SRick Macklem 		*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
178a9285ae5SZack Kirsch 	error = 0;
1799ec7b004SRick Macklem nfsmout:
180a9285ae5SZack Kirsch 	NFSEXITCODE(error);
1819ec7b004SRick Macklem 	return (error);
1829ec7b004SRick Macklem }
1839ec7b004SRick Macklem 
1849ec7b004SRick Macklem /*
1859ec7b004SRick Macklem  * Turn an NFSv4 ace mask into R/W/X flag bits.
1869ec7b004SRick Macklem  */
1879ec7b004SRick Macklem static int
nfsrv_acemasktoperm(u_int32_t acetype,u_int32_t mask,int owner,__enum_uint8 (vtype)type,acl_perm_t * permp)1889ec7b004SRick Macklem nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
189*ba8cc6d7SMateusz Guzik     __enum_uint8(vtype) type, acl_perm_t *permp)
1909ec7b004SRick Macklem {
1919ec7b004SRick Macklem 	acl_perm_t perm = 0x0;
192a9285ae5SZack Kirsch 	int error = 0;
1939ec7b004SRick Macklem 
1949ec7b004SRick Macklem 	if (mask & NFSV4ACE_READDATA) {
1959ec7b004SRick Macklem 		mask &= ~NFSV4ACE_READDATA;
1969ec7b004SRick Macklem 		perm |= ACL_READ_DATA;
1979ec7b004SRick Macklem 	}
1989ec7b004SRick Macklem 	if (mask & NFSV4ACE_LISTDIRECTORY) {
1999ec7b004SRick Macklem 		mask &= ~NFSV4ACE_LISTDIRECTORY;
2009ec7b004SRick Macklem 		perm |= ACL_LIST_DIRECTORY;
2019ec7b004SRick Macklem 	}
2029ec7b004SRick Macklem 	if (mask & NFSV4ACE_WRITEDATA) {
2039ec7b004SRick Macklem 		mask &= ~NFSV4ACE_WRITEDATA;
2049ec7b004SRick Macklem 		perm |= ACL_WRITE_DATA;
2059ec7b004SRick Macklem 	}
2069ec7b004SRick Macklem 	if (mask & NFSV4ACE_ADDFILE) {
2079ec7b004SRick Macklem 		mask &= ~NFSV4ACE_ADDFILE;
2089ec7b004SRick Macklem 		perm |= ACL_ADD_FILE;
2099ec7b004SRick Macklem 	}
2109ec7b004SRick Macklem 	if (mask & NFSV4ACE_APPENDDATA) {
2119ec7b004SRick Macklem 		mask &= ~NFSV4ACE_APPENDDATA;
2129ec7b004SRick Macklem 		perm |= ACL_APPEND_DATA;
2139ec7b004SRick Macklem 	}
2149ec7b004SRick Macklem 	if (mask & NFSV4ACE_ADDSUBDIRECTORY) {
2159ec7b004SRick Macklem 		mask &= ~NFSV4ACE_ADDSUBDIRECTORY;
2169ec7b004SRick Macklem 		perm |= ACL_ADD_SUBDIRECTORY;
2179ec7b004SRick Macklem 	}
2189ec7b004SRick Macklem 	if (mask & NFSV4ACE_READNAMEDATTR) {
2199ec7b004SRick Macklem 		mask &= ~NFSV4ACE_READNAMEDATTR;
2209ec7b004SRick Macklem 		perm |= ACL_READ_NAMED_ATTRS;
2219ec7b004SRick Macklem 	}
2229ec7b004SRick Macklem 	if (mask & NFSV4ACE_WRITENAMEDATTR) {
2239ec7b004SRick Macklem 		mask &= ~NFSV4ACE_WRITENAMEDATTR;
2249ec7b004SRick Macklem 		perm |= ACL_WRITE_NAMED_ATTRS;
2259ec7b004SRick Macklem 	}
2269ec7b004SRick Macklem 	if (mask & NFSV4ACE_EXECUTE) {
2279ec7b004SRick Macklem 		mask &= ~NFSV4ACE_EXECUTE;
2289ec7b004SRick Macklem 		perm |= ACL_EXECUTE;
2299ec7b004SRick Macklem 	}
2309ec7b004SRick Macklem 	if (mask & NFSV4ACE_SEARCH) {
2319ec7b004SRick Macklem 		mask &= ~NFSV4ACE_SEARCH;
232c3e22f83SRick Macklem 		perm |= ACL_EXECUTE;
2339ec7b004SRick Macklem 	}
2349ec7b004SRick Macklem 	if (mask & NFSV4ACE_DELETECHILD) {
2359ec7b004SRick Macklem 		mask &= ~NFSV4ACE_DELETECHILD;
2369ec7b004SRick Macklem 		perm |= ACL_DELETE_CHILD;
2379ec7b004SRick Macklem 	}
2389ec7b004SRick Macklem 	if (mask & NFSV4ACE_READATTRIBUTES) {
2399ec7b004SRick Macklem 		mask &= ~NFSV4ACE_READATTRIBUTES;
2409ec7b004SRick Macklem 		perm |= ACL_READ_ATTRIBUTES;
2419ec7b004SRick Macklem 	}
2429ec7b004SRick Macklem 	if (mask & NFSV4ACE_WRITEATTRIBUTES) {
2439ec7b004SRick Macklem 		mask &= ~NFSV4ACE_WRITEATTRIBUTES;
2449ec7b004SRick Macklem 		perm |= ACL_WRITE_ATTRIBUTES;
2459ec7b004SRick Macklem 	}
2469ec7b004SRick Macklem 	if (mask & NFSV4ACE_DELETE) {
2479ec7b004SRick Macklem 		mask &= ~NFSV4ACE_DELETE;
2489ec7b004SRick Macklem 		perm |= ACL_DELETE;
2499ec7b004SRick Macklem 	}
2509ec7b004SRick Macklem 	if (mask & NFSV4ACE_READACL) {
2519ec7b004SRick Macklem 		mask &= ~NFSV4ACE_READACL;
2529ec7b004SRick Macklem 		perm |= ACL_READ_ACL;
2539ec7b004SRick Macklem 	}
2549ec7b004SRick Macklem 	if (mask & NFSV4ACE_WRITEACL) {
2559ec7b004SRick Macklem 		mask &= ~NFSV4ACE_WRITEACL;
2569ec7b004SRick Macklem 		perm |= ACL_WRITE_ACL;
2579ec7b004SRick Macklem 	}
2589ec7b004SRick Macklem 	if (mask & NFSV4ACE_WRITEOWNER) {
2599ec7b004SRick Macklem 		mask &= ~NFSV4ACE_WRITEOWNER;
2609ec7b004SRick Macklem 		perm |= ACL_WRITE_OWNER;
2619ec7b004SRick Macklem 	}
2629ec7b004SRick Macklem 	if (mask & NFSV4ACE_SYNCHRONIZE) {
2639ec7b004SRick Macklem 		mask &= ~NFSV4ACE_SYNCHRONIZE;
2649ec7b004SRick Macklem 		perm |= ACL_SYNCHRONIZE;
2659ec7b004SRick Macklem 	}
266a9285ae5SZack Kirsch 	if (mask != 0) {
267a9285ae5SZack Kirsch 		error = NFSERR_ATTRNOTSUPP;
268a9285ae5SZack Kirsch 		goto out;
269a9285ae5SZack Kirsch 	}
2709ec7b004SRick Macklem 	*permp = perm;
271a9285ae5SZack Kirsch 
272a9285ae5SZack Kirsch out:
273a9285ae5SZack Kirsch 	NFSEXITCODE(error);
274a9285ae5SZack Kirsch 	return (error);
2759ec7b004SRick Macklem }
2769ec7b004SRick Macklem 
2779ec7b004SRick Macklem /* local functions */
2789ec7b004SRick Macklem static int nfsrv_buildace(struct nfsrv_descript *, u_char *, int,
279*ba8cc6d7SMateusz Guzik     __enum_uint8(vtype), int, int, struct acl_entry *);
2809ec7b004SRick Macklem 
2819ec7b004SRick Macklem /*
2829ec7b004SRick Macklem  * This function builds an NFS ace.
2839ec7b004SRick Macklem  */
2849ec7b004SRick Macklem static int
nfsrv_buildace(struct nfsrv_descript * nd,u_char * name,int namelen,__enum_uint8 (vtype)type,int group,int owner,struct acl_entry * ace)2859ec7b004SRick Macklem nfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen,
286*ba8cc6d7SMateusz Guzik     __enum_uint8(vtype) type, int group, int owner, struct acl_entry *ace)
2879ec7b004SRick Macklem {
2889ec7b004SRick Macklem 	u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype;
2899ec7b004SRick Macklem 	int full_len;
2909ec7b004SRick Macklem 
2919ec7b004SRick Macklem 	full_len = NFSM_RNDUP(namelen);
2929ec7b004SRick Macklem 	NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len);
2939ec7b004SRick Macklem 
2949ec7b004SRick Macklem 	/*
2959ec7b004SRick Macklem 	 * Fill in the ace type.
2969ec7b004SRick Macklem 	 */
297ff392a1dSEdward Tomasz Napierala 	if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW)
2989ec7b004SRick Macklem 		acetype = NFSV4ACE_ALLOWEDTYPE;
299ff392a1dSEdward Tomasz Napierala 	else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY)
3009ec7b004SRick Macklem 		acetype = NFSV4ACE_DENIEDTYPE;
301ff392a1dSEdward Tomasz Napierala 	else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT)
3029ec7b004SRick Macklem 		acetype = NFSV4ACE_AUDITTYPE;
3039ec7b004SRick Macklem 	else
3049ec7b004SRick Macklem 		acetype = NFSV4ACE_ALARMTYPE;
3059ec7b004SRick Macklem 	*tl++ = txdr_unsigned(acetype);
3069ec7b004SRick Macklem 
3079ec7b004SRick Macklem 	/*
3089ec7b004SRick Macklem 	 * Set the flag bits from the ACL.
3099ec7b004SRick Macklem 	 */
3109ec7b004SRick Macklem 	if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT)
3119ec7b004SRick Macklem 		aceflag |= NFSV4ACE_FILEINHERIT;
3129ec7b004SRick Macklem 	if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT)
3139ec7b004SRick Macklem 		aceflag |= NFSV4ACE_DIRECTORYINHERIT;
314ff392a1dSEdward Tomasz Napierala 	if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)
3159ec7b004SRick Macklem 		aceflag |= NFSV4ACE_NOPROPAGATEINHERIT;
316ff392a1dSEdward Tomasz Napierala 	if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY)
3179ec7b004SRick Macklem 		aceflag |= NFSV4ACE_INHERITONLY;
3189ec7b004SRick Macklem 	if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS)
3199ec7b004SRick Macklem 		aceflag |= NFSV4ACE_SUCCESSFULACCESS;
3209ec7b004SRick Macklem 	if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS)
3219ec7b004SRick Macklem 		aceflag |= NFSV4ACE_FAILEDACCESS;
3229ec7b004SRick Macklem 	if (group)
3239ec7b004SRick Macklem 		aceflag |= NFSV4ACE_IDENTIFIERGROUP;
3249ec7b004SRick Macklem 	*tl++ = txdr_unsigned(aceflag);
3259ec7b004SRick Macklem 	if (type == VDIR) {
3269ec7b004SRick Macklem 		if (ace->ae_perm & ACL_LIST_DIRECTORY)
3279ec7b004SRick Macklem 			acemask |= NFSV4ACE_LISTDIRECTORY;
3289ec7b004SRick Macklem 		if (ace->ae_perm & ACL_ADD_FILE)
3299ec7b004SRick Macklem 			acemask |= NFSV4ACE_ADDFILE;
3309ec7b004SRick Macklem 		if (ace->ae_perm & ACL_ADD_SUBDIRECTORY)
3319ec7b004SRick Macklem 			acemask |= NFSV4ACE_ADDSUBDIRECTORY;
3329ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_NAMED_ATTRS)
3339ec7b004SRick Macklem 			acemask |= NFSV4ACE_READNAMEDATTR;
3349ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS)
3359ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITENAMEDATTR;
336c3e22f83SRick Macklem 		if (ace->ae_perm & ACL_EXECUTE)
3379ec7b004SRick Macklem 			acemask |= NFSV4ACE_SEARCH;
3389ec7b004SRick Macklem 		if (ace->ae_perm & ACL_DELETE_CHILD)
3399ec7b004SRick Macklem 			acemask |= NFSV4ACE_DELETECHILD;
3409ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_ATTRIBUTES)
3419ec7b004SRick Macklem 			acemask |= NFSV4ACE_READATTRIBUTES;
3429ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_ATTRIBUTES)
3439ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEATTRIBUTES;
3449ec7b004SRick Macklem 		if (ace->ae_perm & ACL_DELETE)
3459ec7b004SRick Macklem 			acemask |= NFSV4ACE_DELETE;
3469ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_ACL)
3479ec7b004SRick Macklem 			acemask |= NFSV4ACE_READACL;
3489ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_ACL)
3499ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEACL;
3509ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_OWNER)
3519ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEOWNER;
3521d4c0424SEdward Tomasz Napierala 		if (ace->ae_perm & ACL_SYNCHRONIZE)
3531d4c0424SEdward Tomasz Napierala 			acemask |= NFSV4ACE_SYNCHRONIZE;
3549ec7b004SRick Macklem 	} else {
3559ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_DATA)
3569ec7b004SRick Macklem 			acemask |= NFSV4ACE_READDATA;
3579ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_DATA)
3589ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEDATA;
3599ec7b004SRick Macklem 		if (ace->ae_perm & ACL_APPEND_DATA)
3609ec7b004SRick Macklem 			acemask |= NFSV4ACE_APPENDDATA;
3619ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_NAMED_ATTRS)
3629ec7b004SRick Macklem 			acemask |= NFSV4ACE_READNAMEDATTR;
3639ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS)
3649ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITENAMEDATTR;
3659ec7b004SRick Macklem 		if (ace->ae_perm & ACL_EXECUTE)
3669ec7b004SRick Macklem 			acemask |= NFSV4ACE_EXECUTE;
3679ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_ATTRIBUTES)
3689ec7b004SRick Macklem 			acemask |= NFSV4ACE_READATTRIBUTES;
3699ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_ATTRIBUTES)
3709ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEATTRIBUTES;
3719ec7b004SRick Macklem 		if (ace->ae_perm & ACL_DELETE)
3729ec7b004SRick Macklem 			acemask |= NFSV4ACE_DELETE;
3739ec7b004SRick Macklem 		if (ace->ae_perm & ACL_READ_ACL)
3749ec7b004SRick Macklem 			acemask |= NFSV4ACE_READACL;
3759ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_ACL)
3769ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEACL;
3779ec7b004SRick Macklem 		if (ace->ae_perm & ACL_WRITE_OWNER)
3789ec7b004SRick Macklem 			acemask |= NFSV4ACE_WRITEOWNER;
3799ec7b004SRick Macklem 		if (ace->ae_perm & ACL_SYNCHRONIZE)
3809ec7b004SRick Macklem 			acemask |= NFSV4ACE_SYNCHRONIZE;
3819ec7b004SRick Macklem 	}
3829ec7b004SRick Macklem 	*tl++ = txdr_unsigned(acemask);
3839ec7b004SRick Macklem 	*tl++ = txdr_unsigned(namelen);
3849ec7b004SRick Macklem 	if (full_len - namelen)
3859ec7b004SRick Macklem 		*(tl + (namelen / NFSX_UNSIGNED)) = 0x0;
3869ec7b004SRick Macklem 	NFSBCOPY(name, (caddr_t)tl, namelen);
3879ec7b004SRick Macklem 	return (full_len + 4 * NFSX_UNSIGNED);
3889ec7b004SRick Macklem }
3899ec7b004SRick Macklem 
3909ec7b004SRick Macklem /*
3919ec7b004SRick Macklem  * Build an NFSv4 ACL.
3929ec7b004SRick Macklem  */
393b9cc3262SRyan Moeller int
nfsrv_buildacl(struct nfsrv_descript * nd,NFSACL_T * aclp,__enum_uint8 (vtype)type,NFSPROC_T * p)394*ba8cc6d7SMateusz Guzik nfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, __enum_uint8(vtype) type,
3955da9b3b0SRick Macklem     NFSPROC_T *p)
3969ec7b004SRick Macklem {
3979ec7b004SRick Macklem 	int i, entrycnt = 0, retlen;
3989ec7b004SRick Macklem 	u_int32_t *entrycntp;
3999ec7b004SRick Macklem 	int isowner, isgroup, namelen, malloced;
4009ec7b004SRick Macklem 	u_char *name, namestr[NFSV4_SMALLSTR];
4019ec7b004SRick Macklem 
4029ec7b004SRick Macklem 	NFSM_BUILD(entrycntp, u_int32_t *, NFSX_UNSIGNED);
4039ec7b004SRick Macklem 	retlen = NFSX_UNSIGNED;
4049ec7b004SRick Macklem 	/*
4059ec7b004SRick Macklem 	 * Loop through the acl entries, building each one.
4069ec7b004SRick Macklem 	 */
4079ec7b004SRick Macklem 	for (i = 0; i < aclp->acl_cnt; i++) {
4089ec7b004SRick Macklem 		isowner = isgroup = malloced = 0;
4099ec7b004SRick Macklem 		switch (aclp->acl_entry[i].ae_tag) {
4109ec7b004SRick Macklem 		case ACL_USER_OBJ:
4119ec7b004SRick Macklem 			isowner = 1;
4129ec7b004SRick Macklem 			name = "OWNER@";
4139ec7b004SRick Macklem 			namelen = 6;
4149ec7b004SRick Macklem 			break;
4159ec7b004SRick Macklem 		case ACL_GROUP_OBJ:
4169ec7b004SRick Macklem 			isgroup = 1;
4179ec7b004SRick Macklem 			name = "GROUP@";
4189ec7b004SRick Macklem 			namelen = 6;
4199ec7b004SRick Macklem 			break;
4209ec7b004SRick Macklem 		case ACL_EVERYONE:
4219ec7b004SRick Macklem 			name = "EVERYONE@";
4229ec7b004SRick Macklem 			namelen = 9;
4239ec7b004SRick Macklem 			break;
4249ec7b004SRick Macklem 		case ACL_USER:
4259ec7b004SRick Macklem 			name = namestr;
4269ec7b004SRick Macklem 			nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name,
4270f86b94aSEdward Tomasz Napierala 			    &namelen);
4289ec7b004SRick Macklem 			if (name != namestr)
4299ec7b004SRick Macklem 				malloced = 1;
4309ec7b004SRick Macklem 			break;
4319ec7b004SRick Macklem 		case ACL_GROUP:
4329ec7b004SRick Macklem 			isgroup = 1;
4339ec7b004SRick Macklem 			name = namestr;
4349ec7b004SRick Macklem 			nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name,
435c703cba8SEdward Tomasz Napierala 			    &namelen);
4369ec7b004SRick Macklem 			if (name != namestr)
4379ec7b004SRick Macklem 				malloced = 1;
4389ec7b004SRick Macklem 			break;
4399ec7b004SRick Macklem 		default:
4409ec7b004SRick Macklem 			continue;
44174b8d63dSPedro F. Giffuni 		}
4429ec7b004SRick Macklem 		retlen += nfsrv_buildace(nd, name, namelen, type, isgroup,
4435da9b3b0SRick Macklem 		    isowner, &aclp->acl_entry[i]);
4449ec7b004SRick Macklem 		entrycnt++;
4459ec7b004SRick Macklem 		if (malloced)
4469ec7b004SRick Macklem 			free(name, M_NFSSTRING);
4479ec7b004SRick Macklem 	}
4489ec7b004SRick Macklem 	*entrycntp = txdr_unsigned(entrycnt);
4499ec7b004SRick Macklem 	return (retlen);
4509ec7b004SRick Macklem }
4519ec7b004SRick Macklem 
4529ec7b004SRick Macklem /*
4539ec7b004SRick Macklem  * Compare two NFSv4 acls.
4549ec7b004SRick Macklem  * Return 0 if they are the same, 1 if not the same.
4559ec7b004SRick Macklem  */
456b9cc3262SRyan Moeller int
nfsrv_compareacl(NFSACL_T * aclp1,NFSACL_T * aclp2)4579ec7b004SRick Macklem nfsrv_compareacl(NFSACL_T *aclp1, NFSACL_T *aclp2)
4589ec7b004SRick Macklem {
4599ec7b004SRick Macklem 	int i;
4609ec7b004SRick Macklem 	struct acl_entry *acep1, *acep2;
4619ec7b004SRick Macklem 
4629ec7b004SRick Macklem 	if (aclp1->acl_cnt != aclp2->acl_cnt)
4639ec7b004SRick Macklem 		return (1);
4649ec7b004SRick Macklem 	acep1 = aclp1->acl_entry;
4659ec7b004SRick Macklem 	acep2 = aclp2->acl_entry;
4669ec7b004SRick Macklem 	for (i = 0; i < aclp1->acl_cnt; i++) {
4679ec7b004SRick Macklem 		if (acep1->ae_tag != acep2->ae_tag)
4689ec7b004SRick Macklem 			return (1);
4699ec7b004SRick Macklem 		switch (acep1->ae_tag) {
4709ec7b004SRick Macklem 		case ACL_GROUP:
4719ec7b004SRick Macklem 		case ACL_USER:
4729ec7b004SRick Macklem 			if (acep1->ae_id != acep2->ae_id)
4739ec7b004SRick Macklem 				return (1);
4749ec7b004SRick Macklem 			/* fall through */
4759ec7b004SRick Macklem 		case ACL_USER_OBJ:
4769ec7b004SRick Macklem 		case ACL_GROUP_OBJ:
4779ec7b004SRick Macklem 		case ACL_OTHER:
4789ec7b004SRick Macklem 			if (acep1->ae_perm != acep2->ae_perm)
4799ec7b004SRick Macklem 				return (1);
48074b8d63dSPedro F. Giffuni 		}
4819ec7b004SRick Macklem 		acep1++;
4829ec7b004SRick Macklem 		acep2++;
4839ec7b004SRick Macklem 	}
4849ec7b004SRick Macklem 	return (0);
4859ec7b004SRick Macklem }
486