Showing posts with label AD LDS / ADAM. Show all posts
Showing posts with label AD LDS / ADAM. Show all posts

Wednesday, September 14, 2011

ADAMSync Error -2146893813. Error code: 317

Today I discovered what may be a bug in ADAMSync, however I found a workaround. Let me go into detail sharing my findings with you. First... lets cover off my environment.

I have 4 forests, 10 domains. My AD LDS server is a member of subdomain.forest3.lan. Please see the diagram below.



- My LDS Server has multiple instances "LDS Databases" for each Active Directory domain. These instances are listening on 10001, 10002, 10003, 10004 etc... There is a 1 to 1 relationship between a single domain and its corresponding LDS instance.

- Each LDS Instance has only one application partition with the same distinguishedName mapping an Active Directory domain. For example dc=forest2,dc=lan or dc=bu2,dc=forest1,dc=lan.

- My ADAMSync configuration in each instance replicates the user class objects from Active Directory to "userProxy" class objects in each LDS Instance. Objects are successfully replicating.

- userProxy bind redirection is working successfully for all LDS Instances and the corresponding Active Directory domain (excluding forest4.lan due to no domain trusts existing). For more information on userProxy objects see http://clintboessen.blogspot.com/2011/04/userproxy-class-and-adam-lds.html

- There is no synchronization errors. I have validated all attributes declared in my adamsync.xml file are successfully synchronizing to the corresponding userProxy object in LDS for each user account.

- ADAMSync is successfully creating the same Organisational Unit structure matching that of LDS.

- The base distinguishedName of each LDS instance matches the base distinguishedName of the Active Directory domain.

- All child domains in forest1 synchronise using an ldapquery account located in the parent forest1.lan domain. This is configured in the XML file ldapquery and forest1.lan.

- forest2.lan synchronises using an account in forest2.lan

- forest3.lan synchronises using an account in subdomain.forest3.lan. No user accounts reside in the root domain forest3.lan. This is configured as an "empty root domain".

- forest4.lan synchronises using an account located in forest4.lan

The following Active Directory accounts were setup to make this solution work:

- subdomain.forest3.lan\LDSSVC. This account is only a member of "domain users" in subdomain.forest3.lan. This account has "Log on as service" rights assigned under "user rights assignments" on the LDS Server. This account provides the security context under which LDS Instance runs as a service. i.e. all LDS Services run as this account.

- subdomain.forest3.lan\LDSBoss. This account is only a member of "domain users" in subdomain.forest3.lan. During the installation of each LDS Instance using the "Active Directory Lightweight Directory Services Setup Wizard" this account was specified as the Administrator of each instance. This account has no access to the LDS Server itself, i.e. the account does not even have permissions to login to the LDS Server. It only has "Administrative privilages" inside each LDS Instance. All commands which manipulate LDAP data inside an LDS Instance such as ADAMSync must be run under the security context of this LDSBoss account.

- forest1.lan\ldapquery. This account is a member of "Domain Admins" and "Enterprise Admins"in the forest1.lan root domain. It is specified in the ADAMSync.xml file for each child domain in the forest1.lan forest. This account is used to perform LDAP Queries against the forest1.lan forest. If this account is not a Domain Admin or Enterprise Admin, ADAMSync fails to run.

- forest2.lan\ldapquery. This account is a member of "Domain Admins" in the forest2.lan domain. This is specified in the ADAMSync.xml file for the forest2.lan forest. It is used for LDAP queries against forest2.lan

- subdomain.forest3.lan\ldapquery. This account is a member of "Domain Admins" in the subdomain.forest3.lan domain. This is specified in the ADAMSync.xml file for the subdomain.forest3.lan forest. It is used for LDAP queries against subdomain.forest3.lan

- forest4.lan\ldapquery. This account is a member of "Domain Admins" in the forest4.lan domain. This is specified in the ADAMSync.xml file for the forest4.lan forest. It is used for LDAP queries against forest4.lan

So whats the bug you found clint?

I went and installed my ADAMSync XML configuration file running a command prompt under the security context of the user account SUBDOMAIN\LDSBoss with the following command:

adamsync /install localhost:10001 "C:\Windows\ADAM\AdamSync Configs\SUBDOMAIN\SUBDOMAIN-AdamSyncConf.XML" /passprompt

When prompted I entered the password for the subdomain.forest3.lan\ldapquery account which was specified in the ADAMSync XML file.

When I run ADAMSync.exe using my SUBDOMAIN\LDSBoss credentials (the credentials used to install the XML configuration file), the sync works successfully.

However I then created another account called SUBDOMAIN\boessenc_admin which I added to the configuration partition "Administrators" group in my LDS Instance. When I tried to sync using my SUBDOMAIN\boessenc_admin account the sync failed with ADAMSync.exe terminating. The following error is received:

