Cook Computing

A First Look at System.Security in Whidbey

June 6, 2005 Written by Charles Cook

A few days ago I had to write some unmanaged C++ code to modify the DCOM limits settings to give anonymous logons the same permissions as the Everyone account (the issues around the limits settings are described in this Microsoft document). Today I thought I'd have a first look at the System.Security classes introduced in Whidbey to see what it would be like writing similar functionality in managed code. The code retrieves the security descriptor from the registry value; creates an ACE for ANONYMOUS LOGON, giving it Local and Remote access permisssions; then either adds to it to the security descriptor's DACL or replaces an existing ACE for the same SID; and finally writes the security descriptor back to the registry. Note that this is experimental code and for reconfiguring the DCOM limits settings it is likely you will need to change more than just the MachineAccessRestriction ACL.


using System;
using Microsoft.Win32;
using System.Security.AccessControl;
using System.Security.Principal;

class Program
{
  const int COM_RIGHTS_EXECUTE  = 1;
  const int COM_RIGHTS_EXECUTE_LOCAL  = 2;
  const int COM_RIGHTS_EXECUTE_REMOTE  = 4;
  const int COM_RIGHTS_ACTIVATE_LOCAL  = 8;
  const int COM_RIGHTS_ACTIVATE_REMOTE = 16;

  static void Main(string[] args)
  {
    byte[] bin = (byte[])Registry.GetValue(
      "HKEY_LOCAL_MACHINE\\Software\\microsoft\\ole", 
      "MachineAccessRestriction", null);
    RawSecurityDescriptor sd = new RawSecurityDescriptor(bin, 0);
    RawAcl dacl = sd.DiscretionaryAcl;
    NTAccount acc = new NTAccount("ANONYMOUS LOGON");
    SecurityIdentifier sid = (SecurityIdentifier)
      acc.Translate(typeof(SecurityIdentifier));
    CommonAce newAce = new CommonAce(AceFlags.None, 
      AceQualifier.AccessAllowed, COM_RIGHTS_EXECUTE 
      | COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_EXECUTE_REMOTE, 
      sid, false, null);
    int i;
    for (i = 0; i < dacl.Count; i++)
    {
      CommonAce ace = (CommonAce)dacl[i];
      if (ace.SecurityIdentifier == sid)
      {
        dacl.RemoveAce(i);
        break;
      }
    }
    dacl.InsertAce(i, newAce);
    sd.DiscretionaryAcl = dacl;
    byte[] outbuff = new byte[sd.BinaryLength];
    sd.GetBinaryForm(outbuff, 0);
    Registry.SetValue(
      "HKEY_LOCAL_MACHINE\\Software\\microsoft\\ole",
      "MachineAccessRestriction", outbuff);
  }
}

There may be a better way of implementing this using the new classes but even this was much nicer to write than the equivalent unmanaged code. When dealing with security on resources such as files, mutexes, registry keys, etc, there are higher level classes such as FileSecurity which are easier to use than the lower-level classes used in the code above.

Eamon O'Tuathail has a summary of Windows Security in .NET v2 and Mark Pustilnik has an MSDN article Manage Access to Windows Objects with ACLs and the .NET Framework.