How to check that windows account is disabled in C#? - c#

I am trying to check if window account is disabled or not in active directory, for this reason I tried System.DirectoryServices.AccountManagement namespace but could not find any method to check if account is disable unlike IsAccountLockedOut method.
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal =UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
oUserPrincipal.IsAccountLockedOut();

We use this method:
var context = new DirectoryContext(DirectoryContextType.Domain, "domain");
using (var domainController = DomainController.FindOne(context))
{
using (var directorySearcher = domainController.GetDirectorySearcher())
{
directorySearcher.Filter = String.Format("(sAMAccountName={0})", "login");
directorySearcher.SizeLimit = 1;
var userDirectory = directorySearcher.FindOne();
using (var userDirectoryEntry = userDirectory.GetDirectoryEntry())
{
var active = userDirectoryEntry.IsActive();
}
}
}
IsActive - is an extension method:
public static bool IsActive(this DirectoryEntry directoryEntry)
{
if (directoryEntry.NativeGuid == null) return false;
var value = directoryEntry.Properties["userAccountControl"].Value;
if (value == null)
return true;
var flags = (int)value;
return !Convert.ToBoolean(flags & 0x0002);
}
So, get DirectoryEntry of your account and call this method.

PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal =UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
bool? IsEnabled = oUserPrincipal.Enabled;
// if IsEnabled = true then User Account is Enabled
// if IsEnabled = false then User Account is Disabled

Related

C# - how to retrieve gMSA account password?

how to retrieve gMSA account password in C#?
I need to use gMSA account to disable/enable AD account.
But I don't know how to get gMSA password?
public static bool DisableUserAccount(string sUserName)
{
UserPrincipal oUserPrincipal = GetUserForDoamin("D-Domain", sUserName);
oUserPrincipal.Enabled = false;
oUserPrincipal.Save();
return true;
}
public static UserPrincipal GetUserForDoamin(string sDomain, string sUserName)
{
PrincipalContext PrincipalDomain = null;
PrincipalDomain = GetPrincipalContext("D-Domain", "NONE"); ;
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(PrincipalDomain, sUserName);
return oUserPrincipal;
}
public static PrincipalContext GetPrincipalContext(string sDomainZone, string sOU)
{
PrincipalContext ServerCredentials = null;
string sDomainName = "";
sDomainName = "D-Domain";
ServerCredentials = new PrincipalContext(ContextType.Domain, sDomainName, "gMSA$", gMSApassword);
break;
return ServerCredentials;
}
At [GetPrincipalContext], gMSApassword is not nullable column. I try "" & null, but it is not working.
I don't know how to setup.

"Properties" and "GetProperties" not available for UserPrincipal, unable to get 'Department' and other values

I'm trying to get the 'Departmment' value for AD Users, I have a UserPrincipal object, which I get using the following.
public ADUser getADUser(string sid)
{
ADUser ADUser = new ADUser();
string container = "OU=Users,OU=comp,DC=domain,DC=domaindomain";
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "domain", container))
{
UserPrincipal userPrinciple = new UserPrincipal(ctx) { Enabled = true };
PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrinciple);
((DirectorySearcher)principalSearcher.GetUnderlyingSearcher()).SearchScope = SearchScope.OneLevel;
UserPrincipal domainUser = UserPrincipal.FindByIdentity(ctx,IdentityType.Sid, (sid));
ADUser = new ADUser()
{
SID = domainUser.Sid.ToString(),
GUID = domainUser.Guid.ToString(),
Description = domainUser.Description,
DisplayName = domainUser.DisplayName,
EmailAddress = domainUser.EmailAddress,
VoiceTelephoneNumber = domainUser.VoiceTelephoneNumber,
Enabled = domainUser.Enabled,
permissions = getADUserPermissions(sid)
};
} //using
return ADUser;
}
But when I try to get the 'Department' value using either...
domainUser.GetProperty("department");
or
domainUser.Properties["department"].Value;
I get the error that "'UserPrincipal' does not contain a definition for either "GetProperty" or "Properties".
I've found that 'Department' is in the properties of the underlying object in the UserPrincipal, so I tried...
domainUser.GetUnderlyingObject();
Which gets the underlying object, and when debugging I can see 'Department' in its properties, but theres no function to access the properties (at least no function that my version of .net Core 3.1 seems to want to let me use).
This gets the value of a given AD string property:
private string GetAdPropertyValue(DirectoryEntry userAccount, string adPropertyKey)
{
string result = null;
PropertyValueCollection property = userAccount.Properties[adPropertyKey];
if (property != null)
{
object propertyValue = property.Value;
if (propertyValue != null)
{
string propertyValueString = (string)propertyValue;
result = propertyValueString.Trim();
}
}
return result;
}
Example:
DirectoryEntry directoryEntryUser = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
string departmentName = GetAdPropertyValue(directoryEntryUser, "department");