Error occured fetching internationalized message number -2146893813. Error code: 317



Problem signature:
Problem Event Name: APPCRASH
Application Name: adamsync.exe
Application Version: 6.1.7600.16385
Application Timestamp: 4a5bc94c
Fault Module Name: ntdll.dll
Fault Module Version: 6.1.7600.16695
Fault Module Timestamp: 4cc7b325
Exception Code: c0000005
Exception Offset: 0000000000023b12
OS Version: 6.1.7600.2.0.0.272.7
Locale ID: 3081
Additional Information 1: dba5
Additional Information 2: dba5cead4302f0c0fa066ea618a55f8f
Additional Information 3: f135
Additional Information 4: f135fc65c6fa056fecabbbdf82720b5f


I created a memory dump of the ADAMSync process using the following MSDN article:
http://msdn.microsoft.com/en-us/library/bb787181.aspx

I submitted this memory dump to James Li from the Microsoft Directory Service Support Team. James analysed the memory dump carefully and suspects it might be caused by a bug in AdamSync.exe. Here is the stack information he provided me with:

00 00000000`0013e990 000007fe`fd479ce9 ntdll!RtlFormatMessageEx(
unsigned short * MessageFormat = 0x00000000`00000000,
unsigned long MaximumWidth = 0,
unsigned char IgnoreInserts = 0x10 '',
unsigned char ArgumentsAreAnsi = 0x00 '',
unsigned char ArgumentsAreAnArray = 0x00 '',
char ** Arguments = 0x00000000`0013f3b0,
unsigned short * Buffer = 0x00000000`ff7fb630,
unsigned long Length = 0x26d7,
unsigned long * ReturnLength = 0x00000000`0013f174,
struct _PARSE_MESSAGE_CONTEXT * ParseContext = 0x00000000`0013f1a8)+0x272

01 00000000`0013f110 000007fe`fd479a97 KERNELBASE!BaseDllFormatMessage(
unsigned char ArgumentsAreAnsi = 0x00 '',
unsigned long dwFlags = 0x1000,
void * lpSource = 0x00000000`0013f510,
unsigned long dwMessageId = 0x13d,
unsigned long dwLanguageId = 0x400,
unsigned short * lpBuffer = 0x00000000`ff7fb630,
unsigned long nSize = 0x2710,
char ** arglist = 0x00000000`0013f3b0)+0x239

02 00000000`0013f210 00000000`77024d88 KERNELBASE!FormatMessageW(
unsigned long dwFlags = 0,
void * lpSource = 0x00000000`ff7f91b0,
unsigned long dwMessageId = 0,
unsigned long dwLanguageId = 0xff797074,
unsigned short * lpBuffer = 0x00000000`ff7fb630,
unsigned long nSize = 0x2710,
char ** lpArguments = 0x00000000`0013f3b0)+0x37

03 00000000`0013f260 00000000`ff7942d0 kernel32!FormatMessageWStub(
unsigned long dwFlags = 0x13f510,
void * lpSource = 0x00000000`00002800,
unsigned long dwMessageId = 0,
unsigned long dwLanguageId = 0x5f7f20,
unsigned short * lpBuffer = 0x00000000`ff7fb630,
unsigned long nSize = 0x2710,
char ** lpArguments = 0x00000000`0013f3b0)+0x28


I continued investigating the issue... I then reinstalled the ADAMSync XML file by re-running the ADAMSync.exe process under SUBDOMAIN\boessenc_admin using the same command, and specifying the password for the SUBDOMAIN\ldapquery which was specified in the XML configuration file:

adamsync /install localhost:10001 "C:\Windows\ADAM\AdamSync Configs\SUBDOMAIN\SUBDOMAIN-AdamSyncConf.XML" /passprompt

I then ran the ADAMSync.exe program with the sync switch under the security context of SUBDOMAIN\boessenc_admin. It worked!

What did we learn?

Whatever account you used to install the ADAMSync.exe XML configuration file, i.e. the account the ADAMSync.exe process is running as during the config installation MUST also be used to perform the ADAMSync.exe synchronisation. If you attempt to perform a synchronisation using a different account other then the account used during the XML import, the ADAMSync.exe process will crash.

Wednesday, August 10, 2011

Connecting to the configuration partition of an LDS Instance

LDS Instances like Active Directory also have a Configuration Partition and a Schema Partition. On TechNet it is documented:

By default, the security principal that you specify as the AD LDS administrator during AD LDS setup becomes a member of the Administrators group in the configuration partition.

http://technet.microsoft.com/en-us/library/cc731143.aspx

How do I get to the configuration partition in an LDS Instance?

Well if I connect to my application partition created during the LDS installation wizard and go to my Administrators, I can see nested inside is another Administrators group residing inside the Configuration Partition.



