Link to home
Start Free TrialLog in
Avatar of JAaron Anderson
JAaron AndersonFlag for United States of America

asked on

Java ActiveDirectory accountExpires Attribute

I see that you have some great code in VB for assigning an expired date for any Account in ActiveDirectory. Do you know any equivalent functionality I can study for a Java code implementation of such a solution?

In studying other code like in VB I find theres Libraries you can take advantage of like objUser.AccountExpirationDate = #9/28/2007 13:00#  objUser.SetInfo
but I am in Java are these objects available also to Java Libraries?

I am coming from writing to LDAP in Novell though Java and need to also update my AD expiration too at the same method processes... Can I just use the simpleDate equivalent to this format and push it to the ActiveDirectory attribute in a replace instruction as a String?
Or is a data type date required for the ActiveDirectory Attribute?
I guess I should either cater to how many nanosceonds from Jan 01 1601 will expire or is it enough to expect IAD User processes to convert the value to nanoseconds for me when it write to the AD attribute it I prepare the Date in a adequate format of :

My initial thoughts of approach are below, in Java to write a formulaic calculation method something like the following code snippets:

Thanks for your insight

import java.util.*;
import java.text.SimpleDateFormat;
import java.io.UnsupportedEncodingException;
import com.novell.ldap.*;
import java.text.DateFormat;
import java.util.Date;
 
 
public class ADExpirationTestClass {
 
      public static final SimpleDateFormat ldapTimeFormat = new SimpleDateFormat("yyyyMMddHHmm'00'Z");
 
      public static final SimpleDateFormat DISPLAY_EXPIRATION_AD_FORMAT = new SimpleDateFormat("MMM/dd/yyyy HH:mm");
// try this format to empower IAD User Interface to convert for me.
 
private long expirationInterval; //stores 180 days, MUST Change minimum of Twice each Year
 
public long newNanoExpDate; // convert from Date to long
 
      public ADExpirationTestClass (long expirationInterval) { //begin minimum bare constructor
this.expirationInterval = expirationInterval;
        // Make a new Date object. It will be initialized to the current time.
} //end constructor
 
 
public static final Date ACTIVEDIR_CALCDATE;
// formulate from 100-nanosecond intervals since 12:00 AM  January 1, 1601 for Active Directory.
static {
 
  Calendar calendar = Calendar.getInstance();
 
  calendar.set(1601, Calendar.JANUARY, 1);
 
  ACTIVEDIR_CALCDATE = calendar.getTime();
 
}
 
 
// Accessor Method to retrieve Global Variable 
      public long getExpirationInterval() {
            return expirationInterval; //returns 180 days, MUST Change minimum of Twice each Year
      }
 
// Mutator Method to assign expiration interval to instance
      public void setExpirationInterval(long expirationInterval) {
            this.expirationInterval = expirationInterval; //assigns the value 180
      }     
      
// Accessor Method to get this.Event.Instance.Date
      public String getCurrentExpirationDate() {
            if (expirationInterval == 0) return null;       
// get the nanoseconds for this event // 1 millisecond = 1 000 000 nanoseconds
Date now = new Date(System.currentTimeMillis()*1000L*1000L);
// Always try to use System.currentTimeMillis() instead of java.util.Date or java.util.Calendar :: Better Performance
Date nextexp = new Date(System.currentTimeMillis()+expirationInterval*24L*60L*60L*1000L*1000L*1000L);
// expirationInterval*24L*60L*60L*1000L*1000L*1000L should be span of expiration in nanoseconds
// formulate from 100-nanosecond intervals since 12:00 AM  January 1, 1601 for Active Directory.
// next line should be able to be pushed as MMM/dd/yyyy HH:mm to ActiveDirectory and auto calculate nanoseconds since 12:00 AM  January 1, 1601
return DISPLAY_EXPIRATION_AD_FORMAT.format(nextexp);
 
// or if I have to completely calculate nanoseconds to store, also calculate my baseline here :
// Date adstart = new Date(System.currentTimeMillis(ACTIVEDIR_CALCDATE)*24L*60L*60L*1000L*1000L*1000L);
                // Id alternatively do something like the next three lines if manual nano conversion is required.
// Date nanoInterval = new Date(nextexp - adstart); // remainder in nanoseconds from original begin date
// newNanoExpDate = nanoInterval.getTime();
// return newNanoExpDate;
      }
 
//& and later PUSH it to AD
ActiveDirectoryConnection.modify(dn, new LDAPModification(
LDAPModification.REPLACE, new LDAPAttribute(
"accountExpires", // the actual name of the Attribute in ActiveDirectory
newNanoExpDate) // send value in nano seconds from 12:00 AM  January 1, 1601 to the next nanoInterval from this event
));
                  }
} // end class

