Blog Post

Exchange Team Blog
7 MIN READ

Exchange 2000 ACL mechanism

The_Exchange_Team's avatar
Apr 22, 2004

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

fsdrightCreateItem

frightsEditOwned

fsdrightWriteOwnProperty

frightsDeleteOwned

fsdrightDeleteOwnItem

frightsEditAny

fsdrightReadControl fsdrightWriteBody fsdrightWriteAttributes fsdrightWriteProperty fsdrightAppendMsg fsdrightCreateItem fsdrightDelete fsdrightCreateContainer fsdrightOwner fsdrightSynchronize fsdrightWriteSD fsdrightWriteOwner

frightsDeleteAny

fsdrightDelete

frightsCreateSubfolder

fsdrightCreateContainer

frightsOwner

fsdrightOwner fsdrightWriteProperty fsdrightWriteSD fsdrightDelete fsdrightWriteOwner fsdrightWriteAttributes fsdrightViewItem

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

fsdrightReadBody

Ignored

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

Updated Jul 01, 2019
Version 2.0
No CommentsBe the first to comment