Article

rrawson's picture
article
Reads:

9093

Score:
3.5
3.5
2
 
Comments:

2

Making Password Expiration work between AD and eDirectory the way it did before IDM was installed…

Author Info

22 January 2008 - 6:15pm
Submitted by: rrawson

(View Disclaimer)

Problem

For a long time I have struggled with problems of clients who complain that once IDM was installed, password sync between eDirectory and AD causes password expirations to misbehave.

The causes of this issue are two-fold. First, Active Directory does not have any mechanism to record who the perpetrator of a change is, so loopback protection is absent from that driver. The result is that every single change on the subscriber channel comes back on the publisher. This is annoying, but for most changes it gets handled by "optimize modify".

The second problem is that eDirectory within IDM treats every password change as an administrative one. So when a password change comes through the publisher channel, as it does from the password filter right after a password change comes through the subscriber, the password expiration is reset to the current date and time. So every time a user or an administrator changes the password in eDirectory, their password ends up expired.

The simple solution, it would seem, would be to add the password expiration interval to the value of the pwdLastSet in AD (after converting its time stamp to eDirectory format). Then we would get the same interval we are after. But this lacks subtlety: what it actually does is turn every change into a user change, even administrative changes coming from eDirectory. So this is not acceptable, either.

Solution

There are really four use cases to consider here:

  • Adminstrative Change from eDirectory
  • User Change from eDirectory
  • Change from AD (AD does not make a distinction between who makes a change)
  • AD Sets the “User must change password at next logon” in MMC.
  • I created the four rules shown below in the Input Transformation to handle these four cases. They work as follows: First, we map pwdLastSet to Password Expiration Time but transform it appropriately so that it’s converted from Windows time stamps (signed integer representing milliseconds since 1/1/1900) to NetWare time stamps (unsigned integer representing seconds since 1/1/1970). Then we add the password expiration interval.

    If an administrator or a user makes a password change from eDirectory, we determine that this change came from eDirectory by comparing pwdChangedTime to the converted pwdLastSet from AD. If the AD change is 30 seconds or less later than the eDirectory change, we assume it must have originated in eDirectory. Therefore, there is no reason to let the change to pwdLastSet or the modify-password event flow through, so we veto the password change and strip pwdLastSet. This leaves the values that were set by eDirectory and the client unchanged.

    On the other hand, if the password change is originated in AD, we need to determine what to do with password expiration. AD does not make a distinction between user and administrative password changes, so all changes are treated as user changes. However, if the administrator clicks the “User must change password at next logon” checkbox in Active Directory Users and Computers, the pwdLastSet gets set to 0. If that happens, we set the password expiration time to the pwdLastSet value; otherwise, we calculate the Password Expiration Time by adding the pwdLastSet to the Password Expiration Interval.

    <rule>
      <description>[AMC] Set Local Variables</description>
      <conditions>
       <and>
        <if-association op="available"/>
       </and>
      </conditions>
      <actions>
       <do-set-local-variable name="MAD-PWD-LAST-SET">
        <arg-string>
         <token-src-attr name="pwdLastSet"/>
        </arg-string>
       </do-set-local-variable>
       <do-set-local-variable name="PWD-LAST-SET">
        <arg-string>
         <token-xpath expression="jadutil:translateFileTime2Epoch($MAD-PWD-LAST-SET)"/>
        </arg-string>
       </do-set-local-variable>
       <do-set-local-variable name="PWD-CHANGED-TIME">
        <arg-string>
         <token-dest-attr name="pwdChangedTime">
          <arg-association>
           <token-association/>
          </arg-association>
         </token-dest-attr>
        </arg-string>
       </do-set-local-variable>
       <do-set-local-variable name="PWD-EXP-INTVL">
        <arg-string>
         <token-dest-attr name="Password Expiration Interval">
          <arg-association>
           <token-association/>
          </arg-association>
         </token-dest-attr>
        </arg-string>
       </do-set-local-variable>
       <do-set-local-variable name="PWD-EXP-TIME">
        <arg-string>
         <token-dest-attr name="Password Expiration Time">
          <arg-association>
           <token-association/>
          </arg-association>
         </token-dest-attr>
        </arg-string>
       </do-set-local-variable>
      </actions>
     </rule>
    
    <rule>
      <description>[AMC] Check if modify-password initiated by AD</description>
      <conditions>
       <and>
        <if-operation op="equal">modify-password</if-operation>
        <if-xpath op="true">number($PWD-LAST-SET)-number($PWD-CHANGED-TIME) < 30</if-xpath>
       </and>
      </conditions>
      <actions>
       <do-veto/>
      </actions>
     </rule>
    
    <rule>
      <description>[AMC] pwdLastSet: strip on eDir initiated change</description>
      <comment xml:space="preserve">The Identity Vault uses a 32 bit value to store certain time values while Active Directory uses a 64 bit time value. Reformat the 64 bit value to fit within the vault's 32 bit syntax.</comment>
      <conditions>
       <or>
        <if-op-attr name="pwdLastSet" op="available"/>
       </or>
       <or>
        <if-operation op="equal">add</if-operation>
        <if-operation op="equal">modify</if-operation>
       </or>
       <or>
        <if-xpath op="true">number($PWD-LAST-SET)-number($PWD-CHANGED-TIME) < 30</if-xpath>
       </or>
      </conditions>
      <actions>
       <do-strip-op-attr name="pwdLastSet"/>
      </actions>
     </rule>
     <rule>
      <description>[AMC] pwdLastSet: Convert to Identity Vault time format AD initiated change</description>
      <comment xml:space="preserve">The Identity Vault uses a 32 bit value to store certain time values while Active Directory uses a 64 bit time value. Reformat the 64 bit value to fit within the vault's 32 bit syntax.</comment>
      <conditions>
       <or>
        <if-op-attr name="pwdLastSet" op="available"/>
       </or>
       <or>
        <if-operation op="equal">add</if-operation>
        <if-operation op="equal">modify</if-operation>
       </or>
       <or>
        <if-xpath op="not-true">number($PWD-LAST-SET)-number($PWD-CHANGED-TIME) < 30</if-xpath>
       </or>
       <or>
        <if-local-variable name="MAD-PWD-LAST-SET" op="not-equal">0</if-local-variable>
       </or>
      </conditions>
      <actions>
       <do-strip-op-attr name="pwdLastSet"/>
       <do-set-dest-attr-value name="Password Expiration Time">
        <arg-value type="string">
         <token-xpath expression="number($PWD-LAST-SET)+number($PWD-EXP-INTVL)"/>
        </arg-value>
       </do-set-dest-attr-value>
      </actions>
     </rule>
    
    <rule>
      <description>[AMC] pwdLastSet: Convert to Identity Vault time format AD initiated admin reset</description>
      <comment xml:space="preserve">The Identity Vault uses a 32 bit value to store certain time values while Active Directory uses a 64 bit time value. Reformat the 64 bit value to fit within the vault's 32 bit syntax.</comment>
      <conditions>
       <or>
        <if-op-attr name="pwdLastSet" op="available"/>
       </or>
       <or>
        <if-operation op="equal">add</if-operation>
        <if-operation op="equal">modify</if-operation>
       </or>
       <or>
        <if-local-variable name="MAD-PWD-LAST-SET" op="equal"/>
       </or>
      </conditions>
      <actions>
       <do-strip-op-attr name="pwdLastSet"/>
       <do-set-dest-attr-value name="Password Expiration Time">
        <arg-value type="string">
         <token-xpath expression="number($PWD-LAST-SET)"/>
        </arg-value>
       </do-set-dest-attr-value>
      </actions>
     </rule>
    
    

    This rule set was written for IDM 3.01; I have created more efficient versions on IDM 3.51 where the IDM Script is more powerful, but this code should work for both.

    Additional Considerations

    There are some other considerations required when implementing these rules. They are:

    • Filter and Schema Mapping - The filter should be modified to permit synchronization of Password Expiration Time on the publisher channel. It should be mapped to pwdLastSet from Active directory.
    • NMAS Schema Extensions - In order to have the pwdChangedTime attribute exist, you must update NMAS using Security Services 2.04 or later. Additionally, you will need to install the various schema files nmas.sch, nspm.sch and nsimpm.sch. See TID 10091354 for more details.
    • Time Synchronization - Since the rule relies on the fact that the time of a password change in eDirectory and the time of the change in AD are within 30 seconds of each other to determine whether the password change was initiated by AD or by eDirectory, if AD and eDirectory are not in sync, this rule will fail to function correctly.

    We set time sync up on AD to match the NTP source that eDirectory was using by executing the following:

    NET STOP w32time
    NET START w32time
    W32tm /resync
    
    

    In a full production tree, you need to do this on the server acting as the PDC emulator role, as well as the domain controller running the IDM driver shim.


Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).

It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.




User Comments

denchris's picture

Solution not necessary, Fix with Global Config Values

Submitted by denchris on 2 April 2008 - 6:53am.

An Admin type password change is caused when you sync the password to the NDS password. To do that you would have to have the global config value "Publish Password to the NDS Password" set to yes.

If the global config values "Publish Password to the NDS Password" is set to NO and "Publish Password to Distribution password" is set to YES, then the password change will go through as a user type password change and NOT expire it the immediately.

Stonej's picture

Cannot get this working

Submitted by Stonej on 8 November 2012 - 3:22am.

Hello,
I have put the code in the Active Directory driver Input Transfomation, setup the filter and extra stuff and it still will not work.

What am i doing wrong ?

Thanks

© 2013 Novell