Open in new window

Avatar of JAaron Anderson
JAaron Anderson
Flag of United States of America image

ASKER

I have found this specifications developer's note on format of the Active Directory accountExpires Attribute :
http://msdn.microsoft.com/en-us/library/ms675098(VS.85).aspx
this is a GREAT example I got working that manipulates time Date intervals in great examples
http://www.idevelopment.info/data/Programming/java/date/DateExample.java

now next I need to engineer it to accept a time of 180 days in the future.


//in miliseconds and make that the new Date ontop of 
 
//now Date() + 180 days in seconds should be:
//15552000000000 miliseconds
Date now = new Date(System.currentTimeMillis());
 
Date nextExpiration = new Date(System.currentTimeMillis()+expirationInterval*24L*60L*60L*1000L*1000L);

Open in new window

Baseline NOTE:

Java A Date object are represented as a long that counts the * number of milliseconds since midnight, January 01, 1970, Greenwich Meantime

.Net ActiveDirectory object is represented in format #9/28/2007 13:00# and can be converted into nanoseconds since January 01, 1601.

Avatar of Kevin Cross
It appears you have all the major knowledge points you need to get this done.  When I did this last by the way, I used JNDI so here is a good reference.

http://java.sun.com/products/jndi/tutorial/

What you have to do is store the value as long instead of Date.  You set the long initially to a constant representing the number of 100 nano-seconds from 1601-01-01 to 1970-01-01.  Then when you add the number of milliseconds for expiration date properly adjusted to 100-nano-seconds since 1970-01-01 it will be correct timestamp for Active Directory.

You can then post to AD from JNDI same as you would eDirectory.

Speaking of which, have you considered using the Secure Identity Manager (DirXML) starter pack which includes connector for eDirectory to Active Directory and you can synchronize attributes such as this and you would only have to worry about changing this in your meta-directory which would normally be eDirectory (Novell) side especially since that is where you already know how to code this and has APIs for Java.  Microsoft has an Identity Management Tool as well so if interested in that can see if have API for Java but would suspect it is .NET and you would have to do C# or J# which is slightly different.

On that last thought, you can see if J#.NET has the objects you see used in VB for easy access to AD.  I hadn't tried, so not sure.

Kevin

coming up against an AD error not sure if its a connection thing or not.. havent been able to dedicate myself solely to this matter to debug at this time... I will try to write to logs next for a better determination.

stay tuned
I learned that its NOT accountExpires I need to use to expire the password of an AD Account. I have now learned I need to pursue maxPwdAge but it is a Security Policy that is tree driven. From what I understand I cannot uniquely apply a independent password expiration to an individual cn account...

My Goal is to set a unique password GUID for each account at the event of last password reset for a period of 180 days... Is this feasible in Active Directory or would the last most recent user reset the entire group assigned to the AD security policy ?

Is this correct ? Any Thoughts ?
jandersonwidener,

My apologies on the delay, the cleanup tools unsubscribe me as I leave comments so I didn't get to see your comment until this thread came back up in my cleanup tool.  Consequently, I have marked this for full refund to you but am not deleting as I think the discussion may be helpful to others especially your information on the correct field in LDAP needing to be changed.

Anyway, glad you found the correct field.  I wouldn't have remembered that as I handled this through directory sync with DirXML and so set attribute via eDirectory side.

At any rate, this may help:
http://windowsitpro.com/article/articleid/44862/q-how-can-i-run-a-report-that-displays-the-last-password-change-for-all-accounts-in-a-container.html

It should show the last time a specific user account's password was changed, you can use an if logic to check if greater than 180 days and only set a new GUID for that user.  Know you can code this to only update one user as that is the basis of tools like the password sync filter I used and PSync as well as Microsoft's MIIS product for identity management.  Those ran server side though, so might need to be local to a directory server, but see what the article above gets you.

One thing is the dates are stored in specific format, but appears they show you how to convert that.  If need further explanation, see my article here.

https://www.experts-exchange.com/articles/Microsoft/Development/MS-SQL-Server/SQL-Server-2005/Converting-Active-Directory-Timestamps-in-Microsoft-SQL-Server.html

Hope that helps.
ASKER CERTIFIED SOLUTION
Avatar of ee_auto
ee_auto

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial