Exchange Security
-----------------
Every object in the Exchange database has a security descriptor that
controls access to it. (This includes both folders and items, but
security descriptors for items are virtually always inherited from
their parent folders in well-defined ways, so we don't bother thinking
about them.)

The Exchange 2000 Web Storage System has a nifty sytem for translating
Windows security descriptors into XML and back, which unfortunately we
cannot use, because it's buggy. So we have to generate binary format
security descriptors, as described below.

When considering folder permissions, it is important to remember that
while the Exchange database *looks* like a file system when accessed
via WebDAV, it does not behave like a filesystem internally. In
particular, access to an object is controlled only by its *own*
security descriptor; you do not need to have "folder visible"
permission on an object's parent in order to be able to access the
object.


SIDs and Security Descriptors
-----------------------------
This information mostly comes from WinNT.h.


A SID (Security IDentifier) looks like:

	typedef struct {
	       guint8  Revision;
	       guint8  SubauthorityCount;
	       guint8  IdentifierAuthority[6];
	       guint32 Subauthority[];
	} SID;

	#define SID_REVISION 1

Revision is always SID_REVISION. IdentifierAuthority appears to behave
as a 6-byte big-endian number? At any rate, the first 5 bytes are
always 0. There are then SubauthorityCount 4-byte Subauthority values.

A user has a list of SIDs associated with them, including their own
personal SID, the SID for "all users in the local domain", the SID for
"Default", and SIDs for any Windows security groups that they are
members of.

SIDs are also sometimes expressed in string form as:

	S-r-i-s0-s1...

where "r" is the revision, "i" is the identifier_authority, and "sn" is
the nth subauthority.




The ntsecuritydescriptor property on an Exchange 2000 object always
(?) starts with the bytes

	08 00 04 00 00 00 00 00

This does not appear to be part of the descriptor itself, but just
some sort of Exchange-specific overhead. According to MAPI-L, the
first two bytes are the length of the header data to be skipped.

The security descriptor header looks like:

	typedef struct {
		guint8   Revision;
		guint8   Sbz1;
		guint16  Control;
		guint32  Owner;
		guint32  Group;
		guint32  Sacl;
		guint32  Dacl;
	} SECURITY_DESCRIPTOR_RELATIVE;

	#define SECURITY_DESCRIPTOR_REVISION 1

Revision is always SECURITY_DESCRIPTOR_REVISION. Sbz1 is zero padding.
Control is a bitfield as described below. The remaining fields are
offsets from the start of the header (ignoring the Exchange-specific
data mentioned above). Missing sections (eg, the SACL) have 0 for
their offset.

Control is a bitfield of:

	#define SE_OWNER_DEFAULTED         0x0001
	#define SE_GROUP_DEFAULTED         0x0002
	#define SE_DACL_PRESENT            0x0004
	#define SE_DACL_DEFAULTED          0x0008
	#define SE_SACL_PRESENT            0x0010
	#define SE_SACL_DEFAULTED          0x0020
	#define SE_DACL_AUTO_INHERIT_REQ   0x0100
	#define SE_SACL_AUTO_INHERIT_REQ   0x0200
	#define SE_DACL_AUTO_INHERITED     0x0400
	#define SE_SACL_AUTO_INHERITED     0x0800
	#define SE_DACL_PROTECTED          0x1000
	#define SE_SACL_PROTECTED          0x2000
	#define SE_RM_CONTROL_VALID        0x4000
	#define SE_SELF_RELATIVE           0x8000

Where (from WinNT.h):

	SE_OWNER_DEFAULTED, SE_GROUP_DEFAULTED - The Owner / Group was
	    provided by a defaulting mechanism rather than explicitly
	    provided by the original provider of the security
	    descriptor.
	
	SE_DACL_PRESENT, SE_SACL_PRESENT - The Discretionary /
	    Security ACL is present.
	
	SE_DACL_DEFAULTED, SE_SACL_DEFAULTED - The DACL/SACL was
	    provided by a defaulting mechanism rather than explicitly
	    provided by the original provider of the security
	    descriptor.
	
	SE_SELF_RELATIVE - Always set when using this interface.
	    Indicates that the SD occupies contiguous memory and
	    contains offsets rather than pointers.

