Why UserPrincipal.Enabled returns different values? - c#

I am trying to determine if a user account in AD is enabled. For this I use the following code:
string domain = "my domain";
string group = "my security group";
string ou = "my OU";
//init context
using (var cnt= new PrincipalContext(ContextType.Domain, domain))
{
//find the necessary security group
using (GroupPrincipal mainGroup
= GroupPrincipal.FindByIdentity(cnt, IdentityType.Guid, group))
{
if (mainGroup != null)
{
//get the group's members
foreach (var user in mainGroup.GetMembers()
.OfType<UserPrincipal>()
.Where(u => u.DistinguishedName.Contains(ou)))
{
//ensure that all the info about the account is loaded
//by using FindByIdentity as opposed to GetMembers
var tmpUser= UserPrincipal.FindByIdentity(cnt,
user.SamAccountName);
//actually I could use `user` variable,
//as it gave the same result as `tmpUser`.
//print the account info
Console.WriteLine(tmpUser.Name + "\t" +
tmpUser.Enabled.HasValue + "\t" +
tmpUser.Enabled.Value);
}
}
}
}
The problem is, when I run this code under an administrative account, I get the real result, while when I run it under a non-priviledged account, user.Enabled returns false for some of the accounts, while it should be true.
The only similar q&a I managed to find are
UserPrincipal.Enabled returns False for accounts that are in fact enabled?
Everything in Active Directory via C#.NET 3.5 (Using System.DirectoryServices.AccountManagement)
which do not help here.
Why is that so? What are my options to get this info under a non-priviledged account?
Here is another approach: How to determine if user account is enabled or disabled:
private bool IsActive(DirectoryEntry de)
{
if (de.NativeGuid == null)
return false;
int flags = (int)de.Properties["userAccountControl"].Value;
if (!Convert.ToBoolean(flags & 0x0002))
return true;
else
return false;
}
Same approach is described in Active Directory Objects and C#.
However when running under an unpriviledged user account, userAccountControl attribute is null and it's not possible to determine the state of the account.
The workaround here is to use PrincipalContext Constructor, specifying the credentials of a user with enough priviledges to access AD.
It stays unclear to me, why the unpriviledged user had access to AD at all, and couldn't get values of some certain account attributes. Probably this has nothing to do with C#, and should be configured in AD...

You'll need to delegate permissions in Active Directory for the accounts that will be performing the AD queries. This is what I had to do for my applications to work (though we are performing other administrative tasks on user accounts).
Check Here for instructions on how to delegate permissions(or see blockquote below).
You may referred the following procedure to run the delegation:
Start the delegation of control wizard by performing the following steps:
Open Active Directory Users and Computers.
In the console tree, double click the domain node.
In the details menu, right click the organizational unit, click delegate control, and click next.
Select the users or group to which you want to delegate common administrative tasks. To do so, perform the following steps:
On the Users or Groups page, click Add.
In the select Users, computers or Groups, write the names of the users and groups to which you have to delegate control of the organizational unit, click OK. And click next.
Assign common tasks to delegate. To do so perform the following common tasks.
On the tasks to delgate page, click delegate the following common tasks.
On the tasks to delegate page, select the tasks you want to delegate, and click OK. Click Finish
For Example: To delegate administrator to move user/computer objects, you can use advance mode in AD User and Computer and run delegation. It should have write privilege in both OU for the object moving. For writing new values, the administrators account should have delegated values on the user account (Full privilege in specific OU as well.
Something else worth looking into is if the accounts have the userAccountControl attribute. I've heard that accounts missing this attribute may not report correctly. In most scenarios this attribute should be set to NormalAccount.

Related

How to check if a user is also an administrator?

I have a ClickOnce application and on startup I want to check if the user is an administrator.
When starting the application, I'm logged in as myself, and my user is member of the Administrators group. UAC is also turned off.
My first attempt was the following:
var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
var admin = principal.IsInRole(WindowsBuiltInRole.Administrator);
The above didn't work. Going through all built-in roles, only WindowsBuiltInRole.User returns true. So the second attempt was the following:
var identity = WindowsIdentity.GetCurrent();
foreach (var role in identity.Groups)
{
if (role.IsValidTargetType(typeof(SecurityIdentifier)))
{
var sid = role.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
if (sid.IsWellKnown(WellKnownSidType.AccountAdministratorSid) || sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) )
{
admin = true;
break;
}
}
}
This second attempt didn't work either. admin stays false.
To further test the above, I created a new user and added him only to the Administrators group. He is not in the Users group. Starting the app as this new user will still return false.
The only time the above code will return true, ie. the user is an administrator, is when I log in and start the app and the pre-installed Administrator user account.
As I have UAC turned off I shouldn't be dealing with split tokens.
Is the problem related to the application being a ClickOnce app?
Is there a way (that actually works) which will return whether the user is actually an adminisatrator (note: the user can be part of the Domain Admins group but not a local admin)?

