Above:
My current project requires me to validate a user from an Active Directory Group. Catch, a computer may not always be connected to a domain, but users will still have to run the tool.
At this point, you must accept that any coercive security can be circumvented by an attacker, as it is fully enforced on the client. Not really part of the solution, but keep that in mind.
I understand that I cannot query Active Directory until I try to query the SAM machine (MSAM) instead.
Security Accounts Manager stores only local accounts (MACHINENAME \ Administrator and others). It will not have domain user credentials. You are thinking about the LSA cache , which remembers the last credentials for logging into the N domain (where N is a number from 0 to 50 configured by Group Policy), and the last N SID is the mapping names (128 by default, configured through the registry ). Security Account Manager saves only domain accounts on a domain controller.
I am having trouble identifying the current user while I am offline. Here is what I use: PrincipalContext mainctx = new PrincipalContext (ContextType.Machine); UserPrincipal uprincipal = new UserPrincipal (mainctx);
In addition, someone can describe the three parameters ContextType ApplicationDirectory, Domain, Machine. I'm afraid I do not fully understand each option and, therefore, use it incorrectly.
As noted above, information is not cached, but the ContextType enumeration can be described as follows:
From MSDN:
- Domain: Domain store. This is an AD DS repository. (As they say, this applies to domain accounts, for example, to the LDAP Directory Active Directory, which requires network access).
- ApplicationDirectory: Application directory store. This is an AD LDS repository. ( AD Lightweight Directory Services (formerly known as ADAM) is a smaller version of Active Directory designed to store credentials for a single application. To this discussion, but also uses LDAP.)
- Machine: Computer store. This is a SAM store. (Enumerates only local accounts)
From now on, how can I ask who is currently registered on the local machine.
You can always verify a registered user by calling WindowsIdentity.GetCurrent() . This will return the registered user SIDs and group identifiers, possibly cached if the login was offline.
When connecting to a domain, I can request the use of UserPrincipal.Current. If I am not connected to the domain, he will not be able to say "Server failed to contact." Note: this method is not available using the above code, instead I can refuse the PrincipalContext and directly request the current user. When the current user is detected, I can query GetGroups () and determine if they are in one of the required groups.
To determine group membership, verify that the group identifier is required in the identifier returned by WindowsIdentity.GetCurrent . If you do not use the SID in your access control system, you can translate the name into the SID by calling SecurityIdentifier.Translate . You will need to translate it online and then cache it for offline use. It can be saved as a string or as a binary file, so both of them fit well into the registry.
// while we are online, translate the Group to SID // Obviously, administrators would be a bad example as it is a well known SID... var admins = new NTAccount("Administrators"); var adminSid = (SecurityIdentifier)admins.Translate(typeof(SecurityIdentifier)); // store the sid as a byte array on disk somewhere byte[] adminSIDbytes = new byte[adminSid.BinaryLength]; adminSid.GetBinaryForm(adminSIDbytes, 0); // at time of check, retrieve the sid and check membership var sidToCheck = new SecurityIdentifier(adminSIDbytes, 0); if (!wi.Groups.Contains(sidToCheck)) throw new UnauthorizedAccessException("User is not a member of required group");