Here is part 2 of the ACL information from Larry Osterman http://blogs.msdn.com/exchange/archive/2004/04/22/118377.aspx
This is part two of a three part series. See part one here.
When we set out to design the Exchange 2000 NT ACLs, the biggest task we faced was to determine what the correct values for the NT access rights should be.
We knew we had to be compatible with the existing 10 Exchange access rights - every access check semantic that could be expressed in Exchange 5.5 had to be able to be expressed in Exchange 2000. So the logical interpretation was to simply bring the 10 access rights over from Exchange 5.5 and just stick them on the NT ACLs. Since the NT access check mechanism allows for 16 access rights, we figured that would be easy.
Then we remembered IFS.
See, there's this amazingly cool feature in Exchange 2000 called IFS. It exposes Exchange folders as if they're filesystem folders. And the IFS team wanted to support security fully on the store, and they wanted to use Exchange's ACLs directly to do it (as opposed to rewriting the ACL before they handed it to the client).
This threw a huge wrench into the works because it added a whole other level of compatibility requirements. Now Exchange access rights had to:
-
Be able to be mapped bidrectionally between Exchange 5.5 access rights
-
Be bit-wise compatible with the NT file-system access rights.
-
Be able to express all the semantics of Exchange that aren't present in the file-system.
Needless to say, we were in quite a pickle. One major issue we had had to do with the NT native access rights themselves. The NT filesystem access rights are as follows:
Access Right | Bit pattern | Applies to: |
FILE_READ_DATA | 0x0001 | file & pipe |
FILE_LIST_DIRECTORY | 0x0001 | directory |
FILE_WRITE_DATA | 0x0002 | file & pipe |
FILE_ADD_FILE | 0x0002 | directory |
FILE_APPEND_DATA | 0x0004 | file |
FILE_ADD_SUBDIRECTORY | 0x0004 | directory |
FILE_CREATE_PIPE_INSTANCE | 0x0004 | named pipe |
FILE_READ_EA | 0x0008 | file & directory |
FILE_WRITE_EA | 0x0010 | file & directory |
FILE_EXECUTE | 0x0020 | file |
FILE_TRAVERSE | 0x0020 | directory |
FILE_DELETE_CHILD | 0x0040 | directory |
FILE_READ_ATTRIBUTES | 0x0080 | all |
FILE_WRITE_ATTRIBUTES | 0x0100 | all |
NT defines 14 different access rights, but it also overlays the rights. For example, the same access right that allows access to the data streams on a file is used to control if the user can see the contents of a directory. Similarly, the same bit that's used to determine if a file can be opened for append access is used to control the creation of subdirectories. In addition to those access rights, NT also defines 5 "standard" access rights:
DELETE | 0x00010000L |
READ_CONTROL | 0x00020000L |
WRITE_DAC | 0x00040000L |
WRITE_OWNER | 0x00080000L |
SYNCHRONIZE | 0x00100000L |
These access rights apply to all objects, not just files. The "SYNCHRONIZE" access right isn't a proper "access" right, its an indication that the handle to the object being opened can be used synchronization. The other three access rights protect various parts of the security descriptor in the object.
Fortunately, the Exchange access rights are similarly partionable - 5 of the 10 access rights (frightsReadAny, frightsEditAny, frightsDeleteAny, frightsEditOwned and frightsDeleteOwned) apply to the messages in a folder, 4 of the access rights apply to the folder (frightsCreate, frightsCreateSubfolder, frightsOwner, frightsVisible). The remaining right (frightsContact) isn't really an access right - it's not used to grant or deny access to resources, but just a placeholder used to indicate that a particular user is a contact for the folder.
Taking each of the exchange access rights in turn, we realized that:
-
frightsReadAny - This right is sort-of a "read" access right. It allows the user to read all the properties on any message in the folder.
-
frightsEditAny - This right is sort-of a "write" access right. It allows the user to write any property on any message in the folder.
-
frightsDeleteAny - This maps nicely to the DELETE filesystem access right.
-
frightsEditOwned - This is "sort-of" like a write access, but it's conditional based on the "owner" of the message.
-
frightsDeleteOwned - This is "sort-of" like delete access, but again, it's conditional.
-
frightsCreate - This maps nicely to the FILE_ADD_FILE access right.
-
frightsCreateSubFolder - This maps nicely to the FILE_ADD_SUBDIRECTORY right.
-
frightsOwner - This one's kinda tough - it enables write access to all the properties in the folder.
-
frightsVisible - This property allows read access to the properties in the folder.
Next, we looked at the NT access rights. Our big "aha!" was when we realized that there could be a one-to-many relationship between the exchange access rights and the NT access rights. For example, on a file, there are three access rights that map to "read-like" access rights - FILE_READ_DATA, FILE_READ_EA, and FILE_READ_ATTRIBUTES. Similarly, there are 3 write-like access rights - FILE_WRITE_DATA, FILE_WRITE_EA and FILE_WRITE_ATTRIBUTES. So if we defined Exchange access rights for each of these "read-like" and "write-like" bits, we could simply map the exchange writes to ALL of them. Similarly, we could make the same statements about the frightsOwner and frightsVisible access rights - they can be mapped to FILE_WRITE_ATTRIBUTE and FILE_READ_ATTRIBUTE respectively. So we were 90% of the way done with figuring out what to do.
Once we decided that we were going to map single access rights to multiple access bits, we needed to figure out what each of the NT filesystem access rights would mean to the Exchange store.
We started with the read access rights: FILE_READ_DATA, FILE_READ_EA, and FILE_READ_ATTRIBUTES.
FILE_READ_DATA protects access to the file's data streams. The closest analog to this in Exchange are the properties that make up the "body" of the message. Ok, so far so good. But what are "attributes" and "extended attributes" on a message? Some of the properties like PR_ATTR_READONLY were obvious - it's used to map to the read-only filesystem attribute, so it's clearly an attribute, but what about the other ones.
We decided to make a totally and absolutely arbitrary decision. We defined a specific set of properties as "attributes", a specific set of properties as "body" properties, and all the others we classified as either "extended attributes" or "body" properties depending on whether or not the property was transmittable.
Exchange 2000 Access Mask
When we were finally done and the dust had settled, we had settled on twenty-two access rights, but many of them overlap. We finally ended up with:
The Exchange Platinum access rights are:
fsdrightReadBody† | 0x00000001 | The ability to read the “body” of a message. |
fsdrightListContents‡ | 0x00000001 | The ability to open a contents table. |
fsdrightWriteBody† | 0x00000002 | The ability to modify the “body” of a message. |
fsdrightCreateItem‡ | 0x00000002 | The ability to create new messages |
fsdrightAppendMsg† | 0x00000004 | The ability to append data to a message |
fsdrightCreateContainer‡ | 0x00000004 | The ability to create a subfolder |
fsdrightReadProperty | 0x00000008 | The ability to read properties on the folder/message. |
fsdrightWriteProperty | 0x00000010 | the ability to write properties on the folder/message. |
fsdrightExecute† | 0x00000020 | The ability to “execute” the body of a message |
fsdrightReserved1‡ | 0x00000040 | The ability to delete arbitrary items under this folder |
fsdrightReadAttributes | 0x00000080 | The ability to read the “attributes” of a folder/message. |
fsdrightWriteAttributes | 0x00000100 | The ability to modify the “attributes” of a folder/message. |
fsdrightWriteOwnProperty† | 0x00000200 | The ability to modify messages that the principal granted this right has created. |
fsdrightDeleteOwnItem† | 0x00000400 | The ability to delete messages that the principal granted this right has created. |
fsdrightViewItem | 0x00000800 | The ability to see the items in the folder. |
fsdrightOwner‡ | 0x00004000 | No security semantics, used to indicate the “owner” of a folder. |
fsdrightContact‡ | 0x00008000 | No security semantics, used to indicate “contacts” for a folder – people that are not the owner, but are responsible for the folder. |
fsdrightWriteSD | WRITE_DAC | Alias for NT “WRITE_DAC” right. |
fsdrightDelete | DELETE | Alias for NT “DELETE” right. |
fsdrightWriteOwner | WRITE_OWNER | Alias for NT “WRITE_OWNER” right. |
fsdrightReadControl | READ_CONTROL | Alias for NT “READ_CONTROL” right. |
fsdrightSynchronize | SYNCHRONIZE | Alias for NT “SYNCHRONIZE” right. |
Access rights that apply only to messages have a † symbol after their name; access rights that apply only to folders have a ‡ symbol after their name. If an access right does not have a symbol, it applies to both messages and folders.
Putting it all together
Ok, so now that we've defined the Exchange 2000 access rights, we needed to set up the mapping between Exchange 5.5 access rights and Exchange 2000 access rights. If we can't do that, we can't even begin to attempt to convert ACLs from Exchange 5.5 to Exchange 2000
So here's what we finally came up with:
Exchange 5.5 Rights | Exchange 2000 Rights |
frightsReadAny | fsdrightReadControl fsdrightReadBody fsdrightReadAttributes fsdrightReadProperty fsdrightViewItem fsdrightSynchronize fsdrightExecute |
frightsCreate | |
frightsEditOwned | |
frightsDeleteOwned | |
frightsEditAny | |
frightsDeleteAny | fsdrightDelete |
frightsCreateSubfolder | fsdrightCreateContainer |
frightsOwner | |
frightsContact | fsdrightContact |
frightsVisible | fsdrightViewItem |
And the reverse mapping table (used when converting between an NT security descriptor into an Exchange ACL):
EXCHANGE 2000 ACCESS RIGHTS | Exchange 5.5 access rightS |
| |
fsdrightListContents | Ignored |
fsdrightWriteBody | Ignored |
fsdrightCreateItem | frightsCreate |
fsdrightAppendMsg | Ignored |
fsdrightCreateContainer | frightsCreateSubfolder |
fsdrightReadProperty | frightsReadAny |
fsdrightWriteProperty | frightsEditAny |
fsdrightExecute | Ignored |
fsdrightReserved1 | Ignored |
fsdrightReadAttributes | Ignored |
fsdrightWriteAttributes | Ignored |
fsdrightWriteOwnProperty | frightsEditOwned |
fsdrightDeleteOwnItem | frightsDeleteOwned |
fsdrightViewItem | frightsVisible for folders, ignored on messages |
fsdrightOwner | frightsOwner |
fsdrightContact | frightsContact |
fsdrightWriteSD | Ignored |
fsdrightDelete | frightsDeleteAny on messages |
fsdrightWriteOwner | Ignored |
fsdrightReadControl | Ignored |
fsdrightSynchronize | Ignored |
A quick note: frightsOwner only granted if ALL the folder owner rights are present – fsdrightOwner fsdrightWriteProperty fsdrightWriteSD fsdrightDelete fsdrightWriteOwner fsdrightWriteAttributes fsdrightViewItem.
Well, that's the basics on access rights. I don't quite know how it got this long but...
The next column pulls it together and describes how we convert from Exchange 5.5 ACLs into Exchange 2000 ACLs. (See first column)
- Larry Osterman