Outlook-generated descriptors usually have 0x8c04 (SE_SELF_RELATIVE,
SE_SACL/DACL_AUTO_INHERITED, and SE_DACL_PRESENT).

Each ACL header looks like:

	typedef struct {
		guint8  AclRevision;
		guint8  Sbz1;
		guint16 AclSize;
		guint16 AceCount;
		guint16 Sbz2;
	} ACL;

AclRevision is one of

	#define ACL_REVISION     (2)
	#define ACL_REVISION_DS  (4)

Outlook seems to always use ACL_REVISION, but the buggy case of
setting an XML security descriptor uses ACL_REVISION_DS. WinNT.h says
"The current AclRevision is defined to be ACL_REVISION." MSDN says
"Use ACL_REVISION_DS if the ACL contains object-specific ACEs." We
require AclRevision to be 2.

AclSize is the total size of the ACL including all of its ACEs.

Each ACE looks like:

	typedef struct {
		guint8  AceType;
		guint8  AceFlags;
		guint16 AceSize;
		guint32 Mask;
		SID     Sid;
	} ACE;

	/* type */
	#define ACCESS_ALLOWED_ACE_TYPE  (0x00)
	#define ACCESS_DENIED_ACE_TYPE   (0x01)

	/* flags */
	#define OBJECT_INHERIT_ACE       (0x01)
	#define CONTAINER_INHERIT_ACE    (0x02)
	#define NO_PROPAGATE_INHERIT_ACE (0x04)
	#define INHERIT_ONLY_ACE         (0x08)
	#define INHERITED_ACE            (0x10)

If INHERIT_ONLY_ACE is NOT set, the ACE applies to the folder itself.
If CONTAINER_INHERIT_ACE is set, it applies to subfolders. If
OBJECT_INHERIT_ACE is set, it applies to subitems. In normal
Outlook-generated ACEs, OBJECT_INHERIT_ACE and INHERIT_ONLY_ACE always
go together, and our code requires that. (This means we can't parse
the default ACL on /public though...)

INHERITED_ACE means the ACE was inherited from something. We don't
care about, but we still have to keep track of it, because if it is
set when you read the ACE, you have to set it when you write the ACE
back (even if you changed the permissions), or Exchange will consider
your ACE to be an additional ACE rather than a replacement, and then
you'll end up with an ACL that Outlook doesn't like.

The Mask is essentially opaque to us. e2k-security-descriptor.c
handles translating the MAPI permissions into sets of allowed and
denied NT permissions according to rules from the WSS SDK.


Order of ACEs
-------------
The ACEs *must* appear in a specific order. This is at least partly
determined by how security descriptors work, and how the Outlook
permissions model works.

The way Windows checks an action against an ACL is something like this:

	for each ACE in the ACL {
		if ((ACE.Mask covers the attempted_action) &&
		    (ACE.Sid is in CurrentUserSidList))
			return (ACE.AceType == ACCESS_ALLOWED_ACE);
	}
	return FALSE;

In Outlook's permissions model, there are three possibilities:

	- If the user is specified explicitly in the ACL, he gets
	  exactly the rights he's specified to have, and nothing more

	- If the user isn't specified, but is a member of at least
	  one group that is specified, he has the superset of all
	  the rights granted to those groups.

	- Otherwise, the user has the rights granted to "Default"

So if you have:

	Default   Editor
	Bob       Reviewer
	BobNJane  Contributor
        JaneNTed  delete items

then Bob has "Reviewer", Ted has "delete items", Jane has
"Contributor" and "delete items", and everyone else has "Editor". To
make that work in the Windows security model, we have to put the ACEs
in a specific order, and add explicit "deny" ACEs to prevent
fallthrough.

So, the ordering is:

    1. Object-level ACEs for real users, in allow/deny pairs
    2. Container-level ACEs for real users, in allow/deny pairs
    3. Object-level ACEs for Anonymous, in allow/deny pairs
    4. Container-level ACEs for Anonymous, in allow/deny pairs
    5. Container-level ACEs for groups, first all the allows, then all denies
    6. Container-level ACEs for Default (allow only)
    7. Object-level ACEs for groups, first allows, then denies
    8. Object-level ACEs for Default (allow only)

"Default" is never explicitly denied anything.

