draft-ietf-nfsv4-acl-mapping-04.txt   draft-ietf-nfsv4-acl-mapping-05.txt 
Network Working Group M. Eriksen Network Working Group M. Eriksen
Internet-Draft J. Fields Internet-Draft J. Fields
Expires: November 16, 2006 CITI Expires: February 23, 2007 CITI
May 15, 2006 August 22, 2006
Mapping Between NFSv4 and Posix Draft ACLs Mapping Between NFSv4 and Posix Draft ACLs
draft-ietf-nfsv4-acl-mapping-04 draft-ietf-nfsv4-acl-mapping-05
Status of this Memo Status of this Memo
By submitting this Internet-Draft, each author represents that any By submitting this Internet-Draft, each author represents that any
applicable patent or other IPR claims of which he or she is aware applicable patent or other IPR claims of which he or she is aware
have been or will be disclosed, and any of which he or she becomes have been or will be disclosed, and any of which he or she becomes
aware will be disclosed, in accordance with Section 6 of BCP 79. aware will be disclosed, in accordance with Section 6 of BCP 79.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that Task Force (IETF), its areas, and its working groups. Note that
skipping to change at page 1, line 34 skipping to change at page 1, line 34
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt. http://www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html. http://www.ietf.org/shadow.html.
This Internet-Draft will expire on November 16, 2006. This Internet-Draft will expire on February 23, 2007.
Copyright Notice Copyright Notice
Copyright (C) The Internet Society (2006). Copyright (C) The Internet Society (2006).
Abstract Abstract
A number of filesystems and applications support ACLs based on a A number of filesystems and applications support ACLs based on a
withdrawn POSIX draft [2]. Those ACLs differ significantly from NFS withdrawn POSIX draft [2]. Those ACLs differ significantly from NFS
version 4 (NFSv4) ACLs [1]. We describe how to translate between the version 4 ACLs [1]. We describe how to translate between the two
two types of ACLs. types of ACLs.
1. Introduction 1. Introduction
Access Control Lists (ACLs) are used to specify fine-grained access Access Control Lists (ACLs) are used to specify access rights to file
rights to file system objects. An ACL is a list of Access Control system objects. An ACL is a list of Access Control Entries (ACEs),
Entries (ACEs), each specifying an entity (such as a user) and some each specifying an entity (such as a user) and some level of access
level of access for that entity. for that entity.
In the following sections we describe two ACL models: NFSv4 ACLs, and In the following sections describe NFSv4 ACLs and ACLs based on a
ACLs based on a withdrawn POSIX draft. We will refer to the latter withdrawn POSIX draft. We will refer to the latter as "POSIX ACLs".
as "POSIX ACLs". Since NFSv4 ACLs are more fine-grained than POSIX Since NFSv4 ACLs are more fine-grained than POSIX ACLs, it is not
ACLs, it is not possible in general to map an arbitrary NFSv4 ACL to possible in general to map an arbitrary NFSv4 ACL to a POSIX ACL with
a POSIX ACL with the same semantics. However, it is possible to map the same semantics. However, it is possible to map any POSIX ACL to
any POSIX ACL to a NFSv4 ACL with nearly identical semantics, and it a NFSv4 ACL with nearly identical semantics, and it is possible to
is possible to map any NFSv4 ACL to a POSIX ACL in a way that map any NFSv4 ACL to a POSIX ACL in a way that preserves certain
preserves certain guarantees. We will explain how to do this, and guarantees. We will explain how to do this, and give guidelines for
give guidelines for clients and servers performing such translation. clients and servers performing such translation.
2. NFSv4 ACLs 2. NFSv4 ACLs
An NFSv4 ACL is an ordered sequence of ACEs, each having an entity, a An NFSv4 ACL is an ordered sequence of ACEs, each having an entity, a
type, some flags, and an access mask. type, some flags, and an access mask.
The entity may be the name of a user or group, or may be one of a The entity may be the name of a user or group, or may be one of a
small set of special entities. Among the special entities are small set of special entities. Among the special entities are
"OWNER@" (the current owner of the file), "GROUP@" (the group "OWNER@" (the current owner of the file), "GROUP@" (the group
associated with the file), and "EVERYONE@". associated with the file), and "EVERYONE@".
The type may be ALLOW or DENY. (AUDIT or ALARM are also allowed, but An ACL may have a "type" of ALLOW or DENY. (AUDIT or ALARM are also
they are not relevant to our discussion). allowed, but they are not relevant to our discussion).
The access mask has 14 separate bits, including bits to control read, The access mask has 14 separate bits, including bits to control read,
write, execute, append, ACL modification, file owner modification, write, execute, append, ACL modification, file owner modification,
etc.; consult [1] for the full list. etc.; consult [1] for the full list.
Of the flags, four are relevant here. The ACE4_IDENTIFIER_GROUP flag Of the flags, four are relevant here. The ACE4_IDENTIFIER_GROUP flag
is used to indicate that the entity name is the name of a group. The is used to indicate that the entity name is the name of a group. The
other three concern inheritance: ACE4_DIRECTORY_INHERIT_ACE indicates other three concern inheritance: ACE4_DIRECTORY_INHERIT_ACE indicates
that the ACE should be added to new subdirectories of the directory; that the ACE should be added to new subdirectories of the directory;
ACE4_FILE_INHERIT_ACE does the same for new files; and ACE4_FILE_INHERIT_ACE does the same for new files; and
ACE4_INHERIT_ONLY indicates that the ACE should be ignored when ACE4_INHERIT_ONLY indicates that the ACE should be ignored when
determining access to the directory itself. determining access to the directory itself.
The NFSv4 ACL permission-checking algorithm is straightforward. The NFSv4 ACL permission-checking algorithm is straightforward.
Assume a a requester asks for access, as specified by a single bit in First, assume a requester asks for access specified by a single bit
the access bitmask. We allow the access if the first ACE in the ACL in the access bitmask. We allow the access if the first ACE in the
that matches the requester and that has that bit set is an ALLOW ACE, ACL that matches the requester and that has that bit set is an ALLOW
and we deny the access if the first such ACE is a DENY ACE. If no ACE, and we deny the access if the first such ACE is a DENY ACE. If
matching ACE has the bit in question set, behaviour is undefined. If no matching ACE has the bit in question set, access is normally
an access mask consisting of more than one bit is requested, it denied.
succeeds if and only if each bit in the mask is allowed.
If a requester asks for access requiring multiple bits from the
access bitmask simutaneously, then we allow the access if and only if
each bit in the requested bitmask would be allowed individually.
We refer the reader to [1] for further details. We refer the reader to [1] for further details.
3. POSIX ACLs 3. POSIX ACLs
A number of operating systems implement ACLs based on the withdrawn A number of operating systems implement ACLs based on the withdrawn
POSIX 1003.1e/1003.2c Draft Standard 17 [2]. We will refer to such POSIX 1003.1e/1003.2c Draft Standard 17 [2]. We will refer to such
ACLs as "POSIX ACLs". ACLs as "POSIX ACLs", though they are not part of any published POSIX
standard.
POSIX ACLs use access masks with only the traditional "read", POSIX ACLs use access masks with only the traditional "read",
"write", and "execute" bits. Each ACE in a POSIX ACL is one of five "write", and "execute" bits. Each ACE in a POSIX ACL is one of five
types: ACL_USER_OBJ, ACL_USER, ACL_GROUP_OBJ, ACL_GROUP, ACL_MASK, types: ACL_USER_OBJ, ACL_USER, ACL_GROUP_OBJ, ACL_GROUP, ACL_MASK,
and ACL_OTHER. Each ACL_USER ACE has a uid associated with it, and and ACL_OTHER. Each ACL_USER ACE has a uid associated with it, and
each ACL_GROUP ACE has a gid associated with it. Every POSIX ACL each ACL_GROUP ACE has a gid associated with it. Every POSIX ACL
must have exactly one ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER ACE, must have exactly one ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER ACE,
and at most one ACL_MASK ACE. The ACL_MASK ACE is required if the and at most one ACL_MASK ACE. The ACL_MASK ACE is required if the
ACL has any ACL_USER or ACL_GROUP ACEs. There may not be two ACL has any ACL_USER or ACL_GROUP ACEs. There may not be two
ACL_USER ACEs with the same uid, and there may not be two ACL_GROUP ACL_USER ACEs with the same uid, and there may not be two ACL_GROUP
ACEs with the same gid. ACEs with the same gid.
Given a POSIX ACL and a requester asking for access, permission is Given a POSIX ACL and a requester asking for access, permission is
determined as follows: determined by consulting the ACEs in the order ACL_USER_OBJ,
ACL_USER, ACL_GROUP_OBJ, ACL_GROUP, ACL_OTHER, and allowing or
denying access based on the first ACE encountered that the requester
matches, except that we never allow the ACL_USER, ACL_OWNER_OBJ, or
ACL_GROUP objects to grant more than the ACL_MASK object does, and in
the case of ACL_GROUP_OBJ and ACL_GROUP ACEs, we allow access if any
one of those ACEs allows access.
In more detail:
1. If the requester is the file owner, then allow or deny access 1. If the requester is the file owner, then allow or deny access
depending on whether the ACL_USER_OBJ ACE allows or denies it. depending on whether the ACL_USER_OBJ ACE allows or denies it.
Otherwise, Otherwise,
2. if the requester's uid matches the uid of one of the ACL_USER 2. if the requester matches the file's group, and the ACL mask ACE
would deny the requested access, then skip to step 5. Otherwise,
3. if the requester's uid matches the uid of one of the ACL_USER
ACEs, then allow or deny access depending on whether the ACEs, then allow or deny access depending on whether the
ACL_USER_OBJ ACE allows or denies it. Otherwise, ACL_USER_OBJ ACE allows or denies it. Otherwise,
3. Consider the set of all ACL_GROUP ACEs whose gid the requester is 4. Consider the set of all ACL_GROUP ACEs whose gid the requester is
a member of. Add to that set the ACL_GROUP_OBJ ACE, if the a member of. Add to that set the ACL_GROUP_OBJ ACE, if the
requester is also a member of the file's group. Allow access if requester is also a member of the file's group. Allow access if
any ACE in the resulting set allows access. If the set of any ACE in the resulting set allows access. If the set of
matching ACEs is nonempty, and none allow access, then deny matching ACEs is nonempty, and none allow access, then deny
access. Otherwise, if the set of matching ACEs is empty, access. Otherwise, if the set of matching ACEs is empty,
5. if the requester's access mask is allowed by the ACL_OTHER ACE,
4. if the requester's access mask is allowed by the ACL_OTHER ACE,
then grant access. Otherwise, deny access. then grant access. Otherwise, deny access.
The above description omits one detail: in steps (2) and (3), the
requested bits must be granted both by the matching ACE and by the
ACL_MASK ACE. The ACL_MASK ACE thus limits the maximum permissions
which may be granted by any ACL_USER or ACL_GROUP ACE, or by the
ACL_GROUP_OBJ ACE.
Each file may have a single POSIX ACL associated with it, used to Each file may have a single POSIX ACL associated with it, used to
determine access to that file. Directories, however, may have two determine access to that file. Directories, however, may have two
ACLs: one, the "access ACL", used to determine access to the ACLs: one, the "access ACL", used to determine access to the
directory, and one, the "default ACL", used only as the ACL to be directory, and one, the "default ACL", used only as the ACL to be
inherited by newly created objects in the directory. inherited by newly created objects in the directory.
4. Ordering of NFSv4 and POSIX ACLs 4. Ordering of NFSv4 and POSIX ACLs
POSIX ACLs are unordered--the order in which the POSIX access- POSIX ACLs are unordered--the order in which the POSIX access-
checking algorithm considers the entries is determined entirely by checking algorithm considers the entries is determined entirely by
skipping to change at page 8, line 10 skipping to change at page 8, line 10
The NFSv4 ACL permission-checking algorithm has the property that it The NFSv4 ACL permission-checking algorithm has the property that it
permits a group of bits whenever it would permit each bit permits a group of bits whenever it would permit each bit
individually, so it is impossible to mimic this behaviour with an individually, so it is impossible to mimic this behaviour with an
NFSv4 ACL. NFSv4 ACL.
6. Mapping POSIX ACLs to NFSv4 ACLs 6. Mapping POSIX ACLs to NFSv4 ACLs
6.1. Requirements 6.1. Requirements
In the next section we give an example of a mapping of POSIX ACLs In the next section we give an example of a mapping of POSIX ACLs
into NFSv4 ACLs. We permit a server or client to use a different into NFSv4 ACLs. A server or client may use a different mapping, but
mapping, provided the mapping meets the following requirements: the mapping should meet the following requirements:
It must map the POSIX ACL to an NFSv4 ACL with identical access It must map the POSIX ACL to an NFSv4 ACL with identical access
semantics, ignoring the minor exception described in the previous semantics, ignoring the minor exception described in the previous
section. section.
It must map the read mode bit to ACE4_READ_DATA, the write bit to It must map the read mode bit to ACE4_READ_DATA, the write bit to
ACE4_WRITE_DATA and ACE4_APPEND_DATA (and ACE4_DELETE_CHILD for ACE4_WRITE_DATA and ACE4_APPEND_DATA (and ACE4_DELETE_CHILD for
directories), and the EXECUTE bit to ACE4_EXECUTE. It should also directories), and the EXECUTE bit to ACE4_EXECUTE. It should also
allow ACE4_READ_ACL, ACE4_READ_ATTRIBUTES, and ACE4_SYNCHRONIZE allow ACE4_READ_ACL, ACE4_READ_ATTRIBUTES, and ACE4_SYNCHRONIZE
unconditionally, and allow ACE4_WRITE_ACL and ACE4_WRITE_ATTRIBUTES unconditionally, and allow ACE4_WRITE_ACL and ACE4_WRITE_ATTRIBUTES
to the owner. The handling of other NFSv4 mode bits may depend on to the owner. The handling of other NFSv4 mode bits may depend on
the implementation, but it is preferable to leave them unused. the implementation, but it is preferable to leave them unused.
It should avoid using DENY ACEs. If DENY ACEs are required, it It should avoid using DENY ACEs. If DENY ACEs are required, it
should attempt to place them at the beginning. (This is not always should attempt to place them at the beginning. (This is not always
possible.) possible.)
For simplicity's sake, the translator may choose to handle the mask The resulting NFSv4 ACL must take into account the mask ACE, by
by first applying it to the USER, GROUP, and GROUP_OBJ ACEs, and then ensuring that it does not give the group file owner or any users or
mapping the resulting ACL. However, that will result in an ACL from groups named in the ACL more permissions than permitted by the mask.
which it is impossible to determine the original value of the mask or It would also be possible to specify a mapping that encoded the mask
of the masked USER, GROUP, and GROUP_OBJ bitmasks. If the resulting in such a way that the original value of the mask could be recovered
ACL is later translated back to a POSIX ACL, the translator will by someone that knew the ACL was produced by our algorithm. However,
assume that the value of the mask is the union of the bitmasks the added complexity and fragility of such a mapping is not worth the
permitted to any USER, GROUP, or GROUP_OBJ. If that would be small benefit of preserving the mask information, so we do not
incorrect, the original translation should not modify the bitmasks of attempt that here.
the USER, GROUP, and GROUP_OBJ bitmasks, and should instead use
additional DENY ACEs as necessary to give the effect of the mask. It
should also arrange for the first GROUP@ ACE to be a DENY ACE whose
bitmask is determined by the mask, allowing that ACE to be used to
determine the original mask value.
6.2. Example POSIX->NFSv4 Mapping 6.2. Example POSIX->NFSv4 Mapping
We now describe an algorithm which maps any POSIX ACL to an NFSv4 ACL We now describe an algorithm which maps any POSIX ACL to an NFSv4 ACL
with the same semantics, meeting the above requirements. with the same semantics, meeting the above requirements.
First, translate the uid's and gid's on the ACL_USER and ACL_GROUP First, modify all ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ ACEs by
ACEs into NFSv4 names, using directory services, etc., as removing any permissions not granted by the mask ACE. The mask ACE
appropriate, and translate ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER may then be ignored for the rest of this process.
to the special NFSv4 names "OWNER@", "GROUP@", and "EVERYONE@",
respectively. Translate the uid's and gid's on the ACL_USER and ACL_GROUP ACEs into
NFSv4 names, using directory services, etc., as appropriate, and
translate ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER to the special
NFSv4 names "OWNER@", "GROUP@", and "EVERYONE@", respectively.
Next, map each POSIX ACE (excepting any mask ACE) in the given POSIX Next, map each POSIX ACE (excepting any mask ACE) in the given POSIX
ACL to an NFSv4 ALLOW ACE with an entity determined as above, and ACL to an NFSv4 ALLOW ACE with an entity determined as above, and
with a bitmask determined from the permission bits on the POSIX ACE with a bitmask determined from the permission bits on the POSIX ACE
as follows: as follows:
1. If the read bit is set in the POSIX ACE, then set ACE4_READ_DATA. 1. If the read bit is set in the POSIX ACE, then set ACE4_READ_DATA.
2. If the write bit is set in the POSIX ACE, then set 2. If the write bit is set in the POSIX ACE, then set
ACE4_WRITE_DATA and ACE4_APPEND_DATA. If the object carrying the ACE4_WRITE_DATA and ACE4_APPEND_DATA. If the object carrying the
skipping to change at page 9, line 28 skipping to change at page 9, line 27
ACE4_EXECUTE. ACE4_EXECUTE.
4. Set ACE4_READ_ACL, ACE4_READ_ATTRIBUTES, and ACE4_SYNCHRONIZE 4. Set ACE4_READ_ACL, ACE4_READ_ATTRIBUTES, and ACE4_SYNCHRONIZE
unconditionally. unconditionally.
5. If the ACE is for the special "OWNER@" entity, set ACE4_WRITE_ACL 5. If the ACE is for the special "OWNER@" entity, set ACE4_WRITE_ACL
and ACE4_WRITE_ATTRIBUTES. and ACE4_WRITE_ATTRIBUTES.
6. Clear all other bits in the NFSv4 bitmask. 6. Clear all other bits in the NFSv4 bitmask.
In addition, we set the GROUP flag in each ACE which corresponds to a In addition, set the GROUP flag in each ACE which corresponds to a
named group (but not in the GROUP@ ACE, or any of the other special named group (but not in the GROUP@ ACE, or any of the other special
entity ACEs). entity ACEs).
At this point, we've replaced the POSIX ACL by an NFSv4 ACL with the At this point, we've replaced the POSIX ACL by an NFSv4 ACL with the
same number of ACEs (ignoring any mask ACE), all of them ALLOW ACEs. same number of ACEs (ignoring any mask ACE), all of them ALLOW ACEs.
Order this NFSv4 ACL in the canonical order: OWNER@, users, GROUP@, Order this NFSv4 ACL in the canonical order: OWNER@, users, GROUP@,
groups, then EVERYONE@. groups, then EVERYONE@.
If the bitmasks in the resulting ACEs are non-increasing (so no ACE If the bitmasks in the resulting ACEs are non-increasing (so no ACE
allows a bit not allowed by a previous ACE), then we can skip the allows a bit not allowed by a previous ACE), then we can skip the
next step. next step.
Otherwise, we need to insert additional DENY ACE's to emulate the Otherwise, we need to insert additional DENY ACE's to emulate the
first-match semantics of the POSIX ACL permission-checking algorithm: first-match semantics of the POSIX ACL permission-checking algorithm:
1. If an ACL_USER_OBJ, ACL_OTHER, or ACL_USER ACE fails to grant 1. If an ACL_USER_OBJ, ACL_OTHER, or ACL_USER ACE fails to grant
some permissions that are granted later in the ACL, then that ACE some permissions that are granted later in the ACL, then that ACE
must be prepended by a single DENY ACE. The DENY ACE should have must be preceded by a single DENY ACE. The DENY ACE should have
the same entity and flags as the corresponding ALLOW ACE, but the the same entity and flags as the corresponding ALLOW ACE, but the
bitmask on the DENY ACE should be the bitwise NOT of the bitmask bitmask on the DENY ACE should be the bitwise NOT of the bitmask
on the ALLOW ACE, except that the ACE4_WRITE_OWNER, ACE4_DELETE, on the ALLOW ACE, except that the ACE4_WRITE_OWNER, ACE4_DELETE,
ACE4_READ_NAMED_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRIBUTES bits ACE4_READ_NAMED_ATTRIBUTES, and ACE4_WRITE_NAMED_ATTRIBUTES bits
should be cleared, and the ACE4_DELETE_CHILD bit should be should be cleared, and the ACE4_DELETE_CHILD bit should be
cleared on non-directories. (Also, in the xdr-encoded ACL that cleared on non-directories. (Also, in the xdr-encoded ACL that
is transmitted, all bits not defined in the protocol should be is transmitted, all bits not defined in the protocol should be
cleared.) cleared.)
2. All of the ACL_GROUP_OBJ and ACL_GROUP ACEs are consulted by the 2. All of the ACL_GROUP_OBJ and ACL_GROUP ACEs are consulted by the
POSIX algorithm before determining permissions. To emulate this POSIX algorithm before determining permissions. To emulate this
behaviour, instead of adding a single DENY before corresponding behaviour, instead of adding a single DENY before corresponding
GROUP@ or named group ACEs, we insert a list of DENY ACEs after GROUP@ or named group ACEs, we insert a list of DENY ACEs after
the list of GROUP@ and named group ACEs. Each DENY ACE is the list of GROUP@ and named group ACEs. Each DENY ACE is
determined from its corresponding ALLOW ACE exactly as in the determined from its corresponding ALLOW ACE exactly as in the
previous step. As before, these DENY aces should only be added previous step. As before, these DENY ACEs should only be added
when they are necessitated by an ACE that is less permissive than when they are necessitated by an ACE that is less permissive than
the final EVERYONE@ ace. the final EVERYONE@ ACE.
Finally, we enforce the POSIX mask ACE by prepending each ALLOW ACE
for a named user, GROUP@, or named group, with a single DENY ACE
whose entity and flags are the same as those for the corresponding
ALLOW ACE, but whose bitmask is the inverse of the bitmask determined
from the mask ACE, with the inverse calculated as described above.
In the case of named users, these DENY aces may be coalesced with any
existing prepended DENY aces. The DENY aces are omitted entirely if
they would have no affect, or if the mask ACE has the same bitmask as
the maximum of the affected ACEs. (With the one exception that if
the POSIX ACL posesses exactly 4 ACEs, then a mask-derived DENY ace
should be inserted before the GROUP@ ace, even if it would not
otherwise be.)
Regardless of what scheme is used to represent the mask, the receiver
will use the first GROUP@ DENY ace to determine the value of the mask
(if it is different from the union of the bitmasks on the affected
ACEs), and use the relevant ALLOWs to determine the pre-mask values
of user and group ACEs.
The implementation may also choose to just mask out the bitmasks on
the relevant ALLOW ACEs. This will produce a simpler ACL (in
particular, an ACL that usually requires no DENY ACE's), at the
expense of losing some ACL information after a chmod.
On directories with default ACLs, we translate the default ACL as On directories with default ACLs, we translate the default ACL as
above, but set the ACE4_INHERIT_ONLY_ACE, ACE4_DIRECTORY_INHERIT_ACE, above, but set the ACE4_INHERIT_ONLY_ACE, ACE4_DIRECTORY_INHERIT_ACE,
and ACE4_FILE_INHERIT_ACE flags on every ACE in the resulting ACL. and ACE4_FILE_INHERIT_ACE flags on every ACE in the resulting ACL.
On directories with both default and access ACLs, we translate the On directories with both default and access ACLs, we translate the
two ACLs and then concatenate them. The order of the concatenation two ACLs and then concatenate them. The order of the concatenation
is unimportant. is unimportant.
7. Mapping NFSv4 ACLs to POSIX ACLs 7. Mapping NFSv4 ACLs to POSIX ACLs
7.1. Requirements 7.1. Requirements
Any mapping of NFSv4 ACLs to POSIX ACLs must map any NFSv4 ACL that Any mapping of NFSv4 ACLs to POSIX ACLs must map any NFSv4 ACL that
is semantically equivalent to a POSIX ACL (with the exception of the is semantically equivalent to a POSIX ACL (with the exception of the
"minor inaccuracy" mentioned above) to the equivalent POSIX ACL. It "minor inaccuracy" mentioned above) to an equivalent POSIX ACL.
should also extract the mask correctly; as the mask doesn't affect
the semantics of the NFSv4 ACL, and as there is more than one way the
mask might be encoded, we require a convention for this.
Specifically: we require that the mask be computed as the bitmask
used on the first GROUP@ DENY ACE which precedes any GROUP@ allow
ACE, unless no such DENY ACE exists, in which case the mask must be
computed as the union of the bitmasks allowed to all named users,
groups, and GROUP@ (where by the "bitmask allowed to" an entity we
mean the maximum bitmask that the ACL would permit to any user
matching the entity).
Implementations may vary in how they deal with NFSv4 ACLs that are However, a more difficult problem is presented by NFSv4 ACLs that are
not precisely semantically equivalent to any POSIX ACL. In not precisely equivalant to any POSIX ACL.
particular they may return errors for such ACLs instead of attempting
to map them. However, when possible without compromising security, The only way that the NFSv4 protocol gives servers to indicate that
they should attempt to be forgiving. they support only a subset of the ACL model is the "aclsupport"
attribute, which allows a server to advertise that it only supports
certain ACE types. This allows a server to report that it only
supports ALLOW ACEs, or that it does not support AUDIT or ALARM ACEs
(which will be the case for most servers with only POSIX ACLs). But
it does not give a way to claim support for more complex subsets of
the ACL model.
While it is possible for a server to reject any ACLs that do not fit
its ACL model, this places a large burden on clients and users, since
the server has no way to explain why it rejected a particular ACL.
Therefore, it is preferable to be more forgiving, whenever that is
possible without compromising security, and to limit any restrictions
to those that are easily documented and verified by users.
The language of [1] allows a server some flexibility in handling ACLs The language of [1] allows a server some flexibility in handling ACLs
that it cannot enforce completely accurately, as long as it adheres that it cannot enforce completely accurately, as long as it adheres
to "the guiding principle... that the server must not accept ACLs to "the guiding principle... that the server must not accept ACLs
that appear to make [a file] more secure than it really is." that appear to make [a file] more secure than it really is."
Note that an NFSv4 ACL consisting entirely of ALLOW ACLs can always ACLs with arbitrary sequences of ALLOWs and DENYs may be particularly
be transformed into a POSIX-equivalent ACL by first sorting it into troublesome; but note that an NFSv4 ACL consisting entirely of ALLOW
the canonical order, and then inserting DENY ACEs as necessary to ACLs can always be transformed into a POSIX-equivalent ACL by first
ensure POSIX first-match semantics. Since inserting DENY ACEs can sorting it into the canonical order, then inserting DENY ACEs as
only restrict access, it is safe for a server to do this. necessary to ensure POSIX first-match semantics. Since inserting
DENY ACEs can only restrict access, it is safe for a server to do
this.
We require any server to accept, at least, any NFSv4 ACL that Therefore servers should accept, at least, any NFSv4 ACL that
consists entirely of ALLOW ACLs. consists entirely of ALLOW ACLs.
Clients should also be at least as forgiving, to promote Clients should also be at least as forgiving, to promote
interoperability when heterogeneous clients share files. interoperability when heterogeneous clients share files.
7.2. Example NFSv4->POSIX Mapping 7.2. Example NFSv4->POSIX Mapping
We now give an example of an algorithm that meets the above We now give an example of an algorithm that meets the above
requirements. We assume it is to be used by a server mapping client- requirements. We assume it is to be used by a server mapping client-
provided NFSv4 ACLs to POSIX ACLs it can store in its filesystem, so provided NFSv4 ACLs to POSIX ACLs it can store in its filesystem, so
the translation errs on the side of making the ACL less permissive. the translation errs on the side of making the ACL more restrictive.
Given an NFSv4 ACL, first calculate the mask by taking the bitmask In fact, if we ignore some loss of information in the mask ACE, this
from the first GROUP@ DENY ACE from the original NFSv4 ACL, if it mapping takes an NFSv4 ACL to the unique most permissive POSIX ACL
exists. After doing so, remove that DENY ACE, and clear the bits in that is no more permissive than the given NFSv4 ACL.
its bitmask from any DENY ACE for a named user, group, or GROUP@
which precedes an ALLOW ACE for the same entity.
In the case where there is no such GROUP@ DENY ACE, continue through Before starting, if the ACL in question is for a directory, we split
the rest of the algorithm and then calculate the mask as the union of it into two ACLs, one purely effective and one purely inherited, as
the calculated permissions of all named users, group, and the follows:
GROUP_OBJ ACE.
Given an NFSv4 ACL, sort it into canonical order (OWNER@ ACEs first, 1. ACEs with no inheritance flags are put in the purely effective
then user ACEs, then GROUP@ ACEs, then group ACEs, then EVERYONE@ ACL.
ACEs.) Also, sort the GROUP@ and group ACEs that all ALLOW ACEs
precede all DENY ACEs. To do so, take advantage of the following
observations:
1. If two consecutive ACEs are either both ALLOW ACEs, or both DENY 2. Aces with FILE_INHERIT and DIRECTORY_INHERIT both set are put in
ACEs, then we can swap their order without changing the effect of both the effective and the inherited ACL
the ACL.
2. If it would be impossible for a single user to match both of the 3. Aces with FILE_INHERIT, DIRECTORY_INHERIT, and INHERIT_ONLY all
entities on two consecutive ACEs, then we can swap their order set are put only in the inherited ACL.
without changing the effect of the ACL.
3. If an ALLOW ACE is immediately followed by a DENY ACE, then Other combinations of ineritance flags may be rejected or silently
swapping the order of the two ACEs will not make the ACL any more modified to one of the above.
permissive.
4. If a DENY ACE is immediately followed by an ALLOW ACE, then The main algorithm that follows is then performed on each ACL, with
swapping the order of the two ACEs will not make the ACL any more one used to set the effictive ACL, and one the default ACL.
permissive, *if* we modify the bitmask on the ALLOW ACE by
clearing any bits that are set in the DENY ACE.
The second observation is the trickiest: it may usually be safe to First, we calculate the OTHER mode as follows:
assume that two distinct user names cannot match the same user. An
implementation with knowledge about group memberships or about the
current value of the file owner might also use that information, but
if it does so it will produce a translation that is no longer
accurate after owners or group memberships change.
Fortunately, observations 1, 3, and 4 are sufficient to sort any ACL 1. Initialize the bitmasks other_allow and other_deny both to zero.
into canonical order, so a paranoid implementation can simply ignore
number 2 completely, while an implementation willing to sacrifice
some accuracy may choose to do something more complex.
Ensure that the resulting ACL posesses at least one each of OWNER@, 2. For each ACE in the ACL, starting from the top:
GROUP@, and EVERYONE@ ACEs, by inserting an ALLOW ACE with a zero
bitmask if necessary in the correct position.
Next, for each entity, calculate a bitmask for that entity as 1. If the ACE is not an EVERYONE@ ACE, ignore it and move to the
follows: Starting with the first ACE for that entity (ignoring all next ACE.
previous ACEs), perform the NFSv4 ACL-checking algorithm for a user
that is assumed to match the entity on every DENY ACE that a user
matching the given entity might match, but is assumed to match only
those entities on ALLOW ACEs that *any* user matching the current
entity must match.
Finally, construct the POSIX ACL by translating NFSv4 entity names to 2. If the ACE is an EVERYONE@ ALLOW ACE, then add to other_allow
uid's and gid's (and handling special entities in the obvious way), any bits set in this ACE but not set in other_deny.
then assign a POSIX bitmask determined by the NFSv4 bitmask
calculated in the previous step; the bitmask calculation should use 3. If the ACE is an EVERYONE@ DENY ACE, then add to other_deny
the inverse of the mapping described previously in the POSIX-to-NFSv4 any bits set in this ACE but not set in other_allow.
mapping, erring on the side of denying bits if it cannot determine a
sensible mapping. However, if certain bits simply cannot be mapped 3. Discard other_deny. Set the USER_OBJ mask from other_allow using
in a reasonable way to mode bits, the server may simply ignore them the inverse of the mapping described previously in the POSIX-to-
rather than returning an error. (For example, the server should deny NFSv4 mapping, erring on the side of denying bits if it cannot
write if either ACE4_WRITE_DATA or ACE4_APPEND_DATA are denied. But determine a sensible mapping. However, if certain bits simply
it may choose to ignore ACE4_READ_ATTRIBUTES entirely.) cannot be mapped in a reasonable way to mode bits, the server may
simply ignore them rather than returning an error. (For example,
the server should deny write if either ACE4_WRITE_DATA or
ACE4_APPEND_DATA are denied. But it may choose to ignore
ACE4_READ_ATTRIBUTES entirely; though in that case it may at
least want to treat specially the case where such bits are
explicitly denied by some DENY ACE.)
Note that the bits determined above are exactly the maximum bits that
will always be permitted to a user that doesn't match the file owner
or group, or any of the named owners or groups. Thus this choice of
the OTHER mode is exactly the maximum choice we can safely make.
Next we calculate the GROUP_OBJ and GROUP masks.
1. Initialize to zero an allow and deny bitmask for each GROUP_OBJ
and for each GROUP mask.
2. For each ACE in the ACL, starting from the top:
1. If the ACE is an OWNER@ or named user ACE, ignore it and move
to the next ACE.
2. If the ACE is an EVERYONE@ ALLOW ACE, then, for each GROUP or
GROUP_OBJ allow mask, set the bits allowed in the EVERYONE
ACE but not already in this GROUP or GROUP_OBJ's deny mask.
3. If the ACE is an EVERYONE@ DENY ACE, then, for each GROUP or
GROUP_OBJ deny mask, set the bits denied in the EVERYONE ACE
but not already allowed in this GROUP or GROUP_OBJ's deny
mask.
4. If the ACE is a GROUP or GROUP@ ALLOW ACE, then set the allow
bits in the corresponding GROUP or GROUP_OBJ allow mask that
are allowed by this ACE but not already denied by the
corresponding GROUP or GROUP_OBJ deny mask.
5. If the ACE is a GROUP or GROUP@ DENY ACE, then set the deny
bits in the corresponding GROUP or GROUP_OBJ deny mask that
are denied by this ACE but not already allowed by the
corresponding GROUP or GROUP_OBJ allow mask. Call the
resulting deny mask "m". In each GROUP or GROUP_OBJ deny
mask, set every bit that is in m and not already in that
GROUP or GROUP_OBJ allow mask.
3. Having calculated allow and deny masks for GROUP_OBJ and each
GROUP, we now set the corresponding modes from the allow masks as
we did in the last step of the USER_OBJ mask calculation above.
Note that the bits thus determined for a group are exactly the
maximum bits that will always be permitted to a user that matches the
group in question, and that is denied any bits that could be denied
by matching other groups, without out being allowed bits by matching
any such groups. This is the most permissive mode we can choose that
will never permit more permissions than the original NFSv4 ACL, for
any possible choice of group memberships.
An implementation with special knowledge about the current gowning
group or about group memberships may choose to use that knowledge to
calculate a more permissive mode. However, doing so may render
resulting POSIX ACL inaccurate after the owning group changes, or
after any group memberships change.
Next, we calculate USER modes by first calculating allow and deny
masks for each USER as above, this time assuming we are a user that
does not match the file owner, that matches no user except for the
one user under consideration, and that matches groups only when they
would deny some permissions that they have not allowed yet. (To
ensure this last step it will also be necessary to maintain group
allow and deny ACEs, as we did in the previous calculation.) We omit
the detailed steps, which are similar. Again, the implementation may
choose to use special knowledge about group memberships at the risk
of increased complexity and of loss of some accuracy.
Next, we calculate the USER_OBJ mode by calculating allow and deny
masks for a user that matches the file owner and any user or group
that denies bits that it does not first allow.
Finally, if the resulting ACL has any named user or group ACEs, add a
mask ACE with bitmask equal to the union of the calculated
permissions of all named users, group, and the GROUP_OBJ ACE.
The resulting mapping errs on the side of creating a more restrictive The resulting mapping errs on the side of creating a more restrictive
ACE. However it can be modified to produce a mapping that errs on ACE. However it can be modified to produce a mapping that errs on
the side of permissiveness, for the purposes of translating a server- the side of permissiveness, for the purposes of translating a server-
provided NFSv4 ACL to a POSIX ACL to present to a user or provided NFSv4 ACL to a POSIX ACL to present to a user or
application, as follows: application, as follows:
1. When sorting ACEs, ALLOW ACEs can always be moved towards the 1. When performing the final mapping from the allow bitmask to a
start of the ACL, but a DENY ACE can be moved towards the start mode, we instead using a mapping that errs on the side of
of the ACL only as long as we clear any of the DENY ACE's bitmask permissiveness; for example, we allow write permissions even if
bits that are set in the intervening ALLOW ACEs. only one of WRITE_DATA, APPEND_DATA, or (in the case of
directories) DELETE_CHILD is allowed.
2. When calculating the NFSv4 bitmask for each entity, err on the 2. Wherever in the above we pessimistically assume that a user will
side of assuming that ALLOW ACEs apply and that DENY ACEs don't, match any entity that has permissions denied to it before they
with the one exception that when calculating the GROUP@ and named are first allowed, we instead assume that the user will match any
group bitmasks, ALLOW ACEs for groups other than the one under entity that has permissions allowed to it before they are first
consideration should be ignored. denied.
3. When mapping the NFSv4 bitmask to POSIX mode bits, err on the Once again, the resulting mapping may be seen to produce the unique
side of allowing access. (up to choice of mask) POSIX ACL which is the most restrictive among
all POSIX ACLs no more restrictive than the given NFSv4 ACL.
8. Security Considerations Note that the above algorithms may be optimized in a number of ways:
for example, although they are described in terms of multiple passes,
it will be simpler and more efficient to calculate the entire POSIX
ACL in a single pass.
8. Backwards Compatibility
Previous versions of this document recommended a different
POSIX->NFSv4 mapping, which enforces POSIX semantics by inserting
DENYs into the ACL even when those DENY's would have no effect, and
which represents the POSIX mask ACE using additional DENYs. The
resulting ACLs are overly complex and create problems for Windows
clients, because the default Windows ACL editor prefers to order
DENYs before ALLOWs.
The NFSv4 to POSIX mapping we describe in this document can accept
the NFSv4 ACLs produced by the old mapping.
However, previous versions of this document also recommended
accepting only NFSv4 ACLs that were precisely those produced by the
old POSIX->NFSv4 mapping; therefore, existing implementations of that
recommendation will reject the NFSv4 ACLs produced by the newer
mapping.
We strongly recommend fixing implementations to accept a wider range
of NFSv4 ACLs. However, we briefly document the old mapping here in
case that is impossible:
Names, bitmasks, and flags are determined as in the the current
mapping.
Whenever the following instructions requiring taking "the complement"
of an NFSv4 bitmask, do so as follows: first, take the bitwise NOT of
the bitmask. Then clear the ACE4_WRITE_OWNER, ACE4_DELETE,
ACE4_READ_NAMED_ATTRIBUTES, and ACE4_WRITE_NAMED_ATTRIBUTES bits.
Also, clear the ACE4_DELETE_CHILD bit on non-directories, and clear
any bits not defined in the protocol.
Create one ALLOW ACE for each entity (OWNER@, GROUP@, and EVERYONE@,
and each user and group named in the given POSIX ACL). After each
OWNER@, EVERYONE@, and named user ACE, append a DENY ACE with the
same entity and flags as the corresponding ALLOW ACE, but with
bitmask set to the complement (as defined above) of the ALLOW ACE.
Do the same for each GROUP@ and named group ACE, but instead of
inserting each new DENY ACE after the corresponding ALLOW ACE, insert
all of the DENY ACEs at the end of the list of GROUP@ and named group
ACEs, in the same order that the GROUP@ and named group ALLOW ACEs
occur in.
Finally, prepend each GROUP@, named user, and named group ACE by a
single DENY whose entity and flags are the same as the corresponding
ALLOW, but whose bitmask is the complement (as defined above) of the
bitmask determined from the mask ACE in the given POSIX ACL. Skip
this step if the given POSIX ACL has no mask ACE.
9. Security Considerations
Any automatic mapping from one ACL model to another must provide Any automatic mapping from one ACL model to another must provide
guarantees as to how the mapping affects the meaning of ACLs, or risk guarantees as to how the mapping affects the meaning of ACLs, or risk
misleading users about the permissions set on filesystem objects. misleading users about the permissions set on filesystem objects.
For this reason, caution is recommended when implementing this For this reason, caution is recommended when implementing this
mapping. It is better to return errors than to break any such mapping. It is better to return errors than to break any such
guarantees. guarantees.
That said, there may be cases where small losses in accuracy can That said, there may be cases where small losses in accuracy can
avoid dramatic interoperability and usability problems; as long as avoid dramatic interoperability and usability problems; as long as
the losses in accuracy are clearly documented, these tradeoffs may be the losses in accuracy are clearly documented, these tradeoffs may be
found acceptable. found acceptable.
For example, a server unable to support all of the NFSv4 mode bits For example, a server unable to support all of the NFSv4 mode bits
does not have a way to communicate its exact limitations to clients, does not have a way to communicate its exact limitations to clients,
so clients (and users) may be unable to recover from such errors. so clients (and users) may be unable to recover from such errors.
For this reason we recommend ignoring bitmask bits that the server is For this reason we recommend ignoring bitmask bits that the server is
completely unable to map to mode bits, and advertising this fact completely unable to map to mode bits, at least when no ACE
loudly in the server documentation. If this is considered explicitly contradicts the server's default behavior. If this is
insufficient, we should add to the NFSv4 protocol additional considered insufficient, we should add to the NFSv4 protocol
attributes necessary to advertise the server's limitations. additional attributes necessary to advertise the server's
limitations.
Note also that this ACL mapping requires mapping between NFSv4 Note also that any ACL mapping also requires mapping between NFSv4
usernames and local id's. When the mapping of id's depends on remote usernames and local id's. When the mapping of id's depends on remote
services, the method used for the mapping must be at least as secure services, the method used for the mapping must be at least as secure
as the method used to set or get ACLs. as the method used to set or get ACLs.
9. References 10. References
[1] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame, [1] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,
C., Eisler, M., and D. Noveck, "Network File System (NFS) C., Eisler, M., and D. Noveck, "Network File System (NFS)
version 4 Protocol", RFC 3530, April 2003. version 4 Protocol", RFC 3530, April 2003.
[2] Institute of Electrical and Electronics Engineers, Inc., "IEEE [2] Institute of Electrical and Electronics Engineers, Inc., "IEEE
Draft P1003.1e", October 1997, Draft P1003.1e", October 1997,
<http://wt.xpilot.org/publications/posix.1e/download.html>. <http://wt.xpilot.org/publications/posix.1e/download.html>.
Authors' Addresses Authors' Addresses
Marius Aamodt Eriksen Marius Aamodt Eriksen
U. of Michigan Center for Information Technology Integration U. of Michigan Center for Information Technology Integration
Email: marius@citi.umich.edu Email: marius@citi.umich.edu
J. Bruce Fields J. Bruce Fields
U. of Michigan Center for Information Technology Integration U. of Michigan Center for Information Technology Integration
Email: marius@citi.umich.edu Email: bfields@citi.umich.edu
Intellectual Property Statement Intellectual Property Statement
The IETF takes no position regarding the validity or scope of any The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be on the procedures with respect to rights in RFC documents can be
 End of changes. 47 change blocks. 
190 lines changed or deleted 290 lines changed or added

This html diff was produced by rfcdiff 1.32. The latest version is available from http://www.levkowetz.com/ietf/tools/rfcdiff/