Documentum Content Server version 6.6 introduced a new feature, “Owner Minimum Permissions”, which allows the minimum permissions for owners to be set across the repository. These permissions would override any ACL based calculations – no ACL could reduce the effective owner permissions to be more restrictive than the ones set up in this configuration. Note that version 5.3 also has a similar behavior except that the owner minimum permissions are fixed (not configurable) – READ and all extended permissions other than EXTENDED DELETE.
It has been confirmed that this feature does not work as expected in version 6.6. At least for one operating system and database combination, these settings have no effect and the behavior is identical to 5.3. It is quite likely that this problem is not restricted to this one environment configuration.
A Documentum Architecture whitepaper is available on EMC Documentum Developer Community site – EMC Documentum Architecture: Delivering the Foundations and Services for Managing Content Across the Enterprise. A part of page 13 from the currently posted version (dated January 2008, a newer version will probably fix this issue) is shown below. It describes object-level security in a confusing manner.
The areas of concern are marked in the image. These concerns are explained below:
Under Basic Permissions, it states that Delete is a special case with regard to the cumulative property. This is an incorrect assertion. The Delete basic permission does imply all the other lower basic permissions.
The section title – “Object-level delete privileges” is inconsistent with Documentum terminology. Privileges are associated with users and permissions are associated with objects being secured.
“Delete Object permission” should be “Delete Object extended permission” to be unambiguously correct. It is not the basic delete permission, which is suggested by the last sentence of the previous section.
Two Extended Permissions are missing in the list – Delete Object and Change Folder Links. The Delete Object extended permission is actually what is explained under the title “Object-level delete privileges” above. The Change Folder Links extended permission was introduced in Documentum 6. It enables linking to and unlinking from a folder.
Object permissions are stored as integers in Documentum ACL objects. For each accessor, there is one value (1-7) which represents one of None, Browse, Read, Relate, Version, Write, and Delete. These permissions are hierarchical, so 4 would imply 4 and everything below it.
ACL’s also include extended permissions. An accessor can be assigned a subset of Change Location, Change Ownership, Change Permission, Execute Procedure, Change State, and Extended Delete. All of these values are independent and they can be assigned in any combination to one accessor in an ACL. However, there is only one field to store the extended permissions for one accessor. The obvious way to store such information is using bit fields and, indeed, that is how it is stored in the repository. There is only one catch though – the details are hard to find until you hit the DFC Javadocs for IDfACL. There you can find the specs under the method getAccessorXPermit().
You would think that that’s the whole story but it isn’t. It’s very easy to get it wrong like this post did. The bits at position 0 and 1 are interpreted in a reverse manner compared to the rest of the bits – 0 means has permission and 1 means doesn’t. That is why “no extended permissions” is encoded as 3!
That’s about it. The only additional piece is that D6 has added a new extended permission – Change Folder Links. The Javadoc for bit-encoding hasn’t been updated to reflect this change. However, it will be pretty easy to figure out by dumping an ACL object containing that extended permission.
[UPDATE] Here is the obvious way to implement it using the bit-wise AND operator (&). // assuming that R_ACCESSOR_XPERMIT contains the integer value to be decoded
boolean execProc = (R_ACCESSOR_XPERMIT & 1) == 0;
boolean chgLoc = (R_ACCESSOR_XPERMIT & 2) == 0;
boolean chgState = (R_ACCESSOR_XPERMIT & 65536) != 0;
boolean chgPerm = (R_ACCESSOR_XPERMIT & 131072) != 0;
boolean chgOwner = (R_ACCESSOR_XPERMIT & 262144) != 0;
boolean extDelete = (R_ACCESSOR_XPERMIT & 524288) != 0;
And just for fun, here is another way to implement this decoding without using bit-wise operations. The % is the mod operator which takes the remainder after division. // assuming that R_ACCESSOR_XPERMIT contains the integer value to be decoded
boolean execProc = (R_ACCESSOR_XPERMIT%2) == 0;
boolean chgLoc = (R_ACCESSOR_XPERMIT%4) - (R_ACCESSOR_XPERMIT%2) == 0;
boolean chgState = (R_ACCESSOR_XPERMIT%131072) - (R_ACCESSOR_XPERMIT%65536) != 0;
boolean chgPerm = (R_ACCESSOR_XPERMIT%262144) - (R_ACCESSOR_XPERMIT%131072) != 0;
boolean chgOwner = (R_ACCESSOR_XPERMIT%524288) - (R_ACCESSOR_XPERMIT%262144) != 0;
boolean extDelete = (R_ACCESSOR_XPERMIT%1048576) - (R_ACCESSOR_XPERMIT%524288) != 0;