I can now connect to this using ADSIEdit.



Under the administrators group in the configuration partition I can find the account used when I installed the LDS Instance as per Microsoft documentation on TechNet.

ADAMSync Aging

In this post I will describe Aging with ADAMSync. If you configure ADAMSync to replicate your Active Directory information to an LDS Instance, without aging deleted data from Active Directory will never be removed from LDS. For example if you delete a user object from your Active Directory database, this object will not be deleted from the LDS Instance when you run the next sync.

The ADAMSync aging configuration is done under your ADAMSync XML configuration file.

<schedule>
<aging>
<frequency>0</frequency>
<num-objects>0</num-objects>
</aging>
<schtasks-cmd></schtasks-cmd>
</schedule>


The two configuration options you need to configure are frequency and num-objects.

Frequency:
http://technet.microsoft.com/en-us/library/cc737713.aspx

num-objects:
http://technet.microsoft.com/en-us/library/cc778153.aspx

Unfortunately the documentation on TechNet around these is very poor.

Frequency

- If it's set to "0", the Aging will be skipped, AdamSync will return the following informaiton:
a. Aging is skipped.
b. The times since the last sync.

- If it's larger than "0", system will compare its value with the number of times since the last sync:

a. If its value is larger than the number of times since the last sync, Aging will be skipped, and the number of the times since the last sync will be increased by 1.
b. if its value is not larger than the number of times since the last sync, Aging procedure will be called and the number of times since the last sync will be reset.

Examples:

- If the value is set to 0, aging will be not used.
- If the value is set to 1, the aging will be called each time during the sync.
- if it's set to 2, the aging will be called every two sync.

num-objects

num-objects is the number of objects that need to be aged per run. If you make this 0, it will always age all objects against Active Directory. If you make this 50, it will only age 50. When you perform the next sync, it will age the next 50. Don't worry all objects will eventually be aged... depends on how often you schedule task adamsync.exe to run!

Why was Aging developed?

Please read this fantastic article by Eric Fleischman which explains why Aging was developed by Microsoft in ADAMSync.

http://blogs.technet.com/b/efleis/archive/2006/10/28/change-visibility-in-the-directory-or-lack-there-of-aka-what-s-the-point-of-aging.aspx

Thankyou to James Li from the Directory Services Support Team at Microsoft for looking at the source code of ADAMSync.exe and explaining how the code works! This information was published with written permission from Microsoft via email.

Monday, June 20, 2011

Error 49: ldap_simple_bind_s() failed: Invalid Credentials

I have setup a Windows Server 2008 R2 server running LDS. I have an LDS Instance running on 10001 (LDAP) and 20001 (LDAPS).

I added a user account using the following:

dn: CN=testaccount,CN=Users,DC=domain,DC=ADAM
changetype: add
objectClass: user
userPrincipalName: testaccount
cn: testaccount
displayName: My Test Account
userPassword: Passw0rd


Note: As the requirement for special formatting of unicodePwd has been lifted Microsoft has placed a default requirement to ensure all password operations are done through LDAPS instead of LDAP. To allow password operations through LDAP please see:

http://clintboessen.blogspot.com/2011/06/0x2077-illegal-modify-operation-some.html

When I attempt to bind to this account using ldp.exe using "Simple Bind" over LDAP (not secure LDAP) using the following credentials I get an error:

username: CN=testaccount,CN=Users,DC=domain,DC=ADAM
password: Passw0rd

-----------
res = ldap_simple_bind_s(ld, 'CN=testaccount,CN=Users,DC=domain,DC=ADAM', ); // v.3
Error <49>: ldap_simple_bind_s() failed: Invalid Credentials
Server error: 8009030C: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 2030, v1db0
Error 0x8009030C The logon attempt failed
-----------




There were three things I needed to change to get this working.

Problem 1

I read from multiple places on the internet that by default when you associate a password to an account - the account is disabled. I also know that this error can be related to the user account being disabled - please see:

http://social.technet.microsoft.com/Forums/en-US/winserverDS/thread/44d29c43-4203-400a-bff4-c488da5c5f57/


However the attribute which sets the account password to disabled "msDS-UserAccountDisabled" was not associated with the user class object in the schema. AD LDS has a series of attributes to control a user account for items such as Account Lockout, Account Disabled, Password Never Expires, User Cannot Change Password etc. For a list of these attributes please see:

http://msdn.microsoft.com/en-us/library/aa772124.aspx

Note: Active Directory does not have these attributes, instead all these values are associated with an attribute called userAccountControl. This attribute has an integer set to it.. 512 is a normal account. To disable an account add a value of 2. In decimal, this is 514 (2 + 512). For more information on how this works in Active Directory please see: http://support.microsoft.com/kb/305144

