Restricted Tokens

[Previous] [Next]

As I mentioned earlier, it is impossible for your service or any application to build a token from scratch—the system must build it for you. But Windows will allow you to create a new token, based on an existing token, with some additional restrictions. This new token is known as a restricted token. The restricted token can help your software meet some complex security needs with a very clean solution.

When you create a restricted token, you are not adding restrictions to an existing token. Instead you are using a token as a kind of template to create a new token, although this new token has additional restrictions. There are three restrictions that you can place on your token. Each restriction is optional, and you can choose any combination of them in the creation of your new token. Two of the restrictions rely on knowledge of access control, which I covered in detail in Chapter 10. You can perform any combination of the following actions on a token to create a new restricted token:

  • Delete privileges
  • Disable token SIDs for trustee accounts
  • Add "restricted SIDs" of trustee accounts

Deleting Privileges

When creating a restricted token, you can choose a set of privileges that you do not want granted to the new token, which is not the same as disabling privileges. Rather, you are explicitly removing a privilege from the new token. There might be situations in which you want to use an existing security context but delete certain privileges. For example, you might use your own security context or one received via impersonation and remove the SE_SHUTDOWN_NAME or SE_TCB_NAME privileges.

Disabling Token SIDs

When creating a restricted token, you can select which of the trustees in the existing token will be disabled. The disabled trustees can be any combination of the token user and the groups of which the user is a member. Any trustees whose SIDs are selected to be added to the disabled list will be used for denied access only, when access checks are performed.

For example, suppose the token user's membership in the TEMP USERS group awarded the user access to the C:\Temp directory while denying the user access to the C:\Permanent directory. If the SID for the TEMP USERS group was selected to be a disabled SID in a restricted token, membership in the TEMP USERS group would no longer allow access to the C:\Temp directory, but it would still deny access to the C:\Permanent directory.

You can disable only those SIDs that already exist in the source token, and disabling trustees in a token does not in any way affect the identity of the token. Disabling the token user, for example, only affects access to objects. The token still identifies that particular user.

Adding Restricted SIDs

In addition to disabling existing SIDs, you can create a set of trustees, or SIDs, known as restricted SIDs, to dynamically add to your new token. You might be thinking that the ability to dynamically add a trustee to a token is awfully powerful. But the catch is that the new SIDs are used as a cross-check for access to a securable object. Not only does an access check have to clear the token's "natural" trustees before access can be granted, but it also has to clear the new set of restricted trustees.

Using restricted SIDs is similar to creating a second token and making sure that both tokens have access to a securable object before performing an action on the object. But with restricted tokens, this second check is handled automatically for you by the system. Restricted SIDs change access checks somewhat in that they must actually be performed twice: once for the natural SIDs in the token and once for the restricted SIDs. Only when both succeed is the access check granted. (See Chapter 10 for a detailed discussion of access checks.)

Now you are familiar with the restrictions you can apply to your new restricted copy of a token. Let's look at the function that creates the token, CreateRestrictedToken:

 BOOL CreateRestrictedToken(    HANDLE               hExistingTokenHandle,    DWORD                dwFlags,    DWORD                dwDisableSidCount,    PSID_AND_ATTRIBUTES  pSidsToDisable,    DWORD                dwDeletePrivilegeCount,    PLUID_AND_ATTRIBUTES pPrivilegesToDelete,    DWORD                dwRestrictedSidCount,    PSID_AND_ATTRIBUTES  pSidsToRestrict,    PHANDLE              phNewTokenHandle); 

The hExistingTokenHandle parameter is the source token from which the new token will be created. CreateRestrictedToken creates a new token based on the token whose handle is passed as the hExistingTokenHandle parameter. The handle must have TOKEN_DUPLICATE access. Any token is legal as the source token for a restricted token with the exception of a token that already has a list of restricting SIDs. You can ascertain whether a token contains restricted SIDs by passing its handle to the IsTokenRestricted function:

 BOOL IsTokenRestricted(    HANDLE TokenHandle); 

You can pass DISABLE_MAX_PRIVILEGE as the dwFlags parameter if you want the new token to allow only functionality that requires no privileges. You can pass zero if you want to delete only a subset of the privileges. Passing zero is the more common case.

The dwDisableSidCount parameter indicates the number of trustees you want to ensure are disabled in the new token. The next parameter, pSidsToDisable, points to an array of SID_AND_ATTRIBUTES structures indicating the groups (as well as perhaps the token user) to disable in the new token. The dwDisableSidCount parameter refers to the number of entries passed as this parameter. Disabled SIDs are characterized by the existence of the SE_GROUP_USE_FOR_DENY_ONLY attributes information for the SID in the new token.

