Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving User Account Expiration from ActiveDirectory

I'm trying to retrieve the expiration date from accounts.

I've tried

DirectoryEntry user = new DirectoryEntry(iMem);

var AccountExpiration = DateTime.FromFileTime((int)user.Properties["accountExpires"].Value);

it doesn't work, only gives me the error "Specified cast is not valid".

When I use

var AccountExpiration = user.Properties["accountExpires"];

returns a com object, which I'm unable to read.

Using windows powershell, works fine, I don't get why this wont work...

this is the code I use in powershell

$Expires = [datetime]::FromFileTime($tmpUser.accountExpires)
like image 997
Jazerix Avatar asked Aug 14 '13 12:08

Jazerix


People also ask

How do I find expired ad accounts?

Navigate to Reports> User Reports > Account expired users.

How do I find out when a user password expires in Active Directory?

A really easy way to tell when an AD user account password expires is to use the Net User command. This command is part of the “net commands” that allows you to add, remove, or modify the user account on a computer.

What happens to an expired ad account?

If a synced directory user account is expired (past the account expiration date) in Active Directory (AD), the user will continue to have a status of "Active" in Duo when the next directory sync occurs. This does not disable the user in Duo, so they continue to consume a license.

What happens when password expires in Active Directory?

In Active Directory, the account will not be locked if a user's password expires. Instead, the user will be prompted to change the password, and the new one must follow the password rules established by the organization based on its security policies.


1 Answers

You can use the System.DirectoryServices.AccountManagement namespace to accomplish this task. Once you get a UserPrincipal from a PrincipalContext, you can inspect the UserPrincipal.AccountExpirationDate property.

PrincipalContext context = new PrincipalContext(ContextType.Domain);

UserPrincipal p = UserPrincipal.FindByIdentity(context, "Domain\\User Name");

if (p.AccountExpirationDate.HasValue)
{
    DateTime expiration = p.AccountExpirationDate.Value.ToLocalTime();
}

If you do want to use DirectoryEntry, do this:

//assume 'user' is DirectoryEntry representing user to check
DateTime expires = DateTime.FromFileTime(GetInt64(user, "accountExpires"));

private Int64 GetInt64(DirectoryEntry entry, string attr)
{
    //we will use the marshaling behavior of the searcher
    DirectorySearcher ds = new DirectorySearcher(
    entry,
    String.Format("({0}=*)", attr),
    new string[] { attr },
    SearchScope.Base
    );

    SearchResult sr = ds.FindOne();

    if (sr != null)
    {
        if (sr.Properties.Contains(attr))
        {
            return (Int64)sr.Properties[attr][0];
        }
    }

    return -1;
}

Another way of parsing the accountExpires value is using reflection:

private static long ConvertLargeIntegerToLong(object largeInteger)
{
    Type type = largeInteger.GetType();

    int highPart = (int)type.InvokeMember("HighPart", BindingFlags.GetProperty, null, largeInteger, null);
    int lowPart = (int)type.InvokeMember("LowPart", BindingFlags.GetProperty | BindingFlags.Public, null, largeInteger, null);

    return (long)highPart <<32 | (uint)lowPart;
}

object accountExpires = DirectoryEntryHelper.GetAdObjectProperty(directoryEntry, "accountExpires");
var asLong = ConvertLargeIntegerToLong(accountExpires);

if (asLong == long.MaxValue || asLong <= 0 || DateTime.MaxValue.ToFileTime() <= asLong)
{
    return DateTime.MaxValue;
}
else
{
    return DateTime.FromFileTimeUtc(asLong);
}
like image 113
SeToY Avatar answered Sep 18 '22 17:09

SeToY