joeware - never stop exploring... :)

Information about joeware mixed with wild and crazy opinions...

sAMAccountName is always unique in a Windows domain… or is it?

by @ 7:33 pm on 1/4/2012. Filed under tech

So while chatting with an admin this week he mentioned that his company synced data from their single domain forest into an external database with a primary key of sAMAccountName. This was a topic of interest for him because they had just learned it was possible to have two different objects in Active Directory with the same sAMAccountName value. They learned this little known but important piece of information through direct experience as it actually happened to them. When something like that happens, it kind of messes with any external systems that are using sAMAccountName as a unique key causing varying levels of chaos and disaster and really isn’t all that great for the AD Admins either because it is likely to cause some level of authentication issues for whomever is duplicated.

I know what you are thinking, "but joe… while SAM Names aren’t unique within a multi-domain forest,  they are supposed to be unique within a domain!!!" And that is absolutely correct, they are *supposed* to be unique in a domain[1]. That is, however, a far cry from being guaranteed to be unique.  What’s the difference you ask? The difference is this… If something is supposed to be unique, some decent but reasonable amount of work will be put into play to produce a method that will be used to try to reach a state where you are generally going to have a unique value. If something is guaranteed to be unique, whatever amount of work is necessary to assure that there is no way you can duplicate values no matter what you do is used instead. The sAMAccountName attribute falls squarely into the *supposed* to be unique category.  Microsoft gives it the old college try to work towards uniqueness but don’t go whole hog and absolutely make sure it isn’t possible.

Those of us who have been around since the NT4 days or perhaps those who do a lot of work with the SAM DB on non-domain controllers (member servers, standalone servers, and client machines) are quite used to and expectant of the ability to have unique sAMAccountNames. Since you have but a single SAM DB (aka a portion of the registry) that can be updated at any given moment, that SAM DB is going to be able to enforce uniqueness. Once we moved into the world of Active Directory and a loosely consistent multi-master replication model things changed and the lines blurred a little.

Creating objects with duplicate sAMAccountName attributes method 1 – loosely consistent multi-master replication

The first method to produce objects with duplicate sAMAccountNames that cropped up, a side effect really of the new cool "loosely consistent" replication engine coupled with the multi-master approach to directories, was the day Windows 2000 was released. As soon as you have more than one domain controller for a given domain, you have the ability to create objects that break the uniqueness rule for sAMAccountName. It is quite simple to accomplish, you simply create an object on two different domain controllers inside of the replication convergence period for those DCs. If the DCs are in the same site, that means you have seconds or possibly minutes for convergence, if the DCs are in different sites then you could have hours or days to accomplish the task.

For example, you take a simple script like

admod -hh joeware-dc1 -add -b cn=testcase1,ou=usersample,dc=joeware,dc=local objectclass::user samaccountname::testcase1
admod -hh joeware-dc2 -add -b cn=testcase1,ou=test,dc=joeware,dc=local objectclass::user samaccountname::testcase1

and run it and it is pretty likely you will generate two different user objects with the same sAMAccountName after replication convergence. Like so:

C:\temp>adfind -default -f name=testcase1

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: JOEWARE-DC1.joeware.local:389
Directory: Windows Server 2003
Base DN: DC=joeware,DC=local

dn:CN=testcase1,OU=usersample,DC=joeware,DC=local
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase1
>distinguishedName: CN=testcase1,OU=usersample,DC=joeware,DC=local
>instanceType: 4
>whenCreated: 20120103220701.0Z
>whenChanged: 20120103220701.0Z
>uSNCreated: 1011021
>uSNChanged: 1011022
>name: testcase1
>objectGUID: {85FF63EE-EF50-4EDB-8414-445ECEBB320A}
>userAccountControl: 546
>badPwdCount: 0
>codePage: 0
>countryCode: 0
>badPasswordTime: 0
>lastLogoff: 0
>lastLogon: 0
>pwdLastSet: 0
>primaryGroupID: 513
>objectSid: S-1-5-21-3641047700-3957557241-2644433309-7689
>accountExpires: 9223372036854775807
>logonCount: 0
>sAMAccountName: testcase1
>sAMAccountType: 805306368
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local

