Active Directory: Leading Spaces in Names
Introduction
It should be rare to find objects in Active Directory with names that have a leading space. They cannot be created in ADUC, but can be created in a script. Such objects are difficult to work with. In fact, it is hard to even find them. The issue was raised in the following TechNet Windows Server forum thread Unable to add AD user as a manager, told the object cannot be found.
The leading space can be in the RDN (the "Relative Distinguished Name") of the object, in the sAMAccountName (the "pre-Windows 2000" name), or both. If you suspect you have such objects, this Wiki article can help.
Possible Reasons to Have Objects with Leading Spaces in the Name
Objects with leading spaces in the name may have been created for the following reasons:
- To take advantage of the fact that such objects are difficult to find.
- To obscure the name when the object is seen in ADUC, since the leading space is easy to miss.
- By mistake.
- To make a user appear first alphabetically in ADUC.
However, there are better ways to hide objects in Active Directory. See the links below in the "Other Resources" and "See Also" sections for details.
One complication with leading spaces in distinguished names is that they must be escaped in scripts and code. Leading spaces must be escaped in any component of distinguished names using the backslash ("\) escape character. Characters that must be escaped are documented in Active Directory: Characters to Escape.
In Active Directory Users and Computers
The Active Directory Users and Computers (ADUC) dialog strips off leading spaces when searching or filtering. This means you have to know something else about the object name to find it, unless you use an LDAP syntax filter. Also, objects with a leading space in the Name cannot be created in ADUC (or even in ADSI Edit). They can only be created in a script or in code.
Filtering in ADUC
For example, in the image below "Filter Options..." is selected on the "View" menu of ADUC. An attempt will be made to find a user whose sAMAccountName starts with a leading space.
Next, "Create custom" is selected and the "Customize..." button is clicked.
Then the "Advanced" tab is selected.
And finally, an LDAP filter is entered and the "OK" button is clicked. In this case, the filter is for all users where the sAMAccountName starts with a space character. LDAP recognizes the two character ASCII hexadecimal equivalent of the space character, which is "20", but it must be escaped with the backslash escape character. No other dialog in ADUC recognizes this. The "*" character is the wildcard character. So the LDAP syntax filter is "(sAMAccountName=\20*)". A similar LDAP syntax filter can be used to find users where the Name (the value of the cn or Name attribute) begins with a space. Then the LDAP syntax filter would be "(Name=\20*)".
After you click the "OK" button, only the objects that match the LDAP syntax filter appear in the ADUC. But you still must look in each OU and container to find them.
Selecting a Manager for a User
Below are the properties of a user in ADUC. On the "Organization" tab the "Change..." button is clicked to select the Manager for this user.
Now " fred" (notice the leading space) is entered to find users with that string in the name, and "Check Names" is clicked. There is no option to enter an LDAP syntax filter, and this dialog does not recognize "\20". Notice also that it is necessary to know something about the user beside the fact that the RDN begins with a space. If just the space character is entered, it gets stripped off and nothing results.
The result when "Check Names" is clicked is all users where the RDN either starts with "fred" (without the leading space), or where the string " fred" (with the leading space) appears anywhere in the RDN. The object desired is found, but so are several others. The results are exactly the same if the query uses the string "fred", with no leading space.
Note that users that have the string "fred" do not show up unless the RDN begins with this string. For example, a user named "Alfred Jones" (which exists in the domain) is not included in the list. However, the results are not consistent. In other cases, names starting with a specified string can be found, but similar names with a leading space never show up, no matter what string is used.
In the next image, the string " amy" is entered to find a different user, the one with RDN " Amy Tuttle". Again, it is necessary to know something about the user name other than the leading space.
The image below shows the result. No objects were found, even though " Amy Tuttle" exists in the domain.
The explanation is unknown. The results are the same when the string "amy" (without the leading space) is used. This is difficult to explain.
Below the "Advanced" tab is used to search for any users with a Name that starts with " amy".
Again, there are no results. The user " Amy Tuttle" cannot be found in this dialog. This behavior is not consistent, so the problem is not understood.
If you want to search your domain for managers, and document the relationships between managers and direct reports, you can use the following PowerShell script: Document Active Directory Organization. This script will find all managers and direct reports, even if their names have a leading space, and show the hierarchical structure of your organization.
Adding Members to a Group
The situation is exactly the same when you search for objects to make them members of a group. Once you click "Add..." on the "Members" tab of a group to add a new member, the dialogs are identical to those above. Finding objects with leading spaces in the name to add to a group is equally difficult.
Example LDAP and PowerShell Syntax Filters
You can use LDAP filters with VBScript, the dsquery command line tool, or PowerShell scripts to find objects in Active Directory. PowerShell syntax filters can be used in PowerShell with the AD module cmdlets, such as Get-ADUser or Get-ADObject. The table below documents the result with several example filters.
LDAP Filter | PowerShell Filter | Result |
"(Name= *)" | {Name -Like {Name -Like " *"} | All objects |
"(Name=* fred*)" | {Name -Like "* fred*"} | All objects with " fred" anywhere in the Name |
"(Name= fred*)" | {Name -Like " fred*"} | All objects starting with "fred", but not with leading space |
"(Name=*fred*)" | {Name -Like "*fred*"} | All objects with "fred" anywhere in the Name |
"(Name=\ fred*)" | {Name -Like "\ fred*"} | Nothing |
"(distinguishedName=\ *)" | {distinguishedName -Like "\ *"} | Nothing |
"(Name=\20*)" | {Name -Like "\20*"} | Only objects with leading space in Name |
"(sAMAccountName= *)" | {sAMAccountName -Like " *"} | All objects with sAMAccountName |
"(sAMAccountName<=!)" | {sAMAccountName -le "!"} | All objects with sAMAccountName starting with "!" or less |
"(sAMAccountName=\20*)" | {sAMAccountName -Like "\20*"} | Only objects with leading space in sAMAccountName |
In the second to last row of the above table, less than or equal to "!" means lexicographically less than or equal to "!". This means that the ASCII hexadecimal representation of the leading character is less than or equal to 21. This includes the "!" character, the space character, and several non-keyboard characters.
When the "Result" column in the above table is red the filter returns nothing, or all objects, or does not return objects with leading spaces in the name. No error is raised. If the "Result" column is orange, objects with leading spaces in the name are retrieved, but so are other objects (sometimes a great many others). Only the filters where the "Result" column is green will retrieve objects with leading spaces in the name, and no others. Obviously, the trick is to specify the two character ASCII hexadecimal representation of the space character, escaped with the backslash character, followed by the wildcard character. This works whether you use an LDAP or a PowerShell filter.
Example Scripts
Below are two examples using the dsquery command line tool and LDAP syntax filters. The first command finds all objects where the sAMAccountName has a leading space. The second finds all objects where the RDN has a leading space.
dsquery * -Filter "(sAMAccountName=\20*)"
dsquery * -Filter "(Name=\20*)"
If you want to restrict the results to the user, group, or any other class of objects, you must AND the appropriate clauses. Below are four PowerShell commands using the Get-ADUser cmdlet. The first two find users where the sAMAccountName has a leading space, first using an LDAP syntax filter, then a PowerShell syntax filter. The next two statements find users where the RDN has a leading space.
Get-ADUser -LDAPFilter "(sAMAccountName=\20*)"
Get-ADUser -Filter {sAMAccountName -Like "\20*"}
Get-ADUser -LDAPFilter "(Name=\20*)"
Get-ADUser -Filter {Name -Like "\20*"}
Finally, below is a VBScript program using an LDAP syntax filter to find users where the sAMAccountName has a leading space. The filter for finding users where the RDN has a leading space is commented out.
Option Explicit
Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strDN
' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"
' Filter on user objects where sAMAccountName has a leading space.
strFilter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=\20*))"
' Filter on user objects where Name has a leading space.
' strFilter = "(&(objectCategory=person)(objectClass=user)(Name=\20*))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName"
' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 200
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
' Run the query.
Set adoRecordset = adoCommand.Execute
' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
' Retrieve values and display.
strDN = adoRecordset.Fields("distinguishedName").Value
Wscript.Echo strDN
' Move to the next record in the recordset.
adoRecordset.MoveNext
Loop
' Clean up.
adoRecordset.Close
adoConnection.Close
See Also
- Active Directory: Characters to Escape
- Active Directory: LDAP Syntax Filters
- Wiki: Active Directory Domain Services (AD DS) Portal
- How to Hide Objects in Active Directory from Specific Users
- Active Directory: Requirements For Creating Objects
- Controlling Object Visibility – Deny List Content
Other Resources
- Unable to add AD user as a manager, told the object cannot be found (Windows Server Forum thread)
- Hiding Data in Active Directory
- Hiding Active Directory Objects and Attributes
- Document Active Directory Organization (PowerShell script)