The .NET Framework is a little behind the
curve when it comes to the UAC. This is surprising considering how hard
Microsoft is pushing people to rely on the UAC as a security measure.
Currently, you can't request privilege elevation in the .NET Framework
for a thread or other useful work element. In fact, you have only two
choices:
The following sections describe how to create an
application that provides UAC support within the limits that the .NET
Framework currently allows. In many cases, you'll have to make some
decisions on how to break your application into pieces using the
current strategies. Microsoft will probably make it possible eventually
to perform in-place privilege elevations or allow some method of
creating a thread that will support privilege elevation.
1. Creating a Manifest
The first technique for working with the UAC is to
elevate your entire application to administrator level. You should use
this approach only when the application is designed exclusively for
administrator use, won't see any use outside the network, and is
extremely focused — performing just one or two small tasks. Using this
technique to elevate the privileges of an application that should
normally run at a lower level will leave huge security holes in your
system. The following sections describe how to work with this kind of
application.
1.1. Defining the Manifest Application
The technique shown in this section will work with
any .NET application. However, the example relies on a Windows Forms
template application that has a single button, btnAudit, for testing purposes. The example doesn't require any additional references, but you do need to add the following using statements:
using System.Security.AccessControl;
using System.Security.Principal;
using System.IO;
1.2. Adding the Manifest
The <requestedExecutionLevel> tag accepts two inputs. The first, level, describes what type of execution you need. When working with the UAC, you always request requireAdministrator. However, there are situations where using highestAvailable
may work for specific needs. Microsoft terms these scenarios as mixed
mode, where a standard user and administrator work with the
application. An article at http://msdn.microsoft.com/library/bb756929.aspx describes how these settings react when users have certain settings enabled on their systems.
The second setting, uiAccess, gives the
application access to other windows on the desktop. Normally, the
application can't drive output to other windows. Microsoft recommends
setting this value to false normally. The only exception that
Microsoft makes is for applications with accessibility (special needs)
features. For example, an application might need to send output to an
on-screen keyboard. There are probably other situations where you'll
need to set this value to true, but doing so opens a
potential security hole. Updating a simple status indicator probably
isn't a good use for this feature — the security risk outweighs the
benefit of the update.
1.3. Creating the Application Code
The example application adds or removes auditing from a test file, Test.TXT,
that appears in the output folder. In this case, the application adds
or removes auditing for the write right of the BUILTIN\Users account.
The event fires when the user fails to write to the file. This
application relies on a simple toggle mechanism to perform its task
after detecting the audit state of the file. Listing 1 shows the code you need for this example.
Example 1. Performing an audit of actions on a file or directory
private void btnAudit_Click(object sender, EventArgs e) { // Create a file security object for the target file. FileSecurity FS = File.GetAccessControl( Application.StartupPath + @"\Temp.TXT", AccessControlSections.Audit);
// Create a new rule. FileSystemAuditRule Rule = new FileSystemAuditRule( new NTAccount(@"BUILTIN\Users"), FileSystemRights.Write, AuditFlags.Failure); // Obtain a list of the existing rules. AuthorizationRuleCollection AuditRules = FS.GetAuditRules(true, true, typeof(NTAccount));
// Check for the existence of the rule in the collection. Boolean FoundIt = false; foreach (FileSystemAuditRule AR in AuditRules)
// Look for the rule. if ((AR.IdentityReference == Rule.IdentityReference) && (AR.FileSystemRights.HasFlag(FileSystemRights.Write)) && (AR.AuditFlags.HasFlag(AuditFlags.Failure))) { // Set FoundIt appropriately. FoundIt = true;
// Exit the loop. break; }
// Add or remove the rule as appropriate. if (FoundIt)
// Remove the rule from the file security object. FS.RemoveAuditRule(Rule);
else
// Add the rule to the file security object. FS.AddAuditRule(Rule);
// Save the rule to the file. File.SetAccessControl( Application.StartupPath + @"\Temp.TXT", FS);
// Display a success message. MessageBox.Show("Change Succeeded!"); }
|