dn:CN=testcase1,OU=test,DC=joeware,DC=local
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase1
>distinguishedName: CN=testcase1,OU=test,DC=joeware,DC=local
>instanceType: 4
>whenCreated: 20120103220702.0Z
>whenChanged: 20120103220717.0Z
>uSNCreated: 1011023
>uSNChanged: 1011023
>name: testcase1
>objectGUID: {8C815AFB-42E1-4A0F-84AD-D0ABC0228F88}
>userAccountControl: 546
>codePage: 0
>countryCode: 0
>pwdLastSet: 0
>primaryGroupID: 513
>objectSid: S-1-5-21-3641047700-3957557241-2644433309-8111
>accountExpires: 9223372036854775807
>sAMAccountName: testcase1
>sAMAccountType: 805306368
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local

2 Objects returned

 

"but joe… what about the collision detection logic?"

admod -hh joeware-dc1 -add -b cn=testcase3,ou=usersample,dc=joeware,dc=local objectclass::user samaccountname::testcase3
admod -hh joeware-dc2 -add -b cn=testcase3,ou=usersample,dc=joeware,dc=local objectclass::user samaccountname::testcase3

C:\temp>adfind -default -f name=testcase3*

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: JOEWARE-DC1.joeware.local:389
Directory: Windows Server 2003
Base DN: DC=joeware,DC=local

dn:CN=testcase3,OU=usersample,DC=joeware,DC=local
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase3
>distinguishedName: CN=testcase3,OU=usersample,DC=joeware,DC=local
>instanceType: 4
>whenCreated: 20120103221530.0Z
>whenChanged: 20120103221530.0Z
>uSNCreated: 1011039
>uSNChanged: 1011040
>name: testcase3
>objectGUID: {DFA20362-6899-41F6-94F2-3B7D5924FB41}
>userAccountControl: 546
>badPwdCount: 0
>codePage: 0
>countryCode: 0
>badPasswordTime: 0
>lastLogoff: 0
>lastLogon: 0
>pwdLastSet: 0
>primaryGroupID: 513
>objectSid: S-1-5-21-3641047700-3957557241-2644433309-7691
>accountExpires: 9223372036854775807
>logonCount: 0
>sAMAccountName: testcase3
>sAMAccountType: 805306368
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local

dn:CN=testcase3\0ACNF:c928020b-f156-4e08-8e87-314eb8817a2a,OU=usersample,DC=joeware,DC=local
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase3\0ACNF:c928020b-f156-4e08-8e87-314eb8817a2a
>distinguishedName: CN=testcase3\0ACNF:c928020b-f156-4e08-8e87-314eb8817a2a,OU=usersample,DC=joeware,DC=local
>instanceType: 4
>whenCreated: 20120103221530.0Z
>whenChanged: 20120103221546.0Z
>uSNCreated: 1011041
>uSNChanged: 1011041
>name: testcase3\0ACNF:c928020b-f156-4e08-8e87-314eb8817a2a
>objectGUID: {C928020B-F156-4E08-8E87-314EB8817A2A}
>userAccountControl: 546
>codePage: 0
>countryCode: 0
>pwdLastSet: 0
>primaryGroupID: 513
>objectSid: S-1-5-21-3641047700-3957557241-2644433309-8113
>accountExpires: 9223372036854775807
>sAMAccountName: testcase3
>sAMAccountType: 805306368
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local

2 Objects returned

As you can clearly see, collision logic absolutely works for duplicated RDNs… but there is nothing around checking for duplication of sAMAccountName when replicating in objects from another DC. The only check in place for duplicate sAMAccountName attributes is on object instantiation when the SAM Rules code is called to validate the attribute settings for a given object.

 

Creating objects with duplicate sAMAccountName attributes method 2 – tombstone reanimation

The second method for creating objects with duplicate sAMAccountName attributes surfaced, again as a side effect, in Windows Server 2003 with the release of the new tombstone reanimation functionality. This is the functionality that gave you a basic object "undelete" capability in Active Directory. Prior to 2003 if you deleted something and needed it back, well you better have functioning backups. With Windows Server 2003 the AD team gave us the ability to recover the tombstones so they could be used again (YEAH![2]). This functionality is not all that well known and even some of the people who know about it don’t really know how to accomplish it so in most shops this method for duplicating the sAMAccountName attribute is not as likely[3].

So for example, here I will create a user object, delete it, create another user object with the same SAM Name and then recover the original user object’s tombstone.

C:\>admod -b CN=testcase5,CN=Users,DC=k8r2dom,DC=loc -add objectclass::user samaccountname::testcase5

AdMod V01.16.00cpp Joe Richards (joe@joeware.net) March 2011

DN Count: 1
Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2

