Recently I was asked to make a WinForm application I was working on secure using CAS (Code Access Security). Specifically they wanted function calls to be secured based on the users domain groups. The intention was to add several different groups to each user that had access to the application and restrict access to certain functionality depending on which role they were assigned. The expectation was that CAS would make this more secure that just disabling menus and buttons.
I have no real experience with CAS and it was surprisingly difficult to find just a simple example of how to use it for domain group security. Most articles are either very high level or so complex that it just takes too long to get to the important information. Normally code access security is used either from a WebSite (ASP.NET 2.0 handles this pretty much automatically so long as your Web.Config and overall website structure is setup correctly) or its used to block or provide specific access rights to 3rd party assemblies (such as file access libraries).
I'm not interested in either of those senarios. I just want to block access to BLL and DAL libraries based on the users domains groups.
The following code is sufficient to do exactly that. This example class demonstrates the minimum code required. The output log should show the current windows user including either the workgroup or domain. The first function should succeed but since the second function is restricted by an unlikely group name it should fail.
If you comment out the AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); line of code both will fail because the SecurityAction.Demand declaration requires the security access be met - in other words the default is no access.
class Security
{
private WindowsPrincipal wp;
private string logs;
public Security() {
logs = "";
wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
logs += "UserName=" + wp.Identity.Name + "\r\n";
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
}
public string GetLogs() {
return logs;
}
public void CheckSecurity() {
try {
if (!wp.IsInRole("EVERYONE"))
logs += "DoRollEveryone: Not in role EVERYONE\r\n";
else
logs += "DoRollEveryone: In role EVERYONE\r\n";
DoRollEveryone();
} catch (Exception err) {
logs += "DoRollEveryone failed: " + err.Message + "\r\n\r\n";
}
try {
if (!wp.IsInRole("BLAHBLAH"))
logs += "DoRollBlahBlah: Not in role BLAHBLAH\r\n";
else
logs += "DoRollBlahBlah: In role BLAHBLAH\r\n";
DoRollBlahBlah();
} catch (Exception err) {
logs += "DoRollBlahBlah failed: " + err.Message + "\r\n\r\n";
}
}
[PrincipalPermission(SecurityAction.Demand, Role = "EVERYONE")]
private void DoRollEveryone() {
logs += "DoRollEveryone called successfully.\r\n\r\n";
}
[PrincipalPermission(SecurityAction.Demand, Role = "BLAHBLAH")]
private void DoRollBlahBlah() {
logs += "DoRollBlahBlah called successfully.\r\n\r\n";
}
}This code works and accomplishes what I was asked to do.
But is it actually secure?
After writing the code my first thought was, "Is the compiler securing the Role attributes". Since the role attributes (Role = "BLAHBLAH") is a constant string, and it must be a constant string, it may appear as plain text in the executable. You can't use SecureString for the attribute because it requires a constant to compile.
Normally this sort of security would likely be used in middle tier libraries or for a web service. In these cases the user would not have access to the libraries directly so they would not be able to modify them. In my case the application is a simple WinForm client server application running on the user's desktop.
I took a quick look in the exe with a hex editor and immediately found "BLAHBLAH". I then modified BLAHBLAH by changing it to EVERYONE. Running the exe again I found I now had access to the 2nd function which I originally did not have access to. Perhaps I'm doing something wrong. Is there a way to encrypt the role attributes or is this CAS security really just a false sense of security when used in a local application to which the user has direct access.
Comments
hw to Fix the Roll Based on my Application...
Hello Will any Plz Help me How to Include This Code in my Application and hw to Fix the Roll Based on my Application...
Harish
RE: hw to Fix the Roll Based on my Application...
Hi Harish,
If you can give me some more details I'll see if I can help solve your problem.
Generally if you want to use CAS (Code Access Security), such that Roles determine the access given to specific functions, you need to do the following:
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);NOTE: Keep in mind that Windows doesn't always refresh user/group access rights immediately so its possible you will need to logoff the machine and then log back in after adding the user to the group. Its also handy to code a little routine that will tell you which groups the current user has access to so you know if its your code or your setup having the problem.
To get the roles for the current user the following should work:
List<string> groups = new List<string>();
WindowsIdentity wi = WindowsIdentity.GetCurrent();
IdentityReferenceCollection userGroups = wi.Groups;
foreach (IdentityReference group in userGroups)
{
string groupName = group.Translate(typeof(System.Security.Principal.NTAccount)).ToString();
groups.Add(groupName.ToUpper());
}