WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

wNT
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

SID values - AD - round tripping and ADMT


Here's some information that probably ought to go into the NT extender help file as well as in the tech support db. It's of interest to anybody who's dealing with accounts that have been migrated into AD via the ADMT utility, as well as with accounts that have been moved between domains within AD.

All security in the Windows NT platform family, which includes WinNT v3.x, WinNT v4.x, Win2K, WinXP, Win2K3 and the upcoming "Vista", is implemented thru a construct known as a SD [Security Descriptor]. An SD can be applied to any securable object in the operating system, such as folders & files, registry keys, named piped, printers, file shares, printer shares and even processes & threads. The same mechanism is used to secure access to objects and their attributes in Active Directory.

A SD contains something called a DACL [Discretionary Access Control List], which is commonly known as the "permissions". If you've used the wntAccess*() functions in the NT extender, you've interrogated and/or manipulated the DACL on various objects in the operating system.

A DACL, in turn, is a list of ACEs [Access Control Entries]. Each ACE identifies a security principle and the type of access that is being granted or denied.

A security principle is a user or a group, and although we commonly refer to these accounts by their names, every account has a SID [Security IDentifier] and it is the SID value that is stored in an ACE.

Every SID is a unique value, is internally stored in a binary format, but is also capable of being represented as a string. SID values expressed as strings begin with the letter "S" followed by a series of numbers separated by dashes "-". The very last portion of the SID - the last group of numbers after the final "-" - is known as a RID [Relative IDentifier]. The portion of the SID before the RID component belongs to the domain in which the account exists, or it belongs to the computer itself if the account is a local account on workstation or server that isn't a domain controller. The RID is unique within the domain or on the local computer, but RID values may be duplicated across domains or across computers. It is the combination of the base portion of the SID with the RID that results in the complete SID being unique. If an account is deleted and a new one is created with the same name, the old & new accounts would have different SID values since RID values are not recycled within a domain.

The wntLsaPolGet() function with the "PrimaryDomain" and "AccountDomain" classes specified can be used to retrieve the base SID value for the domain or local computer. The wntAcctInfo() function can be used to convert an account name to a SID and vice-versa.

Now, here's where things go "wonky":

In the traditional NT domain environment, any given account's SID was a constant unique value. In the world of Active Directory, this isn't always true. AD allows for accounts to be migrated into AD from legacy NT domains. AD also allows for accounts to be moved around between domains within an AD forest. Since each domain has it's own base SID value, and each account requires a unique SID in order for security to function properly, migrating accounts into AD or moving them between domains results in the accounts being given new SID values. In order for all of the "legacy" security settings to continue to function properly, however, it is also necessary that the user's previous SID values be retained for reference purposes.

The end result of all this fudging of SID values is that instead of there being a 1::1 relationship between account names & SID values, there is now a 1::many relationship between any given account and a set of SID values. Any given account is guaranteed to have a single primary SID value that is unique. Any given account may have one or more historical SID values that are also unique and which at previous times in the past have been the account's primary SID value.

A problem can occur if programmers continue to assume that there's a 1::1 relationship between account names and SID values. Previously, you could always take a SID value, convert to an account name and then back to a SID value such that the original SID and computed SID value are the same. With historical SID values in AD, converting a historical SID value into an account name works in that it does retrieve the appropriate account name that the historical SID is associated with. However, converting that account name into a SID value will always result in obtaining the account's current SID value. This means that the original SID value won't "round trip" back to itself during the SID -> name -> SID conversion. Any code that is dependent upon such "round trip" behavior may malfunction when historical SID values are being used.

Deleted accounts introduce a related problem where you may have a SID value from a deleted domain account present as a member of a local group, or, you may have NTFS file system security or registry key security settings that contain SID values for deleted global accounts or deleted local accounts. Again, the SID will fail to "round trip" since the attempt to convert it into an account name will fail.

When attempting to interrogate or manipulate security settings via SID values, it is important to keep the above mentioned concepts & caveats in mind so that you don't fall into the trap of incorrectly handling the presence of historical SID values or SIDs that belong to deleted accounts.

A recent fix to the NT extender addresses some problems in the wntMemberDel() & wntMemberSet() functions that were caused due to the above mentioned issues. Specifically, the underlying API functions for management of global groups are different from the ones used to manage local groups. There was a condition that could occur where a user-supplied SID value was passed in as group member parameter and the extender was attempting to convert it into an account name and back into a SID value again before doing the member del/set operation. This problem only affected local groups, and only local groups can end up with orphaned SID values as members of them. Global groups get "tidied up" a bit in that when a member of a global group is deleted from the domain, all group membership lists that contained the deleted member get cleaned up and so there's orphaned SID members in global groups.


If you use LDAP or the ADSI COM interfaces [which in turn use LDAP] to access AD, you interact with it with significantly more control & functionality than if you try to access AD via the legacy NT domain interfaces. In the case of the historical SID values, the legacy NT domain interfaces do not expose any functionality that allows you to directly work with historical SID values. In fact, the NT domain interfaces somewhat mask the presence of historical SID values so that legacy applications that aren't AD-aware continue to function as well as possible when a domain is part of AD.

Given that the NT extender is using those NT domain interfaces, there are some types of information in AD that the extender won't be able to directly access, or which it won't be able to access with full awareness of the nature of the information. For example, a SID's historical nature can be inferred from the fact that the SID value converts to an account name but does not "round trip" back to its same value. Using ADSI or LDAP, you could directly access the SID history attribute of a user and determine that a SID is a historical SID value. Likewise, universal groups in AD don't have a counterpart in the legacy NT domain model, so there's no way to directly differentiate between a domain global group and a universal group with the NT extender.

Also of interest is the fact that there are certain types of ACEs that can be placed in DACLs & SACLs where the security principle is identified not by a SID value, but instead by a GUID value. These are object-specific types of ACEs, and although they've been a part of the SD [Security Descriptor] definition since Win2K was released, their use in the security settings on folders, files & registry keys is almost never observed. However, they do exist and currently the NT extender cannot report on or manpiulate object-specific ACES. These types of ACEs can grant or deny specific types of access to either specific objects in AD [each object has unique GUID regardless of whether it has a SID [or not] or whether it has a SID history list [or not]. These types of ACEs can also be used to grant or deny access to entire classes of objects based on the GUID of the object's base class in AD. A future update to the NT extender will provide support for object-specific ACEs.

Another aspect of AD that the NT domain interfaces are not aware of is the nesting of group memberships at the domain level. In the NT domain view of security, local groups can have local users, domain users & domain global groups as members, while domain global groups may only have domain users as members. In the AD view of domain security, domain global groups may also have other domain global groups as members. The NT domain interfaces are not aware of this fundamental change so listing the members of a domain global group via the NT extender may not provide the same results as listing a domain global group's membership list via the ADSI extender.


Article ID:   W17067
File Created: 2007:07:03:14:28:04
Last Updated: 2007:07:03:14:28:04