The ordering above isn't explained completely by the preceding
description (in particular, there doesn't seem to be any reason to
want to put object- and container-level ACEs in a particular order).
I'm not sure if there are additional unknown constraints that force
exactly that ordering or if it's just an artifact of how Outlook
creates them. At any rate, we do it the same way.



Example
-------
http://schemas.microsoft.com/exchange/ntsecuritydescriptor:
    08 00 04 00 00 00 00 00 01 00 04 80 c0 00 00 00
    cc 00 00 00 00 00 00 00 14 00 00 00 02 00 ac 00
    05 00 00 00 00 09 24 00 a9 08 12 00 01 05 00 00
    00 00 00 05 15 00 00 00 2e 43 ac 40 dd e8 e4 1c
    16 c0 ea 32 96 04 00 00 01 09 24 00 16 07 1f 00
    01 05 00 00 00 00 00 05 15 00 00 00 2e 43 ac 40
    dd e8 e4 1c 16 c0 ea 32 96 04 00 00 00 02 24 00
    a9 08 12 00 01 05 00 00 00 00 00 05 15 00 00 00
    2e 43 ac 40 dd e8 e4 1c 16 c0 ea 32 96 04 00 00
    01 02 24 00 16 c9 0d 00 01 05 00 00 00 00 00 05
    15 00 00 00 2e 43 ac 40 dd e8 e4 1c 16 c0 ea 32
    96 04 00 00 00 02 14 00 a9 08 12 00 01 01 00 00
    00 00 00 01 00 00 00 00 01 01 00 00 00 00 00 05
    12 00 00 00 01 02 00 00 00 00 00 05 20 00 00 00
    20 02 00 00

Exchange header:
    08 00 04 00 00 00 00 00 

SD revision, zero pad, control flags
    01,  00,  04 8c

Offsets of owner, group, sacl (not present), and dacl
    c0 00 00 00
    cc 00 00 00
    00 00 00 00
    14 00 00 00

DACL (at offset 0x14 from start of SD)
  DACL revision, zero pad, DACL size, ACE count, zero pad
    02,  00,  ac 00,  05 00,  00 00

  ACE #1: allowed, subitem, 36 bytes
    00,  09,  24 00
  permissions mask
    a9 08 12 00
  SID (S-1-5-21-1085031214-484763869-854245398-1174)
    01 05 00 00 00 00 00 05 15 00 00 00 2e 43 ac 40
    dd e8 e4 1c 16 c0 ea 32 96 04 00 00 

  ACE #2: denied, subitem, 36 bytes
    01,  09,  24 00 
  permissions mask
    16 07 1f 00
  SID (S-1-5-21-1085031214-484763869-854245398-1174)
    01 05 00 00 00 00 00 05 15 00 00 00 2e 43 ac 40
    dd e8 e4 1c 16 c0 ea 32 96 04 00 00 

  ACE #3, allowed, self/subfolder, 36 bytes
    00,  02,  24 00
  permissions mask
    a9 08 12 00
  SID (S-1-5-21-1085031214-484763869-854245398-1174)
    01 05 00 00 00 00 00 05 15 00 00 00 2e 43 ac 40
    dd e8 e4 1c 16 c0 ea 32 96 04 00 00 

  ACE #4, denied, self/subfolder, 36 bytes
    01,  02,  24 00
  permissions mask
    16 c9 0d 00
  SID (S-1-5-21-1085031214-484763869-854245398-1174)
    01 05 00 00 00 00 00 05 15 00 00 00 2e 43 ac 40
    dd e8 e4 1c 16 c0 ea 32 96 04 00 00 

  ACE #5, allowed, self/subfolder, 20 bytes
    00,  02,  14 00
  permissions mask
    a9 08 12 00
  SID (S-1-1-0 = Default)
    01 01 00 00 00 00 00 01 00 00 00 00

Owner SID (at offset 0xc0 from start of SD)
  SID (S-1-5-18 = NT AUTHORITY\SYSTEM)
    01 01 00 00 00 00 00 05 12 00 00 00

Group SID (at offset 0xcc from start of SD)
  SID (S-1-5-32-544 = BUILTIN\Administrators)
    01 02 00 00 00 00 00 05 20 00 00 00 20 02 00 00
