MDAC 2.5 SDK - Technical Articles


 

Access Control Administration

The final area of security administration that the provider must handle is access control administration. The data provider implements the IObjectAccessControl interface to handle all access control administration tasks.

The IObjectAccessControl interface is similar in purpose to the standard COM interface IAccessControl. However, IObjectAccessControl is somewhat more complicated because many data stores do not expose their database objects as COM objects. For more information about the difference between IObjectAccessControl and IAccessControl, see the Appendix of this guide.

To handle access control tasks, the data provider must be able to do the following:

  1. The data provider must be able to uniquely identify the object on which access control settings are being read or written. The SEC_OBJECT and SEC_OBJECT_ELEMENT structures are used to identify a database object or a type of database object in the data store. The SEC_OBJECT structure contains an array of SEC_OBJECT_ELEMENT structures.
  2. The data provider must identify the permission settings for the object. The ACCESS_MASK structure controls which permissions are granted or denied on an object for a trustee. Each permission setting controls whether a specific action is allowed or denied. The ACCESS_MASK structure sets aside 16 bits for specific permission settings needed by the object. OLE DB uses 8 of these 16 bits to control specific permission settings on the object. Several PERM* constants are defined to simplify working with the bits in this structure. This structure is documented in the Access Control section of the Microsoft® Platform SDK.

  3. The data provider must associate each ACCESS_MASK with a specific trustee. The EXPLICIT_ACCESS structure is used to pair each trustee with changes to the permissions for an object. The trustee is identified with a TRUSTEE structure in the Trustee element of the EXPLICIT_ACCESS structure. The permissions are in an ACCESS_MASK structure stored in the grfAccessPermissions element. Two additional elements are used to determine the operation and the inheritance characteristics:

EXPLICIT_ACCESS, ACCESS_MASK, ACCESS_MODE, and ACCESS_INHERITANCE are all fully documented in the Access Control section of the Microsoft Platform SDK. Microsoft Windows® includes the BuildExplicitAccessWithName function to assist with initializing an EXPLICIT_ACCESS structure.

IObjectAccessControl Methods

IObjectAccessControl methods can manage access control for database objects. By using these methods, the consumer can set and get the access permissions for a trustee on an object, set and get the owner of an object, and perform an access check.

To set the access permissions on an object, the consumer allocates a SEC_OBJECT structure and initializes it to specify the object. The consumer also allocates and initializes an array of EXPLICIT_ACCESS structures to indicate the trustees, the permissions being applied, and the operations to apply. Then the consumer calls IObjectAccessControl::SetObjectAccessRights, and the provider selects the specified database object in the data store. The provider iterates the array of EXPLICIT_ACCESS structures and sets the indicated permissions on the selected object. Any errors are returned to the consumer by using the HRESULT.

To get the access permissions on an object, the consumer allocates a SEC_OBJECT structure and initializes it to specify the object. To get all the explicit rights for the object, the consumer can call IObjectAccessControl::GetObjectAccessRights right away. Otherwise, the consumer allocates and initializes a TRUSTEE structure and an array of one or two EXPLICIT_ACCESS structures and then initializes the Trustee elements of each to point to the TRUSTEE structure. If the consumer uses only one EXPLICIT_ACCESS structure, it sets the grfAccessMode element to either SET_ACCESS or DENY_ACCESS. If the consumer uses two structures to get the full set of permissions, it sets one structure's grfAccessMode element to SET_ACCESS and the other to DENY_ACCESS and then calls IObjectAccessControl::GetObjectAccessRights.

The provider handles IObjectAccessControl::GetObjectAccessRights by examining the pcAccessEntries parameter, which identifies how many elements are in the array of EXPLICIT_ACCESS structures. If pcAccessEntries is zero, the provider allocates an array of EXPLICIT_ACCESS structures; otherwise, the provider uses the array that was passed to the method by the consumer. In either case, the provider selects the specified object and gathers the access permissions for the object, allocating the array of EXPLICIT_ACCESS structures if necessary. Then the provider sets the grfAccessPermissions and grfInheritance elements in the appropriate EXPLICIT_ACCESS structures. Any errors are returned to the consumer by using the HRESULT, and if errors occurred, any allocated memory is released by the provider. The consumer, if it requested all the rights for the object, releases the array of allocated EXPLICIT_ACCESS structures when it is finished with it.

To set the owner of an object, the consumer allocates a SEC_OBJECT structure and initializes it to specify a database object. The consumer also allocates and initializes a TRUSTEE structure and then calls IObjectAccessControl::SetObjectOwner. The provider sets the trustee as the owner of the specified object. Any errors are returned to the consumer by using the HRESULT.

To get the owner of an object, the consumer allocates a SEC_OBJECT structure, initializes it to specify a database object, and then calls IObjectAccessControl::GetObjectOwner. The provider allocates a TRUSTEE structure, gets the owner of the specified object, and initializes the TRUSTEE structure with the owner of the object. Any errors are returned to the consumer by using the HRESULT. The consumer releases the TRUSTEE structure when it is finished with it.

To perform an access check, the consumer allocates a SEC_OBJECT structure and initializes it to specify a database object. The consumer also allocates and initializes an EXPLICIT_ACCESS structure to indicate the trustee and the permissions being checked. Then the consumer calls IObjectAccessControl::IsObjectAccessAllowed, passing a pointer to a BOOL variable, and the provider determines whether the trustee has the permissions listed in the EXPLICIT_ACCESS structure. In doing so, the provider may include the permissions of any membership trustees to which the trustee belongs. The provider sets the BOOL variable depending on the outcome. Any errors are returned to the consumer by using the HRESULT.