To associate these attributes with the user class object you need to connect to the LDS Instance using the Active Directory Schema Console. If Active Directory Schema does not exist in your MMC snap-in list register it using "regsrv32 schmmgmt.dll" from command line.

Note: When connecting to your LDS Instance you cannot use localhost or it will fail. You must use the IP address of the LDS Instance. This is due to a code error in the Active Directory schema console, please see:

http://clintboessen.blogspot.com/2011/06/lds-active-directory-schema-status.html

Once connected to your LDS Instance in Active Directory Schema MMC snap-in go to the properties of the user class object and click the attributes tab.



As you see none of the msDS-User type class objects exist. Go ahead and add the following attributes:

- ms-DS-UserAccountAutoLocked

- msDS-UserAccountDisabled

- msDS-UserDontExpirePassword

- ms-DS-UserEncryptedTextPassword

- msDS-UserPasswordExpired

- ms-DS-UserPasswordNotRequired



After the attribute is added, restart your LDS Instance service and connect to the application partition in ADSIEdit containing your user account. Set the msDS-UserAccountDisabled to FALSE.



Problem 2

You must allow Simple Bind requests to an AD LDS Instance over standard LDAP. To do this connect to the configuration partition on your LDS Instance using ADSIEdit. My instance is listening on TCP 10001.



Navigate to:

CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,CN={GUID}

Open the properties of Directory Service. Open the multivalued attribute msDS-Other-Settings. Ensure RequireSecureSimpleBind is set to 0. This will ensure that both LDAP and LDAPS connections are allowed to bind authentication to the LDS Instance.



Note: RequireSecureProxyBind is for userProxy class objects which perform bind proxy redirection.

Problem 3

The third problem related to the following TechNet article:

http://technet.microsoft.com/en-us/library/cc732460.aspx

This article states:

AD LDS does not include any default security principals. However, AD LDS does provide importable schema extensions that you can use to create users in AD LDS. Users that are created from these user classes can be used as security principals. In addition, you can make any object class in the AD LDS schema a security principal by adding the msDS-bindableobject auxiliary class and the unicodePwd attribute to the schema definition of an object class. Each AD LDS security principal must be assigned an account and password, which AD LDS uses for authentication.

To do this open up ADSIEdit and connect to the Schema partition of your LDS Instance.



Navigate to the CN=User class object in ADSIEdit under the Schema partition and open its properties.



As you see the msDS-bindableobject auxiliary class does not exist.



Add it to the list and click OK.



Restart the LDS Instance under the services MMC console.

Reset the user's password by connecting to the appropriate application partition in ADSIEdit, right clicking on the user and clicking Reset Password.

I was now ale to perform a simple bind to my LDS Instance using a LDS user account.

-----------
res = ldap_simple_bind_s(ld, 'CN=SVCLDAPQuery,CN=Users,DC=domain,DC=ADAM',); // v.3
Authenticated as: 'CN=SVCLDAPQuery,CN=Users,DC=domain,DC=ADAM'.
-----------




You can also do this using an LDIF file:

dn: CN=User,CN=Schema,CN=Configuration,DC=X
changetype: Modify
add: auxiliaryClass
auxiliaryClass: msDS-BindableObject
-

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-


imported using (ignore line wraps below)

ldifde -i -f
-s : -c
"CN=Schema,CN=Configuration,DC=X" #schemaNamingContext


Thanks to Lee Fight (Directory Services MVP) who assisted me in getting this working!

Wednesday, June 15, 2011

Active Directory userAccountControl and LDS

Active Directory user accounts have an attribute called userAccountControl which is used to control items such as Account Lockout, Account Disabled, Password Never Expires, User Cannot Change Password etc. This is determined by an integer value... based on the value the system knows which options are enabled and which are disabled. The value 512 is the base value for all normal user accounts. To understand all integers that make this attribute work please refer to the following KB article.

http://support.microsoft.com/kb/305144

AD LDS (ADAM) does not support the userAccountControl attribute. Instead, AD LDS uses several individual attributes to hold the information that is contained in the flags of the userAccountControl attribute.

For a list of these attributes please refer to the following MSDN article:


http://msdn.microsoft.com/en-us/library/aa772124.aspx


Any userAccountControl flags that are not listed below are not supported by AD LDS.

0x2081 Multiple values were specified for an attribute

I'm trying to import the following LDIF file into an LDS Instance using LDIFDE.

dn: CN=SVCLDAPQuery,CN=Users,DC=testinstance,DC=ADAM
changetype: add
objectClass: user
userPrincipalName: SVCLDAPQuery
cn: Service Now LDAP Query
displayName: Service Now LDAP Query
userPassword: Passw0rd

I am performing the import with the following command:

ldifde -i -f SVCLDAPQuery.ldf -s localhost:10001