C# Ask for Domain Admin credential and use them to perform some task

I need some help with examples how to use Credential of a current user running application.
So in windows 7 you can run application using user loged in by simply running application or you can use "Run as a different User" option and run it as another user.
In my Active Directory I have 2 account Domain User and one with Domain Admin rights. I'm login Windows as a Domain User and when I need I'm using "Run as a different User" to launch some task as a Domain Admin.
So the task is to get my Credential and use it to perform some task, lets say rename active directory user name.
Best way to do this as I can see is to ask user running application to enter Domain Admin credential on then start application and use them for various task. Of course I can easily run application with "Run as a different User" but I still need to get this credential and use them.
I've searched through the web and I can't find this, all i could find is using credential for a web auth.
If you can show me some examples how to:
1) Ask user for a Admin user credential ( i can leave without this )
2) Get and use credentials of a user running application
I don't want to know password I know I can't. Don't really want to add to a WPF form password box I prefer to use windows API to handle this i've already entered user name and password using "Run as a different User".
PS: I sorry if this topic exists :( I guess I'm bad at creating correct search requests.
ADDED: to be more clear what I need. In powershell it will look like this:
# This Asks user to enter credentials
$cred = Get-Credential;
# this checks if I have rights to use them.
Get-ADDomain “DOMAIN” –Server “Domain.com” –Credential $cred;
Of course it's simplified as hell though the point is that I can use credentials user entered when ever it's needed.
The equivalent C# to your Get-ADDomain is quite simple, it is just
public void PerformSomeActionAsAdmin(string adminUsername, string adminPassword)
{
//Null causes the constructor to connect to the current domain the machine is on.
// |
// V
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, null, adminUsername, adminPassword))
{
//do something here with ctx, the operations will be performed as whoever's username and password you passed in.
}
}
if you don't want to connect to the current domain and instead want to connect to Domain.com then replace the null with the appropriate string.
EDIT: if you want to use secure strings you can't use System.DirectoryServices.AccountManagement.PrincipalContext, you will need to go with the lower level calls in System.DirectoryServices.Protocols. Doing this process is quite complex, here is a link to the MSDN article "Introduction to System.DirectoryServices.Protocols (S.DS.P)" explaining how to use it. It is a big complex read and honestly I don't think it is worth it to be able to use encrypted strings.
public void PerformSomeActionAsAdmin(NetworkCredential adminCredential)
{
using(LdapConnection connection = new LdapConnection("fabrikam.com", adminCredential))
{
// MAGIC
}
}
Do you want to check if the current user is a doman admin? start by looking at his code, it should help you get started identifying what AD groups the current user is in. This will give you a list of strings that are each group's name the current user belongs to. Then you can check that list against whatever AD group you are trying to check for. Replace YourDomain with your domain name:
WindowsIdentity wi = WindowIdentity.GetCurrent();
List<string> result = new List<string>();
foreach (IdentityReference group in wi.Groups)
{
result.Add(group.Translate(typeof(NTAccount)).ToString().Replace("YourDomain\\", String.Empty));
}
Since i'm not quite sure what you're trying to do, this also might be helpful. You'd have to get the user name and password from a textobx, password box etc. This could be used for an "override" to use, for example, a manager's credentials etc. to do something the current user wasn't allowed to do because of AD group membership etc.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YourDomain"))
{
if (UserName.Contains("YourDomain\\"))
{
UserName = UserName.Replace("YourDomain\\", String.Empty);
}
//validate the credentials
bool IsValid = pc.ValidateCredentials(UserName, Password);
}

c# application authorization based on Windows current user