Adding specified objects…
   DN: CN=testcase5,CN=Users,DC=k8r2dom,DC=loc…

The command completed successfully

C:\>adfind -showdel -default -f name=testcase5* samaccountname

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase5,CN=Users,DC=k8r2dom,DC=loc
>sAMAccountName: testcase5

1 Objects returned

C:\>adfind -default -f name=testcase5* -dsq | admod -del

AdMod V01.16.00cpp Joe Richards (joe@joeware.net) March 2011

DN Count: 1
Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2

Deleting specified objects…
   DN: CN=testcase5,CN=Users,DC=k8r2dom,DC=loc…

The command completed successfully

C:\>admod -b CN=testcase5,ou=testou,DC=k8r2dom,DC=loc -add objectclass::user samaccountname::testcase5

AdMod V01.16.00cpp Joe Richards (joe@joeware.net) March 2011

DN Count: 1
Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2

Adding specified objects…
   DN: CN=testcase5,ou=testou,DC=k8r2dom,DC=loc…

The command completed successfully

C:\>adfind -showdel -default -f name=testcase5* samaccountname

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase5,OU=testOU,DC=k8r2dom,DC=loc
>sAMAccountName: testcase5

dn:CN=testcase5\0ADEL:9a4e0a1f-4498-4ef3-aa1e-76bf0c69c61e,CN=Deleted Objects,DC=k8r2dom,DC=loc
>sAMAccountName: testcase5

2 Objects returned

C:\>adfind -showdel -default -rb "cn=deleted objects" -f name=testcase5* -dsq | admod -undel

AdMod V01.16.00cpp Joe Richards (joe@joeware.net) March 2011

DN Count: 1
Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2

Undeleting specified objects…
   DN: CN=testcase5\0ADEL:9a4e0a1f-4498-4ef3-aa1e-76bf0c69c61e,CN=Deleted Objects,DC=k8r2dom,DC=loc…

The command completed successfully

C:\>adfind -showdel -default -f name=testcase5

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase5,CN=Users,DC=k8r2dom,DC=loc
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase5
>distinguishedName: CN=testcase5,CN=Users,DC=k8r2dom,DC=loc
>instanceType: 4
>whenCreated: 20120104214547.0Z
>whenChanged: 20120104214802.0Z
>uSNCreated: 498225
>uSNChanged: 498257
>name: testcase5
>objectGUID: {9A4E0A1F-4498-4EF3-AA1E-76BF0C69C61E}
>userAccountControl: 546
>badPwdCount: 0
>codePage: 0
>countryCode: 0
>badPasswordTime: 0
>lastLogoff: 0
>lastLogon: 0
>pwdLastSet: 0
>primaryGroupID: 513
>operatorCount: 0
>objectSid: S-1-5-21-1767008341-141532995-3086693677-62124
>adminCount: 0
>accountExpires: 0
>logonCount: 0
>sAMAccountName: testcase5
>sAMAccountType: 805306368
>lastKnownParent: CN=Users,DC=k8r2dom,DC=loc
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=k8r2dom,DC=loc
>dSCorePropagationData: 20120104214802.0Z
>dSCorePropagationData: 16010101000000.0Z

dn:CN=testcase5,OU=testOU,DC=k8r2dom,DC=loc
>objectClass: top
>objectClass: person
>objectClass: organizationalPerson
>objectClass: user
>cn: testcase5
>distinguishedName: CN=testcase5,OU=testOU,DC=k8r2dom,DC=loc
>instanceType: 4
>whenCreated: 20120104214650.0Z
>whenChanged: 20120104214650.0Z
>uSNCreated: 498237
>uSNChanged: 498238
>name: testcase5
>objectGUID: {05C87B3D-DFED-4740-9E6E-7F82BC499F82}
>userAccountControl: 546
>badPwdCount: 0
>codePage: 0
>countryCode: 0
>badPasswordTime: 0
>lastLogoff: 0
>lastLogon: 0
>pwdLastSet: 0
>primaryGroupID: 513
>objectSid: S-1-5-21-1767008341-141532995-3086693677-62125
>accountExpires: 9223372036854775807
>logonCount: 0
>sAMAccountName: testcase5
>sAMAccountType: 805306368
>objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=k8r2dom,DC=loc
>dSCorePropagationData: 16010101000000.0Z

2 Objects returned

C:\>