This command throws out the following errors:

Connecting to "localhost:10001"
Logging in as current user using SSPI
Importing directory from file "SVCLDAPQuery.ldf"
Loading entries.
Add error on entry starting on line 1: Invalid DN Syntax
The server side error is: 0x2081 Multiple values were specified for an attribute that can have only one value.
The extended server error is:
00002081: NameErr: DSID-03050C42, problem 2003 (BAD_ATT_SYNTAX), data 0, best match of:
'CN=SVCLDAPQuery,CN=Users,DC=testinstance,DC=ADAM'

0 entries modified successfully.
An error has occurred in the program
No log files were written. In order to generate a log file, please
specify the log file path via the -j option.




This occured because the "cn" attribute did not match the first part of the "distinguishedName" attribute. If we change this to:

dn: CN=SVCLDAPQuery,CN=Users,DC=testinstance,DC=ADAM
changetype: add
objectClass: user
userPrincipalName: SVCLDAPQuery
cn: SVCLDAPQuery
displayName: Service Now LDAP Query
userPassword: Passw0rd

The import will work correctly:



Please also see this problem as it is related:
http://clintboessen.blogspot.com/2011/06/0x2077-illegal-modify-operation-some.html

0x2077 Illegal modify operation. Some aspect of the modification is not permitted.

I'm trying to import the following LDIF file into an LDS Instance using LDIFDE.

dn: CN=SVCLDAPQuery,CN=Users,DC=testinstance,DC=ADAM
changetype: add
objectClass: user
userPrincipalName: SVCLDAPQuery
userPassword: Passw0rd


Note: For ADAM, Microsoft enabled the userPassword attribute to function as a write-alias for unicodePwd and removed the requirement for the special formatting unicodePwd required. This allows your LDIF files to have clear-text passwords specified.

I am performing the import with the following command:

ldifde -i -f SVCLDAPQuery.ldf -s localhost:10001

This command throws out the following errors:

Connecting to "localhost:10001"
Logging in as current user using SSPI
Importing directory from file "SVCLDAPQuery.ldf"
Loading entries.
Add error on entry starting on line 1: Operations Error
The server side error is: 0x2077 Illegal modify operation. Some aspect of the modification is not permitted.
The extended server error is:
00002077: SvcErr: DSID-033807B5, problem 5012 (DIR_ERROR), data 8237

0 entries modified successfully.
An error has occurred in the program
No log files were written. In order to generate a log file, please
specify the log file path via the -j option.



As the requirement for special formatting of unicodePwd has been lifted Microsoft has placed a default requirement to ensure all password operations are done through LDAPS instead of LDAP. This is why it will not import the password!

To lift this requirement make the following change to the configuration partition of the instance:

Navigate to CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,CN={GUID of the ADAM}

Edit dSHeuristics attribute and set value to 0000000001001



Now you can perform password operations without requiring LDAPS.



Please also see this problem as it is related:
http://clintboessen.blogspot.com/2011/06/0x2081-multiple-values-were-specified.html

Monday, June 13, 2011

Ldap error occured. ldap_add_sW: Object Class Violation

I am performing ADAMSync from an Active Directory domain to an LDS Instance. My AD Domain Partition is called DC=Domain,DC=Local. My LDS Instance also has the same distinguished name of DC=Domain,DC=Local. When Syncing the following error is experienced:

Processing Entry: Page 18, Frame 1, Entry 48, Count 1, USN 0
Processing source entry

Processing in-scope entry 08080633da0dfe4f8b46508f00f2708f.
Adding target object CN=JoeBlow,OU=Disabled accounts,OU=IS Users,OU=IS,DC=Domain,DC=Local.
Adding attributes: sourceobjectguid, sn, title, description, physicalDeliveryOfficeName, telephoneNumber, givenName, instanceType, department, company, objectSid, sAMAccountName, lastagedchange, objectclass,
Ldap error occured. ldap_add_sW: Object Class Violation.
Extended Info: 0000207D: UpdErr: DSID-0315121C, problem 6002 (OBJ_CLASS_VIOLATION), data 19
.
Ldap error occured. ldap_add_sW: Object Class Violation.
Extended Info: 0000207D: UpdErr: DSID-0315121C, problem 6002 (OBJ_CLASS_VIOLATION), data 19
.


************
************
************ A fatal error occured in the program while processing entry
************ GUID=08080633da0dfe4f8b46508f00f2708f
************ The error will be ignored at user request. Continuing...
************
************


Below I will explain how to resolve this. I am syncing all User Objects from Active Directory to userProxy objects in LDS. This is required for single sign on (SSO). userProxy objects forward authentication bind requests to domain controllers which process the authentication request, pass it back to LDS then to the client.

To understand this in more detail please read my following blog post on the userProxy class:

