DESKTOP

Using Standard NT Security Features in Windows 7 : WORKING DIRECTLY WITH WINDOWS NT SECURITY (part 1) - Checking User Permissions

5/14/2013 4:25:38 AM

If you aren't already assigning security to objects that your application creates, then you're missing out on a valuable Windows feature. Basic Windows NT security is the cornerstone of protection on every system that runs the Windows operating system. Newer features, such as Role-Based Security (RBS), are add-ons to this basic level of security. Think of role-based and other forms of security as the alarm system and other advanced security features in modern homes. Even though these advanced security features are welcome and extremely important, they can't replace the basic locks in a home. Likewise, you can't replace basic Windows NT security in your application. The following sections show how to perform some basic protection tasks using Windows NT security.

NOTE

The .NET Framework 4 supplies the new System.Security.AccessControl namespace that gives you access to Windows NT security features. You can read about it at http://msdn.microsoft.com/library/system.security.accesscontrol.aspx. If you're using an older version of the .NET Framework, you must resort to using Platform Invoke (P/Invoke) programming techniques to gain access to Windows NT security. Using P/Invoke is somewhat cumbersome but not impossible.

1. Checking User Permissions

The factors that describe a user's permissions vary according to the user. A user will always have a SID and specific characteristics, such as an impersonation level. In addition, user permissions aren't always stored with the user token. Smart administrators use groups to help describe user permissions. Granting rights to groups (rather than individual users) saves time and effort when rights change to meet a new requirement. The following sections describe how to obtain information about user permissions.

1.1. Configuring the User Permission Example

The User Permission example begins with the Windows Forms template. You need a button to call the code used to display the user's permissions, a label to mark the output, and a list box as shown in Figure 1.

Figure 1. Define the User Permission interface as shown here.

The application doesn't require any special references. However, you do need to add the following using statement:

using System.Security.Principal;

1.2. Writing the User Permission Code

Microsoft doesn't make it hard to obtain the user permission entries. In fact, obtaining user permission settings is one of the items that the .NET Framework has supported for a long time. Microsoft does tweak the functionality, but the code in Listing 1 shows what you can typically expect to obtain as information from the .NET Framework without any special coding.

Example 1. Checking a user's permissions
private void btnCheck_Click(object sender, EventArgs e)
{
    // Get the current user.
    WindowsIdentity User = WindowsIdentity.GetCurrent();

    // Display the user's information.
    lstPermissions.Items.Add("Name: " + User.Name);
    lstPermissions.Items.Add("SID: " + User.User.Value);

    // Display the authentication information.
    lstPermissions.Items.Add(
        "Authenticated? " + User.IsAuthenticated.ToString());
    lstPermissions.Items.Add(
        "Guest? " + User.IsGuest.ToString());
    lstPermissions.Items.Add(
        "System Account? " + User.IsSystem.ToString());
    lstPermissions.Items.Add(
        "Authentication Type: " + User.AuthenticationType.ToString());
    lstPermissions.Items.Add(
        "Impersonation Level: " + User.ImpersonationLevel.ToString());

// Get the group membership.
    lstPermissions.Items.Add("");
    lstPermissions.Items.Add("Group Membership:");
    foreach (IdentityReference Group in User.Groups)
        lstPermissions.Items.Add("\t" +
            Group.Translate(typeof(NTAccount)));
}

The example begins by creating a WindowsIdentity object, User, that points to the current user by using the GetCurrent() method. The WindowsIdentity object doesn't provide any common constructor, but uses specialty constructors to help you obtain the right user identity. For example, you can just as easily obtain an anonymous account or impersonate another user.

The code displays the user's login name (as contrasted to the user's full name) and next the SID. Every user has a unique SID, so you can use a SID to ensure that the user you're working with is actually the user you want, even if there's a chance of having users with similar login names on the network.

After the code displays basic identification, it provides some authentication information. For example, you can determine whether the user is logged in to the system (authenticated) and whether the user is a guest. Your computer also has a number of system accounts that aren't meant for use by users, and you can detect system accounts as well. The three common system accounts are:

Discovering group membership is extremely important. As you can see, the WindowsIdentity object makes this task quite simple. Unfortunately, you can use the WindowsIdentity object only to discover group affiliation — you can't use it to change group or any other information for that matter. Figure 2 shows typical output from this example.

Figure 2. Discovering user permissions will help you interact with the user in an application.

1.3. Using WMI for Permissions Example

Sometimes the .NET Framework will fall short in the information department. Another way to obtain the security information you need is to use Windows Management Instrumentation (WMI), as shown in the User Permissions Using WMI example in Listing 10-2. In this case, the example views user group affiliation from the group perspective, rather than from the user perspective. To begin this example, you create a Windows Forms application with controls similar to those shown in Figure 10-4.

In order to use WMI, you must add a reference to the System.Management assembly. You must also add the following using statement:

using System.Management;

It's important to realize that WMI isn't a managed interface — it relies on native code and Component Object Model (COM) interfaces. You can use WMI directly at the command line using the WMIC (Windows Management Interface Command line) utility. Because of the way WMI is constructed, you might find that you have to create some convoluted code in order to obtain the desired results. Listing 2 shows an example of a simple WMI application.