c# comparing current windows user to AD group

I am trying to grab the current windows user and see if that user is part of a certain group in Active Directory. The username information finds "Harper\TSmith" which seems fine but when I get to the
UserPrincipal uPrincipal = Psearch.FindOne() as UserPrincipal
Line UPrincipal is null. Can not figure out why. I also have at the bottom a validator class that as a bool method to see if they are part of that particular group.
PrincipalContext principalCtx = new PrincipalContext(ContextType.Domain);
UserPrincipal findUser = new UserPrincipal(principalCtx);
//findUser.Name = Environment.UserName;
findUser.Name = WindowsIdentity.GetCurrent().Name;
PrincipalSearcher pSearch = new PrincipalSearcher();
pSearch.QueryFilter = findUser;
UserPrincipal uPrincipal = pSearch.FindOne() as UserPrincipal;
Validator validate = new Validator();
//validate.IsUserInGroup("VisualOne", uPrincipal);
if (validate.IsUserInGroup("MyGroup", uPrincipal))
{
var MemberShipForm = new Membership();
MemberShipForm.Show();
}
public bool IsUserInGroup(string groupName, UserPrincipal user)
{
PrincipalContext context = new PrincipalContext(ContextType.Domain, "Harper");
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, "MyGroup");
if (user.IsMemberOf(group))
{
return true;
}
return false;
}
PrincipalContext principalCtx = new PrincipalContext(ContextType.Domain);
UserPrincipal uPrincipal = UserPrincipal.Current;
if (validate.IsUserInGroup("MyGroup", uPrincipal))
{
var MemberShipForm = new Membership();
MemberShipForm.Show();
}

Get parent OU of user in Active Directory using C#

I want to check, if a a user is in a specific parent OU.
How can I do that?
Check below code for a clear desciption of what I am looking for.
using System.DirectoryServices.AccountManagement;
public bool IsUserInOU(string samAccountName, string OUName){
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
//Check if the user is in the OU specified in OUName
//Something like:
//return user.IsInOU(OUName);
}
}
}
public void TestIt_1(){
//The parent OU of this user is "AwesomeOU"
string samAccountName = "Joe";
string OUName = "AwesomeOU";
bool expected = true;
bool actual = IsUserInOU(samAccountName, OUName);
Assert.AreEqual(expected, actual);
}
public void TestIt_2(){
//The parent OU of this user is "WhateverOU"
string samAccountName = "Mike";
string OUName = "AwesomeOU";
bool expected = false;
bool actual = IsUserInOU(samAccountName, OUName);
Assert.AreEqual(expected, actual);
}
The Domain:
National OU
Awesome OU
Joe
Whatever OU
Mike
Solution 1 after empi's answer
With the information given by empi, I wrote the below method to extract the first OU in the DistinguishedName. Having done that, the rest is a breeze.
public static string GetOUForUser(string samAccountName)
{
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
//System.Console.WriteLine(user.DistinguishedName);
int startIndex = user.DistinguishedName.IndexOf("OU=", 1) + 3; //+3 for length of "OU="
int endIndex = user.DistinguishedName.IndexOf(",", startIndex);
var group = user.DistinguishedName.Substring((startIndex), (endIndex - startIndex));
return group;
}
}
}
Solution 2 after JPBlanc's answer
public static string GetOUForUser(string samAccountName)
{
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
using (DirectoryEntry deUser = user.GetUnderlyingObject() as DirectoryEntry)
{
using (DirectoryEntry deUserContainer = deUser.Parent)
{
return deUserContainer.Properties["Name"].Value.ToString();
}
}
}
}
}
Ok #Empi solution is working, but UserPrincipal is built on DirectoryEntry objects that provides a parent or container properties that just give you the object you are looking for, without using string way.
/* Retreiving a principal context
*/
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "WM2008R2ENT:389", "dc=dom,dc=fr", "dom\\jpb", "MyPwd");
/* Retreive a user
*/
UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, "user1");
/* Retreive the container
*/
DirectoryEntry deUser = user.GetUnderlyingObject() as DirectoryEntry;
DirectoryEntry deUserContainer = deUser.Parent;
Console.WriteLine (deUserContainer.Properties["distinguishedName"].Value);
This information is in UserPrincipal.DistinguishedName. You should check if DistinguishedName ends with "," + ou distinguished name (case insensitive). However, you must know the distingushed name of ou you're checking.
For example, if dn is: CN=Jeff Smith,OU=Sales,DC=Fabrikam,DC=COM, then it says that user is in OU=Sales,DC=Fabrikam,DC=COM ou.
This is how I would get the Distinguished Name for a specific AD user, hope it helps :-)
private static string GetDNOfUser(string user)
{
var ctx = new PrincipalContext(ContextType.Domain, Environmentals.Domain, Environmentals.OUPath);
//Creating object for search filter
UserPrincipal userPrin = new UserPrincipal(ctx)
{
//Only getting users with the same name as the input
Name = user
};
var searcher = new PrincipalSearcher
{
//Applying filter to query
QueryFilter = userPrin
};
//Finding the user
var results = searcher.FindOne();
searcher.Dispose();
//Return the distinguishedname
return results.DistinguishedName;
}