http://clintboessen.blogspot.com/2011/04/userproxy-class-and-adam-lds.html

Here is a copy of my XML configuration file I installed into ADAMSync:

<?xml version="1.0"?>
<doc>
<configuration>
<!-- Sync File Description -->
<description>ADAMSync Configuration</description>
<security-mode>object</security-mode>
<!-- source-ad-name = fqdn of the domain controller -->
<source-ad-name>domaincontroller.domain.local</source-ad-name>
<!-- source-ad-partition = root AD domain partition -->
<source-ad-partition>dc=domain,dc=local</source-ad-partition>
<!-- source-ad-account = use this to specify an account to connect to AD -->
<!-- if not used, the current user will be used -->
<source-ad-account>ldapquery</source-ad-account>
<account-domain>domain</account-domain>
<!-- target-dn = target ADAM OU -->
<target-dn>dc=domain,dc=local</target-dn>
<query>
<!-- base-dn = should be the root AD partition if you want all users -->
<base-dn>dc=domain,dc=local</base-dn>
<!-- object-filter = standard ldap query format, this will grab all users -->
<!-- need to review results to see if you should modify this filter -->
<object-filter>(objectCategory=person)</object-filter>
<attributes>
<!-- include=userproxy requires objectSID to link back to the AD account -->
<include>objectSID</include>
<include>givenName</include>
<include>sn</include>
<include>description</include>
<include>title</include>
<include>company</include>
<include>department</include>
<include>mail</include>
<include>physicalDeliveryOfficeName</include>
<include>telephoneNumber</include>
<include>sAMAccountName</include>
</attributes>

</query>
<!-- map for user-to-userproxy object types -->
<user-proxy>
<source-object-class>user</source-object-class>
<target-object-class>userProxy</target-object-class>
</user-proxy>

<schedule>
<aging>
<frequency>0</frequency>
<num-objects>0</num-objects>
</aging>
<schtasks-cmd></schtasks-cmd>
</schedule>
</configuration>
<synchronizer-state>
<dirsync-cookie></dirsync-cookie>
<status></status>
<authoritative-adam-instance></authoritative-adam-instance>
<configuration-file-guid></configuration-file-guid>
<last-sync-attempt-time></last-sync-attempt-time>
<last-sync-success-time></last-sync-success-time>
<last-sync-error-time></last-sync-error-time>
<last-sync-error-string></last-sync-error-string>
<consecutive-sync-failures></consecutive-sync-failures>
<user-credentials></user-credentials>
<runs-since-last-object-update></runs-since-last-object-update>
<runs-since-last-full-sync></runs-since-last-full-sync>
</synchronizer-state>
</doc>


Notice the bits in bold. These are the attribute I want to Sync. I am also syncing these attributes FROM a user object TO a userProxy object. Let's use the "Active Directory Schema" mmc snap-in to look at the LDS Instance schema. To understand how to use "Active Directory Schema" mmc snap-in to connect to an LDS Instance please read:

http://technet.microsoft.com/en-us/library/cc816707.aspx

Your also going to probably run into this problem when connecting to the LDS Instance:

http://clintboessen.blogspot.com/2011/06/lds-active-directory-schema-status.html

In this environment I imported the following schema extensions MS-UserProxy.ldf, MS-AdamSyncMetadata.ldf, MS-AdamSchemaW2K8.ldf to my LDS Instance. In my Active Directory Schema if I look at my userProxy class object attribute association I have the following attributes associated:



However in my user class object I have the following attributes associated:



Can you pick the problem yet? I have asked ADAMSync to sync the following attributes FROM user class in Active Directory TO userProxy:

<attributes>
<!-- include=userproxy requires objectSID to link back to the AD account -->
<include>objectSID</include>
<include>givenName</include>
<include>sn</include>
<include>description</include>
<include>title</include>
<include>company</include>
<include>department</include>
<include>mail</include>
<include>physicalDeliveryOfficeName</include>
<include>telephoneNumber</include>
<include>sAMAccountName</include>
</attributes>


userProxy does not have these attributes associated. After I added these attributes to the userProxy class object all was fixed:

LDS Active Directory Schema Status Unavailable

Back when LDS (Lightweight Directory Services) was called ADAM (Active Directory Application Mode) there was a console known as "ADAM Schema" which was the ADAM version of the "Active Directory Schema" MMC console.



Now with LDS the "ADAM Schema" no longer exists. Microsoft say to use "Active Directory Schema" for both LDS and Active Directory databases. For the TechNet article please see:

http://technet.microsoft.com/en-us/library/cc816707.aspx

I setup an LDS instance running on TCP10001. When I try and connect to the instance using Active Directory Schema on localhost:10001 it comes up as available. However I know my instance is there as I can connect to it using ADSIEdit.



