Access Checks

Before I begin today’s post, a caveat: In this discussion, when I use the term “security”, I don’t mean “security defect free”, instead I mean “using the NT security subsystem”.  The two often become confused, and I just want to make sure that people know which aspect of security I’m talking about.  Also, people should refer to my glossary on security terms if there is any confusion about terms I’m using inside this post.

Whenever discussions of NT security come up, the first comment that people make is “Oooh, security is hard”.  And I always respond “No it’s not, security in NT is just bit manipulation”.

Well, if you look at it at the fine grained details (the myriad types of groups, the internal data structure of a SID, how to look up user information from the SAM database, etc) then security can seem daunting.

But the reality is that the core of NT’s security architecture is a single routine: AccessCheck.  And the AccessCheck API is all about bit twiddling. Over the next couple of posts, I’ll describe how NT’s access check functionality works.  There are about a half a dozen functions that perform access checks, but they all share the basic structure of the AccessCheck API (in fact, internally all the NT access check functions are performed by a single routine).

At its core, the AccessCheck API takes three inputs: The user’s token, a desired access mask, and a security descriptor.  The access mask and the user’s token are applied to the SecurityDescriptor and the API determines if the user should have access or not.

Before we can discuss AccessCheck, we first need to discuss security descriptors (or, to be more specific, Access Control Lists (ACLs)).  In general, in NT, a security descriptor has four components:

1)      The security descriptor owner (a SID).

2)      The security descriptor group (a SID).

3)      The security descriptor discretionary ACL (DACL).

4)      The security descriptor System ACL (SACL).

First, the easiest of the four: The security descriptor group exists in NT for posix compliance; it’s not used as a part of the access check process…

The security descriptor owner is usually the creator of the object (if the creator is a member of the administrators group, then the owner of the object is the administrators group, this is because all administrators are considered to be interchangeable for the purposes of object ownership).  The owner of a security descriptor is automatically granted WRITE_DAC access to the object – in other words, the owner of an object can ALWAYS modify the security descriptor of that object.

The SACL describes the auditing semantics of the object – if the application calls an access check function that does auditing (AccessCheckAndAuditAlarm, AccessCheckByTypeAndAuditAlarm, AccessCheckByTypeResultListAndAuditAlarm, and AccessCheckByTypeResultListAndAuditAlarmByHandle), then after the AccessCheck functionality is executed, the system applies the result to the SACL and if the SACL indicates that the result should be audited, then an audit entry is generated.

The DACL’s the big kahuna.  It’s the structure that completely describes the access rights that the user has to the object being protected. 

The DACL and SACL are both access control lists, and thus share the same structure.

Essentially an access list is an ordered list of Access Control Entries (ACEs).  There are about 15 different types of access control entries, in general they fall into four different categories:

1)      Access Allowed ACEs – these grant access to an object for a particular SID.

2)      Access Denied ACEs – these deny access to an object for a particular SID.

3)      Audit ACEs – these indicate if an audit should be generated when a particular user is either granted or denied a particular access right.

4)      Alarm ACEs – currently unused, but similar to audit aces – an alarm ACE would trigger a system alarm if their criteria were met instead of generating an audit record.

Regardless of the type of the ACE, each ACE shares a common header, the ACE_HEADER.  There are two important fields in the ACE header – the first is the ACE type, which describes the semantics of the ACE, the second is the AceFlags – this field describes the ACL inheritance rules for this ACE.  It also contains the FAILED_ACCESS_ACE_FLAG and SUCCESSFUL_ACCESS_ACE_FLAG which is used for the audit ACEs.

Tomorrow: How are ACL’s used in the access check algorithm.