How to determine if user account is enabled or disabled

I am throwing together a quick C# win forms app to help resolve a repetitive clerical job.
I have performed a search in AD for all user accounts and am adding them to a list view with check boxes.
I would like to default the listviewitems' default check state to depend upon the enabled/disabled state of the account.
string path = "LDAP://dc=example,dc=local";
DirectoryEntry directoryRoot = new DirectoryEntry(path);
DirectorySearcher searcher = new DirectorySearcher(directoryRoot,
"(&(objectClass=User)(objectCategory=Person))");
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult result in results)
{
DirectoryEntry de = result.GetDirectoryEntry();
ListViewItem lvi = new ListViewItem(
(string)de.Properties["SAMAccountName"][0]);
// lvi.Checked = (bool) de.Properties["AccountEnabled"]
lvwUsers.Items.Add(lvi);
}
I'm struggling to find the right attribute to parse to get the state of the account from the DirectoryEntry object. I've searched for AD User attributes, but not found anything useful.
Can anyone offer any pointers?
this code here should work...
private bool IsActive(DirectoryEntry de)
{
if (de.NativeGuid == null) return false;
int flags = (int)de.Properties["userAccountControl"].Value;
return !Convert.ToBoolean(flags & 0x0002);
}
Using System.DirectoryServices.AccountManagement:
domainName and username must be the string values of the domain and username.
using (var domainContext = new PrincipalContext(ContextType.Domain, domainName))
{
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, username))
{
if (foundUser.Enabled.HasValue)
{
return (bool)foundUser.Enabled;
}
else
{
return true; //or false depending what result you want in the case of Enabled being NULL
}
}
}
Not that anyone asked, but here's a java version (since I ended up here looking for one). Null checking is left as an exercise for the reader.
private Boolean isActive(SearchResult searchResult) {
Attribute userAccountControlAttr = searchResult.getAttributes().get("UserAccountControl");
Integer userAccountControlInt = new Integer((String) userAccoutControlAttr.get());
Boolean disabled = BooleanUtils.toBooleanObject(userAccountControlInt & 0x0002);
return !disabled;
}
You can use something like this:
ADUserAccountControl flags;
Enum.TryParse(de.Properties["userAccountControl"].Value.ToString(), out flags);
if(flags.HasFlag(ADUserAccountControl.ACCOUNTDISABLE)
{
// account is disabled
}
Here is a complete list of all possible flags:
/// <summary>
/// Source: https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
/// </summary>
public enum ADUserAccountControl : long
{
SCRIPT = 0x0001,
ACCOUNTDISABLE = 0x0002,
HOMEDIR_REQUIRED = 0x0008,
LOCKOUT = 0x0010,
PASSWD_NOTREQD = 0x0020,
PASSWD_CANT_CHANGE = 0x0040,
ENCRYPTED_TEXT_PWD_ALLOWED = 0x0080,
TEMP_DUPLICATE_ACCOUNT = 0x0100,
NORMAL_ACCOUNT = 0x0200,
INTERDOMAIN_TRUST_ACCOUNT = 0x0800,
WORKSTATION_TRUST_ACCOUNT = 0x1000,
SERVER_TRUST_ACCOUNT = 0x2000,
DONT_EXPIRE_PASSWORD = 0x10000,
MNS_LOGON_ACCOUNT = 0x20000,
SMARTCARD_REQUIRED = 0x40000,
TRUSTED_FOR_DELEGATION = 0x80000,
NOT_DELEGATED = 0x100000,
USE_DES_KEY_ONLY = 0x200000,
DONT_REQ_PREAUTH = 0x400000,
PASSWORD_EXPIRED = 0x800000,
TRUSTED_TO_AUTH_FOR_DELEGATION = 0x1000000,
PARTIAL_SECRETS_ACCOUNT = 0x04000000,
}
I came here looking for an answer, but it was only for DirectoryEntry. So here is a code that works for SearchResult / SearchResultCollection, for people who had the same problem:
private bool checkIfActive(SearchResult sr)
{
var vaPropertiy = sr.Properties["userAccountControl"];
if (vaPropertiy.Count > 0)
{
if (vaPropertiy[0].ToString() == "512" || vaPropertiy[0].ToString() == "66048")
{
return true;
}
return false;
}
return false;
}

Categories