NOTE
You can pass a superset of the trustees represented in the source token as the pSidsToDisable parameter. The system will ignore any SIDs not in the source token. In this way you can generically apply a single list of disabled SIDs to more than one token with different underlying token users and groups.

The SID_AND_ATTRIBUTES structure is defined as follows:

 typedef struct _SID_AND_ATTRIBUTES {     PSID  Sid;     DWORD Attributes;  } SID_AND_ATTRIBUTES ; 

The Attributes member of the structure is ignored by CreateRestrictedToken. Other functions such as GetTokenInformation use the Attributes member to report attributes of a SID such as SE_GROUP_USE_FOR_DENY_ONLY and SE_GROUP_MANDATORY. The Sid member of SID_AND_ATTRIBUTES points to a SID structure indicating the trustee that you wish to disable in the new token.

Your server should pass a fully populated array of SID_AND_ATTRIBUTES structures as the pSidsToDisable parameter of CreateRestrictedToken. If you do not want to disable any trustees in your new token, you should pass zero for the dwDisableSidCount and NULL for the pSidsToDisable parameter.

The dwDeletePrivilegeCount and pPrivilegesToDelete parameters of CreateRestrictedToken work similarly to the "disabled SID" parameters, except that pPrivilegesToDelete points to an array of LUID_AND_ATTRIBUTES structures. As with disabled SIDs, passing zero and NULL for dwDeletePrivilegeCount and pPrivilegesToDelete is appropriate when you don't want to delete any privileges. For a detailed discussion of the LUID_AND_ATTRIBUTES structure, refer to the section "Adjusting a Token's Privileges" earlier in this chapter.

The dwRestrictedSidCount and pSidsToRestrict parameters represent the count and the array of the trustees that you want to add as "restricted SIDs" to the new token, respectively. You should use the same rules applied to dwDisableSidCount and pSidsToDisable to build your restricted trustee list. Remember that you are not required to include any restricted SIDs in your new token. If no restricted SIDs are desired, pass zero for the dwRestrictedSidCount parameter.

The difference between the disabled SIDs array that you pass to CreateRestrictedToken and the restricted SIDs array is that with restricted SIDs the function does not ignore trustees that do not exist in the original token. In fact, you will often include trustees not included in the original token to further restrict access checks.

The last parameter of CreateRestrictedToken, named phNewTokenHandle, points to a HANDLE variable, which receives a handle to the new, restricted token.

CreateRestrictedToken is a powerful function allowing you flexible restriction of existing tokens. Consider, for example, the following scenario, which illustrates this flexibility. Imagine that you wanted to secure a group of objects for which you explicitly allow or deny users certain access, in a somewhat unorthodox manner. You want to restrict access to some objects only on Tuesdays, regardless of what the typical access is for this object. You can take the following steps to implement this functionality without undermining the typical non-Tuesday access to the objects. Here are the administrative tasks:

  1. Create a user account named Tuesday for the sole purpose of adding restrictions to securable objects.
  2. Modify the objects' DACLs to include the restrictions desired on Tuesdays. Assign these access-denied ACEs to the SID of the Tuesday account.

Here are the server tasks:

  1. When a user connects to your server, use the GetSystemTime function to determine whether it is Tuesday.
  2. If it is Tuesday, rather than use the impersonation token for the user, create a restricted token before executing code on behalf of the client.
  3. Build a list of restricting SIDs that matches the groups in the source token, and include the user SID for the token. Additionally include in the list of restricting SIDs an entry for the Tuesday trustee.
  4. Impersonate the new restricted token using ImpersonateLoggedOnUser.

Using this process you can easily enforce additional restrictions without requiring a change to the access control of all of your secured objects every Tuesday.

The TokenMaster sample application allows you to retrieve a token and then create a restricted version of the token. You can use this restricted version to launch applications. This can be a very useful tool in furthering your understanding of restricted tokens.

After reading this chapter, you are familiar with tools and techniques that allow your software to maintain and manage a sense of identity in a flexible manner that is consistent with the Windows access control model. Your software will greatly benefit from your understanding of the token as the system's way of enforcing user context. Your software will also greatly benefit from your knowledge of impersonation, which allows you to act on behalf of your client. (Chapter 12 takes this topic to the next level with the SSPI.) The restricted token is another powerful feature you can use in secure projects that require a great deal of flexibility in their access control.

The better you understand the features discussed in this chapter, as well as the capabilities and features covered in the last two chapters, the better you will be able to design software that makes security work for you.



Programming Server-Side Applications for Microsoft Windows 2000
Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Programming)
ISBN: 0735607532
EAN: 2147483647
Year: 2000
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net