I found out if you connect using the IP address of the server's primary network interface card it connects successfully.



Must be something dodgy embedded into the code of the Active Directory Schema snap-in.

Monday, June 6, 2011

Allowing Domain Membership through a Cisco Firewall

When setting up windows networks a DMZ must be created. This DMZ cannot contain any PC's that are a member of your internal Active Directory domain for security reasons. For your SME companies best practice is to generally configure all machines in your DMZ in a workgroup setup. For your enterprise companies best practice is to create a separate active directory forest for your DMZ. This allows centralised management over your DMZ servers allowing administrators to control servers using things such as Group Policy and WSUS.

However there are times where you need to allow PC's in your DMZ to access your internal Active Directory. For example I needed to setup an ADAM server to synchronise only particular attributes from various domains in an Active Directory forest which to be exposed to the internet using LDAPS (Secure LDAP) on secure port 636 for an external application. This ADAM server needs to be a member of of the Active Directory domain as I require User Proxy Bind Redirection to forward authentication requests through to an Active Directory domain controller. We created a separate DMZ just to contain this server requiring domain membership.



For more information on User Proxy Bind Redirection see:

http://clintboessen.blogspot.com/2011/04/userproxy-class-and-adam-lds.html

Windows machines are not very "firewall friendly". To start off with we opened up the following ports between our isolated "Domain DMZ" and our internal network:

UDP 53 – DNS Queries
TCP 88 – Kerberos v5 over TCP
UDP 88 – Kerberos v5 over UDP
TCP 135 – Microsoft Report Procedure Call Endpoint Mapper
UDP 389 – Unsecure LDAP over UDP
TCP 389 – Unsecure LDAP over TCP
TCP 443 – WSUS Windows Updates
TCP 445 – Simple Message Block Protocol
TCP 1688 – Key Management Server
TCP 3268 – Global Catalog Requests
TCP 3389 – Remote Desktop for management purposes

All the ports above still do not allow a workstation to be a member of an Active Directory domain due to the DCOM RPC ports. Microsoft RPC (MS-RPC) does not only use port TCP135 it also uses randomly generated ports from TCP 1024-65535 for XP/2003 and TCP 49152-65535 for Vista/2008 upwards. These are frequently informally referred to as "random RPC ports." In these cases, RPC clients rely on the RPC Endpoint Mapper (EPM) which runs on TCP135 to tell them which dynamic port(s) were assigned to the server.

Multiple components from the underlining windows subsystem get assigned their own dynamic RPC port every time the windows PC boots. These components include:

- Active Directory (Local Security Authority) – Runs on each domain member!
- Certificate Services
- Cluster Service
- Distributed File System
- Distributed File System Replication
- Distributed Link Tracking Server
- Distributed Transaction Coordinator
- Outlook MAPI Client
- ISA Server
- Fax Service
- File Replication
- FTP Publishing Service
- Group Policy
- Net Logon
- Remote Storage Notification
- Remote Storage Server
- Systems Management Server 2.0
- Terminal Services Licensing
- Terminal Services Session Directory

All these windows components get a dynamic port each time the system boots. RPC clients discover which port these services are on by querying TCP 135 (the port mapper).

So how did we get around this without opening every port from 1024-65535?

Our corporate firewall is currently a Cisco ASA 5540 running OS v8.4(1). The lastest Cisco OS software for the 5540 has integrated smarts for the Windows RPC Endpoint Mapper (EPM) running on TCP135. Cisco refers to this as "DCERPC".

This process works as follows:
1. A client queries an EPM server for the dynamically-allocated port number of a required DCERPC service. The EPM server listens on the well-known TCP port 135.
2. The ASA, located between the client and EPM server, intercepts the communication.
3. The EPM server indicates the port number on which the DCERPC service is available.
4. The ASA opens a pinhole for that DCERPC service.

This allows us to make the access control lists (ACLs) as tight as possible maintaining security whilst allowing application functionality through the ASA firewall.

Here is the Syntax used for configuring this functionality on our ASA:

class-map dcerpc
match port tcp eq 135
policy-map interface_dcerpc
class dcerpc
inspect dcerpc

service-policy interface_dcerpc interface dmz_adam


interface_dcerpc is our custom Service Policy
dmz_adam is our costom interface

Of course you also need to allow TCP135 (the RPC Port Mapper) in the ACL rules for this to work!

For more information on these dynamically generated RPC ports used by Windows Systems please see the following Microsoft knowledge base articles:

http://support.microsoft.com/kb/154596
http://support.microsoft.com/kb/832017