I write a small application and I need to add some authorization security tips.
Simple Example:
I have a WinForm that contain two buttons: btnAdd and btnDelete. I want that:
if the current user is in the Administrator group, both the two buttons above will be displayed
else (if not in the Administrator group (like like guess account)) only btnAdd will be displayed.
How can I do that
You should be able to construct a WindowsPrincipal object, then just check if the user is in the role you expect, and use the return value to set the button to visible or not. Something like the below
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
// using WindowsBuiltInRole.Administrator or "BUILTIN\\Administrators" should work
btnAdd.Visible = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
The updated code works, I've tested this, where I'm a local admin, since you want to test the current user, WindowsIdentity.GetCurrent() is actually cleaner.
If you need to confirm whether or not you are an admin on the machine, you can either check the group membership through MMC, but if there is any domain groups involved and you don't have access you won't be able to check this through MMC unless you have access to AD.
A sure way to verify if a user is a member of group is running the below in a command prompt window
Get members of local Administrators group:
net localgroup administrators
Get members of the domain group: this is necessary if for example, mydomain\WorkstationAdmins is a member of the local Administrators group and userId is a member of mydomain\WorkstationAdmins (thus an admin of the wokstation)
net group "WorkstationAdmins" /domain

How to test if a user is in the Built-in Administrators group without elevating privileges?

I expected this code:
WindowsPrincipal principal = new WindowsPrincipal( WindowsIdentity.GetCurrent() );
public bool UserHasAdminRights( WindowsPrincipal principal, WindowsBuiltInRole role )
{
bool isAdmin;
// get the role information of the current user
if ( principal.IsInRole( role ) )
{
isAdmin = true;
}
else
{
isAdmin = false;
}
return isAdmin;
}
to return true when a user is in the Built-in Administrators group.
HOWEVER
MSDN for IsInRole states:
In Windows Vista, User Account Control (UAC) determines the privileges
of a user. If you are a member of the Built-in Administrators group,
you are assigned two run-time access tokens: a standard user access
token and an administrator access token. By default, you are in the
standard user role. When you attempt to perform a task that requires
administrative privileges, you can dynamically elevate your role by
using the Consent dialog box. The code that executes the IsInRole
method does not display the Consent dialog box. The code returns false
if you are in the standard user role, even if you are in the Built-in
Administrators group. You can elevate your privileges before you
execute the code by right-clicking the application icon and indicating
that you want to run as an administrator.
Question is how do I modify this code so that it returns true, if the user is in the built-in Admin group, WITHOUT requiring the user to elevate permissions during/before runtime?
Since I can't neatly post code in comments, like I can here, let me just suggest some pseudo code
var user = Windows.GetThisUser( me ); //current method (I said pseudo code)
function CheckIfImAdmin( user ) .... //current method
proposed method:
var administrativeUsers = Windows.GetUsersInRole( "admin" ); //use a SID here, much more reliable
foreach(user in administrativeUsers){
if (user == me) return true;
return false;
}
While this may look the same, it's not. Instead of querying the user to see if it's currently in a given role (non-escalated aren't) I'm focusing on who the administrators are and then asking if that group contains the user I want, namely the current user.

Enabling the button visibility for different accounts

I'm currently working on a website that requires me to enable validation for different accounts.
I have 2 accounts - Admin and User.
My Admin account is able to view all the functions available in the website, but the User is only allowed a few functions.
What I have in mind is to disable the visibility of a button - btnUpload.
Below are the codes that I've came up with so far.
Mp.Mp login = new Mp.Mp();
bool result = login.AuthenticateUser(tbxUsername.Text, tbxPassword.Text);
if (result == true) {
Session.Add("Session_name", tbxUsername.Text);
//Session["Username"] = tbxUsername.Text;
Response.Redirect("Index.aspx");
}
I need help with the visibility of buttons to ensure that btnUpload appears only to Admin and not User.
May be you want some thing like this
if(Session["Session_name"] == "admin")
{
btnUpload.Visible = true;
}
else
{
btnUpload.Visible = false;
}
You have RollName AND RollID For Identify your user by that roleid.
You just need to check rollID at time of user login and store your user rollid in session and then check this rollid in whatever page where you need to check constrain regarding user role.
try
btnUpload.Visible = Session ["Session_name"] == "Admin";
How you are going to decide if the user is admin or a regular user? In simplistic scenario, your user data may have a flag that indicates whether user is an admin or not. Flexible approaches uses role based security - so if the user is member of particular role then he get access to certain features. So in such system, you can have a access right (or feature) for admin privileges and admin role will have this feature. In integrated authentication schemes, you can also use on windows groups or active directory groups as a security role. ASP.NET has good support for role based security (see this, this and this). Regardless of a implementation, once you decide is user is admin or not, controlling UI is very simple thing.

Categories

Resources