Export (0) Print
Expand All

How To: Update a Security Descriptor of a WMI Namespace 

.NET Framework 2.0

A security descriptor identifies a securable object's owner and primary group. A functional security descriptor is in binary format, but security descriptors can also be in string format to store and transmit security descriptor information. By changing a security descriptor, you can grant a group certain rights to access a securable object. This example updates the security descriptor information for a namespace so that certain users can access and modify the namespace.

Example

The following code example grants all rights to the Power Users group for a given namespace. To change the namespace name, change the value of the namespaceName variable in the Sample class.

using System;
using System.Management;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace ManagementSample
{
    class Sample
    {
        private readonly string namespaceName = 
            "TestNamespaceSecurity";

        public void Run()
        {
            IntPtr stringSecurityDescriptorPtr = IntPtr.Zero;
            IntPtr securityDescriptorPtr = IntPtr.Zero;
            int stringSecurityDescriptorSize = 0;
            int securityDescriptorSize = 0;

            try
            {
                // Create a test namespace
                this.CreateTestNamespace();

                // Retreive SD of a namespace
                ManagementClass systemSecurity = 
                    new ManagementClass("root/" + 
                    namespaceName + ":__SystemSecurity");
                ManagementBaseObject outParams =
                    systemSecurity.InvokeMethod("GetSD",
                      null, null);
                if ((uint)outParams["ReturnValue"] != 0)
                {
                    Console.WriteLine("GetSD returns an error: " +
                        outParams["ReturnValue"]);
                    return;
                }                                

                // Convert SD to string SD
                this.ConvertSDtoStringSD((byte[])outParams["SD"],
                    out stringSecurityDescriptorPtr,
                    out stringSecurityDescriptorSize);
                string stringSecurityDescriptor =
                    Marshal.PtrToStringAuto(
                    stringSecurityDescriptorPtr);
                Console.WriteLine("Original string security " +
                    "descriptor of the {0} namespace:",
                    namespaceName);
                Console.WriteLine(stringSecurityDescriptor);
                
                // Grant all permissions to Power Users Group
                stringSecurityDescriptor +=
                    "(A;;CCDCLCSWRPWPRCWD;;;PU)";

                //Convert string SD to SD
                Console.WriteLine(
                    "\nNew String Security Descriptor:");
                Console.WriteLine(stringSecurityDescriptor); 
                this.ConvertStringSDtoSD(stringSecurityDescriptor,
                    out securityDescriptorPtr,
                    out securityDescriptorSize);
                byte[] securityDescriptor = 
                    new byte[securityDescriptorSize];
                Marshal.Copy(securityDescriptorPtr,
                    securityDescriptor, 0, securityDescriptorSize);

                //Set the new SD for the namespace
                ManagementBaseObject inParams = 
                    systemSecurity.GetMethodParameters("SetSD");                                
                inParams["SD"] = securityDescriptor;
                outParams = systemSecurity.InvokeMethod("SetSD",
                    inParams, null);
                if ((uint)outParams["ReturnValue"] != 0)
                {
                    Console.WriteLine("SetSD returns error: " +
                        outParams["ReturnValue"]);
                    return;
                }
                Console.WriteLine("\nNew string security descriptor"
                    + " is set. Press Enter to exit.");
                Console.ReadLine();
            }
            finally
            {
                // Free unmanaged memory
                if (securityDescriptorPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(securityDescriptorPtr);
                    securityDescriptorPtr = IntPtr.Zero;
                }
                if (stringSecurityDescriptorPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(stringSecurityDescriptorPtr);
                    stringSecurityDescriptorPtr = IntPtr.Zero;
                }
                this.DeleteTestNamespace();
            }
        }

        public void ConvertSDtoStringSD(byte[] securityDescriptor,
            out IntPtr stringSecurityDescriptorPtr,
            out int stringSecurityDescriptorSize)
        {
            bool result = 
                ConvertSecurityDescriptorToStringSecurityDescriptor(
                securityDescriptor,
                1,
                SecurityInformation.DACL_SECURITY_INFORMATION | 
                SecurityInformation.GROUP_SECURITY_INFORMATION |
                SecurityInformation.OWNER_SECURITY_INFORMATION |
                SecurityInformation.SACL_SECURITY_INFORMATION,
                out stringSecurityDescriptorPtr,
                out stringSecurityDescriptorSize);
            if (!result) 
            {
                Console.WriteLine( "Fail to convert" +
                    " SD to string SD:" );
                throw new Win32Exception(
                    Marshal.GetLastWin32Error());
            }
        }

        public void ConvertStringSDtoSD(
            string stringSecurityDescriptor,
            out IntPtr securityDescriptorPtr,
            out int securityDescriptorSize)
        {
            bool result =
                ConvertStringSecurityDescriptorToSecurityDescriptor(
                stringSecurityDescriptor,
                1,
                out securityDescriptorPtr,
                out securityDescriptorSize);
            if (!result) 
            {
                Console.WriteLine( 
                    "Fail to convert string SD to SD:" );
                throw new Win32Exception(
                    Marshal.GetLastWin32Error());
            }
        }

        private enum SecurityInformation : uint
        {
            OWNER_SECURITY_INFORMATION= 0x00000001,
            GROUP_SECURITY_INFORMATION= 0x00000002,
            DACL_SECURITY_INFORMATION= 0x00000004,
            SACL_SECURITY_INFORMATION= 0x00000008,
            PROTECTED_DACL_SECURITY_INFORMATION= 0x80000000,
            PROTECTED_SACL_SECURITY_INFORMATION= 0x40000000,
            UNPROTECTED_DACL_SECURITY_INFORMATION= 0x20000000,
            UNPROTECTED_SACL_SECURITY_INFORMATION= 0x10000000,
        };

        [DllImport("Advapi32.dll", CharSet=CharSet.Auto,
            SetLastError=true, ExactSpelling=false)]
        private static extern bool 
            ConvertSecurityDescriptorToStringSecurityDescriptor(
            [In] byte[] SecurityDescriptor,
            [In] int RequestedStringSDRevision,
            [In] SecurityInformation SecurityInformation,
            [Out] out IntPtr StringSecurityDescriptor,
            [Out] out int StringSecurityDescriptorLen
        );


        [DllImport("Advapi32.dll", CharSet=CharSet.Auto,
            SetLastError=true, ExactSpelling=false)]
        private static extern bool 
            ConvertStringSecurityDescriptorToSecurityDescriptor(
            [In] string StringSecurityDescriptor,
            [In] uint StringSDRevision,
            [Out] out IntPtr SecurityDescriptor,
            [Out] out int SecurityDescriptorSize
        );

        private void CreateTestNamespace()
        {
            ManagementClass rootNamespace = 
                new ManagementClass("root:__namespace");
            ManagementObject testNamespace = 
                rootNamespace.CreateInstance();
            testNamespace["Name"] = namespaceName;
            testNamespace.Put();
        }

        private void DeleteTestNamespace()
        {
            ManagementObject testNamespace = 
            new ManagementObject("root:__namespace.Name='" 
                + namespaceName + "'");
            try
            {
                testNamespace.Get();
                testNamespace.Delete();
            }
            catch (ManagementException e)
            {
                if (e.ErrorCode == ManagementStatus.NotFound)
                    return;
            }
        }

        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                new Sample().Run(); 
            }
            catch (Win32Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}

Compiling the Code

The example requires references to the System and System.Management namespaces.

See Also

Community Additions

ADD
Show:
© 2014 Microsoft