Example 2. WMI provides a secondary means of interacting with users and groups
private void btnCheck_Click(object sender, EventArgs e)
{
    // Create a query for the local group accounts.
    SelectQuery GroupQuery = new SelectQuery("Win32_Group");

    // Define the search object.
    ManagementObjectSearcher Searcher =
        new ManagementObjectSearcher(GroupQuery);

    // Look at each group.
    foreach (ManagementObject ThisGroup in Searcher.Get())
    {
        // Display the group's information.
        lstPermissions.Items.Add("Name: " +
            ThisGroup["Name"].ToString());
        lstPermissions.Items.Add("Domain: " +
            ThisGroup["Domain"].ToString());
        lstPermissions.Items.Add("Description: " +
            ThisGroup["Description"].ToString());
        lstPermissions.Items.Add("Local Group? " +
            ThisGroup["LocalAccount"].ToString());
        lstPermissions.Items.Add("SID: " +
            ThisGroup["SID"].ToString());
        lstPermissions.Items.Add("Status: " +
            ThisGroup["Status"].ToString());

        // Obtain a list of users for the group.
        SelectQuery UserQuery = new SelectQuery("Win32_GroupUser");
        ManagementObjectSearcher UserList =
            new ManagementObjectSearcher(UserQuery);

        // Display the list.
        lstPermissions.Items.Add("Users:");
        foreach (ManagementObject ThisUser in UserList.Get())
        {
            // Obtain the group information for each entry.
            String GroupPart = ThisUser["GroupComponent"].ToString();

					  

// When the group information matches the current group, output
            // it to the listbox.
            if (GroupPart.Contains(ThisGroup["Name"].ToString()))
            {
                // Obtain the user information for the entry.
                String UserPart = ThisUser["PartComponent"].ToString();

                // Extract the user name and output it.
                lstPermissions.Items.Add("\t" +
                    UserPart.Substring(UserPart.IndexOf("Name=")));
            }
        }

        // Add a space.
        lstPermissions.Items.Add("");
    }
}

The .NET Framework provides a number of ways to create a WMI query. The easiest method is to create a SelectQuery object, such as GroupQuery, and supply it with a WMI class. In this case, the example begins with the Win32_Group class. You can find a listing of WMI classes at http://msdn.microsoft.com/library/aa394554.aspx.

Creating the query is only the first step. You must now execute the query using a ManagementObjectSearcher object, Searcher. The .NET Framework will happily create any query you want, but the query can fail if it's incorrect. The failure will occur when you execute the query using the ManagementObjectSearcher object, so sometimes the errant code isn't where the debugger tells you it is.

The for loop is where the query actually executes. Calling Searcher.Get() obtains a single group entry and places it in the ManagementObject, ThisGroup. The ThisGroup object contains a wealth of helpful information, such as the group name, SID, and status.

At this point, you have a list of groups, but not of users who are members of the groups. In order to obtain the list of users, you must create another query for the Win32_GroupUser class. The output of this query is actually an object array consisting of two strings, as shown here:

{\\MAIN\root\cimv2:Win32_GroupUser.GroupComponent= 
"\\\\MAIN\\root\\cimv2:Win32_Group.Domain=\"MAIN\",
Name=\"Administrators\"",
PartComponent="\\\\MAIN\\root\\cimv2:Win32_UserAccount.Domain=\"Main\",
Name=\"Administrator\""}

The two strings are the GroupComponent and the PartComponent. The GroupComponent contains the complete path to the group information, which is Administrators in this example. Likewise, the PartComponent contains the complete path to the user associated with the group, which is Administrator in this example. The two-part nature of this query complicates the code a bit, but you can easily locate the users associated with a particular group using a for loop and then comparing the group name to the name in the GroupComponent (represented by GroupPart).

NOTE

The UAC has an effect on WMI. In some cases, you obtain less data and other classes become inaccessible. For example, you won't obtain a complete list of user accounts when the WMI output is filtered by the UAC because the UAC hides sensitive accounts from view. The article at http://msdn.microsoft.com/library/aa826699.aspx provides details on what you can expect when an account is hobbled by UAC filtering.

Once the code has located a user associated with the current group, it outputs the information from PartComponent. Because the output contains a complete path, you use the Substring() method to extract just the information needed. Figure 3 shows typical output from this example.

Figure 3. Using WMI has some significant advantages, but at the cost of additional code.
Other  
  •  Using Standard NT Security Features in Windows 7 : UNDERSTANDING BASIC NT SECURITY
  •  Windows Server 2008 R2 networking : Planning and Deploying a TCP/IP Network Infrastructure (part 2) - Policy-based QoS
  •  Windows Server 2008 R2 networking : Planning and Deploying a TCP/IP Network Infrastructure (part 1)
  •  Windows Server 2008 R2 networking : Overview of Windows Server 2008 R2 Networking
  •  Windows Server 2003 : Recovering from System Failure
  •  Windows Server 2003 : Advanced Backup and Restore (part 2) - Scheduling Backup Jobs, Shadow Copies of Shared Folders
  •  Windows Server 2003 : Advanced Backup and Restore (part 1) - Managing Media, Backup Options, The Ntbackup Command
  •  Windows Server 2003 : Managing and Implementing Disaster Recovery - Restoring Data
  •  Windows 7 : Networking and HomeGroup Sharing - Sharing Between PCs (part 2) - Old-School Sharing
  •  Windows 7 : Networking and HomeGroup Sharing - Sharing Between PCs (part 1) - HomeGroup Sharing
  •  
    Top 10
    Review : Sigma 24mm f/1.4 DG HSM Art
    Review : Canon EF11-24mm f/4L USM
    Review : Creative Sound Blaster Roar 2
    Review : Philips Fidelio M2L
    Review : Alienware 17 - Dell's Alienware laptops
    Review Smartwatch : Wellograph
    Review : Xiaomi Redmi 2
    Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
    Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
    3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    VIDEO TUTORIAL
    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
    Popular Tags
    Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8