Monday, March 17, 2014

How To Interpret AccessRights Numbers In CRM Security Exceptions

When a user attempts to preform an action in CRM there are two potential types of security issues that could arise.
  1. The user’s access level for the privilege required to perform the action is none e.g., attempting to share a contact:
    Contact_No_Share
  2. The user has an access level for the privilege required to perform the action, but it isn’t generous enough e.g., attempting to share a contact with a user outside of the business unit:
    Contact_Org_Share
In either case, if action requires a single privilege, and the user doesn’t have the privilege (or doesn’t have high enough access rights for the privilege), you’ll get an error like the following:
CrmException:
 SecLib::AccessCheckEx failed. Returned hr = -2147187962,
 ObjectID: abe86dd6-d7aa-e311-ade6-cfcd73da4a68,
 OwnerId: db2f6110-1a9d-df11-9d85-005056bb728e, 
 OwnerIdType: 8 and
 CallingUser: edce293b-789d-e311-950c-ed9561bb126a.

 ObjectTypeCode: 4201,
 objectBusinessUnitId: 966fe7c8-89c1-de11-853f-005056bb728e,
 AccessRights: prvShareActivity


This gives combined with the Security Role UI to Privilege Mapping gives all the information required to determine the security rights required.  The Calling user, object, object’s type, object’s owner, object’s owner type, and object’s business, as well as the Access Right required.  Sometimes though, the error looks like this:


CrmException:
 SecLib::AccessCheckEx failed. Returned hr = -2147187962,
 ObjectID: abe86dd6-d7aa-e311-ade6-cfcd73da4a68,
 OwnerId: db2f6110-1a9d-df11-9d85-005056bb728e, 
 OwnerIdType: 8 and
 CallingUser: edce293b-789d-e311-950c-ed9561bb126a.

 ObjectTypeCode: 4201,
 objectBusinessUnitId: 966fe7c8-89c1-de11-853f-005056bb728e,
 AccessRights: 262153


In this case the Access Rights is a little more cryptic.  This is what happens when an operation requires multiple privileges, e.g. Share and Append.  To “decrypt” it you’ll need to know how enum flags work, and what the actual powers of two are in this case.


Below are the values as taken from the Microsoft.Crm.Sdk.Messages.AccessRights Enum

Name Value Binary Value Description
ReadAccess 1 0001 Specifies the right to read the specified type of object.
WriteAccess 2 0010 Specifies the right to update (write to) the specified object.
AppendAccess 4 0100 Specifies the right to append the specified object to another object.
AppendToAccess 16 0001 0000 Specifies the right to append another object to the specified object.
CreateAccess 32 0010 0000 Specifies the right to create an instance of the object type.
DeleteAccess 65536 0001 0000 0000 0000 0000 Specifies the right to delete the specified object.
ShareAccess 262144 0100 0000 0000 0000 0000 Specifies the right to share the specified object.
AssignAccess 524288 1000 0000 0000 0000 0000 Specifies the right to assign the specified object to another security principal.


In the error above, 262153 is

0100 0000 0000 0000 1001

But wait, There is no Access Right with a binary value of 1000.  Since I’ve been unable to find any other documentation, my guess is that something on our installation (that was an upgrade from a CRM 4.0 server) still has a reference to the CRM 4.0 enum values in which AppendToAccess is actually 8 (1000) rather than 16 (0001 0000).


Using that assumption and the table above, 2621534 is made up of ShareAccess, AppendToAccess, and ReadAccess.  This means the user has to have sufficient Access Levels for Share, Append, and Read privileges of the entity, in order to successfully perform the requested operation.