As you can see, we once again have two user objects in the same domain with the same sAMAccountName attribute values. A good argument could be put together that perhaps a validation of the SAM Name should be made in this case but like with replication, it just wasn’t something they wanted to put the extra work into as, again like replication, it is a pretty small edge case.

 

$DUPLICATE-<hexchars> for sAMAccountName???

"Ok joe… so while I don’t like it, it makes sense, but I swear I have seen $DUPLICATE-<hexchars> for a user or (more likely) computer objects in AD before so I thought that there was conflict resolution to handle these things for sAMAccountName like RDNs and (effectively) DNs???"

Yes it is definitely possible you saw this, but that conflict resolution did not occur during either of the processes above. It occurred later when someone tried to create yet another new object with the duplicated name or when someone tries to authenticate using the duplicated SAM Name.

Example 1 – creating a new object with the same duplicated SAM Name

C:\>admod -b CN=testcase5,cn=computers,DC=k8r2dom,DC=loc -add objectclass::user samaccountname::testcase5

AdMod V01.16.00cpp Joe Richards (joe@joeware.net) March 2011

DN Count: 1
Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2

Adding specified objects…
   DN: CN=testcase5,cn=computers,DC=k8r2dom,DC=loc…: [K8R2Dom-DC1.k8r2dom.loc] Error 0x44 (68) – Already Exists

ERROR: Too many errors encountered, terminating…

The command did not complete successfully

C:\>adfind -showdel -default -f name=testcase5 samaccountname

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase5,CN=Users,DC=k8r2dom,DC=loc
>sAMAccountName: $DUPLICATE-f2ac

dn:CN=testcase5,OU=testOU,DC=k8r2dom,DC=loc
>sAMAccountName: testcase5

2 Objects returned

 

Example 2 – trying to authenticate to the duplicated SAM Name

C:\>adfind -showdel -default -f name=testcase1 samaccountname

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase1,CN=Users,DC=k8r2dom,DC=loc
>sAMAccountName: testcase1

dn:CN=testcase1,OU=testOU,DC=k8r2dom,DC=loc
>sAMAccountName: testcase1

2 Objects returned

C:\>adfind -default -s base -dn -u k8r2dom\testcase1 -p password -exterr

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

LDAP_BIND: [] Error 0x31 (49) – Invalid Credentials
Extended Error: No extended error info available.
Terminating program.

C:\>adfind -showdel -default -f name=testcase1 samaccountname

AdFind V01.45.00cpp Joe Richards (joe@joeware.net) March 2011

Using server: K8R2Dom-DC1.k8r2dom.loc:389
Directory: Windows Server 2008 R2
Base DN: DC=k8r2dom,DC=loc

dn:CN=testcase1,CN=Users,DC=k8r2dom,DC=loc
>sAMAccountName: $DUPLICATE-f2aa

dn:CN=testcase1,OU=testOU,DC=k8r2dom,DC=loc
>sAMAccountName: testcase1

2 Objects returned

 

This concludes this blog post. I hope that it was informative and I hope to bring a lot more like this to the blog again this year. Once again I apologize for my relative absence last year. :)

 

   joe

 

 

[1] This is obviously about Active Directory Domain Services, ADAM or ADLDS can have duplicate sAMAccountName attributes all day assuming you have sAMAccountName defined in the schema. There is absolutely NOTHING in place to assure or guarantee anything for it.

[2] Anything that helps me avoid authoritative restores is a YEAH! type of thing. :)

[3] The main reason for the lack of knowing is likely that Microsoft never produced any kind of "reanimate" GUI interface which effectively prevented some 90% of the Windows admins out there from ever knowing about it and probably even more from using it. A second "strike", if you will, was that a tombstone object didn’t normally have all of the attributes that were populated on the object prior to deletion so even if you knew how to perform the reanimation, you may end up performing a restore of the object anyway to get all of the info for the object. Now if you knew about the functionality and you knew how to take advantage of it it likely was very useful for you when absolutely needed and you didn’t want to fuss around with an authoritative restore (again [2]). Of course now we have recycle bin so we are many steps beyond tombstone reanimation now (or have the capability to be…) but in terms of this blog post, tombstone reanimation gave us a new method to duplicate a sAMAccountName.

Rating 4.40 out of 5

One Response to “sAMAccountName is always unique in a Windows domain… or is it?”

  1. Mike Kline says:

    Talk about coming back with a bang…nice job Joe!! I knew this was a keeper when I had to go through it a couple times to make sure I took it all in :)

[joeware – never stop exploring… :) is proudly powered by WordPress.]