A big thank you to Peter Revill (CCIE #18371 Routing and switching, Voice) for helping me out on this one.

Friday, April 8, 2011

UserProxy Class and ADAM / LDS

In this blog post I will be talking about the UserProxy Class which is used to create UserProxy Objects in ADAM / LDS Partitions.

ADAM = 2003 and prior name
LDS = Windows Server 2008 name
ADAM = Active Directory Application Mode
LDS = Lightweight Directory Service

They are both the same thing!

For LDS to forward authentication requests onto Active Directory we need to use UserProxy objects. These are objects get created in an application directory partition within an LDS instance.

In LDAP sense connecting to a database/object is often referred to as binding.

ProxyObjects allow you to use bind redirection, ADAM can accept and process bind requests to an ADAM proxy object that contains as one of its attributes the security ID (SID) from an Active Directory security principal. With ADAM, you can use bind redirection to provide Active Directory users with access to both ADAM data and Active Directory data, using Active Directory domain credentials as a single sign-on (SSO). In addition, you can use ADAM proxy objects to store user data that is specific to a particular application in ADAM, while using Active Directory to store more widely used directory data.

Bind redirection enables a user to bind to ADAM by means of a simple bind while still using Active Directory credentials. Other types of binding with Active Directory credentials work without requiring a proxy, but a simple bind does not. Proxy binding works only for a simple bind.

The ADAM .ldf files, which you can import into the ADAM schema during ADAM setup, contain an object definition for the object userProxy, which can be used for bind redirection. This object contains attributes that include a distinguished name and a SID. By creating a userProxy object in ADAM—specifying a distinguished name to be used for binding—and by using a valid SID from an Active Directory user account, you can bind to ADAM using bind redirection.

There are 4 "types" of users class objects provided by Microsoft:
- InetOrgPerson (the universal standard for LDAP users)
- User (the Microsoft standard lol)
- Organizational-Person (I have never used this)
- UserProxy

There are three default LDF files which you can use to create the userProxy class object in the ADAM/LDS Instance schema. These all exist in the default ADAM folder in your ADAM installation. These LDF files are the ones I was referring to above.

MS-UserProxy.ldf - contains the definitions for the userProxy class only.
MS-InetOrgPerson.ldf - Contains the definitions for all user classes including InetOrgPerson, User, Organizational-Person and userProxy.
MS-User.ldf - Contains definitions for all user classes excluding the InetOrgPerson class.

When would you want to use a userProxy object. Well you may have an external company that has an application that needs to authenticate with objects (such as users) in your Active Directory domain. Creating userProxy objects allows you to have ADAM authenticate logon credentials using AD usernames and passwords from the a domain controller without the application connecting to a domain controller. userProxy objects are very similar to AD and ADAM User objects except they do not store passwords and has an objectSID attribute that contains the SID from the linked AD User object. The SID of the userProxy object matching the User object in Active Directory is key - this is how the proxy works!

You can create userProxy objects using ADSIEdit console or using command line tools however this can be tedious. You can do this automatically for all users in an AD domain partition if you setup something like ADAMSync to synchronize. If you are preparing to use ADAMSync you need to perform the schema expantions on the ADAM partition for ADAMSync to work. You also must import the same Schema extension as your AD FFL to ensure all attributes you wish to sync exist in the ADAM instance schema. There are templates for this in the ADAM folder such as MS-AdamSchemaW2K3.LDF which is the 2003 FFL (Forest Functional Level) schema. When performing syncronization you create an LDAP configuration file which states exactly which attributes will be synced.

By default a SSL certificate required when using Userproxy objects however you can modify this by editing the configuration partition:

CN=Directory Service,CN=Windows NT, CN=Services, CN=Configuration

Change the Attribute RequiresSecureProxyBind from 1 to 0.

The reason it requires SSL by default is to encrypt the user and password information when being transmitted. ADAM does not support kerberos v5, so you must use Secure LDAP (LDAP with SSL Certificate) to protect information. You can use self signed certificates using something like selfssl.exe from the IIS Resource Kit or an internal PKI... or even public if you wish to spend money.

To be able to create UserProxy objects we must extend the ADAM schema to ensure the UserProxy class exists. Objects are created from Class objects.

One more thing, if your going to use userProxy, make sure the ADAM server is a member of the domain that trusts the AD users matching the SIDs in the userProxy objects. If the ADAM server is not a member of the domain they won't work as bind proxies as bind proxies rely on the underlying Windows security infrastructure to be able to forward the authentication to Windows/AD.

What happens if there is more then one domain? The ADAM server can only be a member of one domain! Will userProxy be able to forward authentication requests on to the appropriate domain over the trust links?

The answer is yes, user proxy objects can forward authentication requests over forest trusts, parent child trusts and tree root trusts.



I hope you have learnt something today, I have! Tip:

Buy Brian Desmonds [MVP - Directory Services] book, Active Directory forth edition. Its an awesome read:

http://oreilly.com/catalog/9780596520601