Click here to Skip to main content
15,896,726 members
Articles / Programming Languages / C#

WMI Namespace Security

Rate me:
Please Sign up or sign in to vote.
4.70/5 (13 votes)
4 Dec 2006CPOL15 min read 132.4K   3.5K   35  
Describes WMI namespace security, and introduces code to review and modify WMI Namespace security.
using System;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;

namespace WmiSecurity
{
	/// <summary>
	/// Provides methods and data to modify WMI namespace security.
	/// </summary>
	sealed public class ChangeNameSpaceSecurity : NameSpaceSecurity
	{
		private bool m_bAccessAllowed;					// Access allowed ACE or Access Denied?
		private uint m_uiAceFlags;						// Access mask for trustee, defined in AceString class
		private bool m_bInit;							// Object initialization OK?
		private bool m_bRecursive;

		public ChangeNameSpaceSecurity(string name, bool recursive):base(name)
		{
			m_bAccessAllowed=true;
			m_uiAceFlags=0;
			m_bRecursive=recursive;
			m_bInit=false;
		}
		
		public void setAceFlags(bool bAccessAllowed, uint aceFlags)
		{
			m_bInit=false;
			m_bAccessAllowed=bAccessAllowed;
			m_uiAceFlags=aceFlags;
			if(m_sNameSpace.Length > 0)
				 m_bInit=true;
		}

		
		public void Modify(string sComputer, string sTrusteeSid)
		{
			if(m_bInit==false)
				throw new Exception("Failure to set Namespace or Ace Flags information");

			IntPtr pStringSD = IntPtr.Zero;				// ptr to string Security Descriptor
			IntPtr pSystemSD = IntPtr.Zero;				// ptr to system Security Descriptor
			int iStringSDSize = 0;						// size of string Security Descriptor
			int iSystemSDSize = 0;						// size of system Security Descriptor
			string stringSD;							// string representation of system Security Descriptor
			int iError;									// Win32 error
			bool bRes;									// Boolean result


			try
			{
				connectToComputer(sComputer);
			}
			catch(Exception ex)
			{
				throw new Exception("ChangeNamespaceSecurity.Modify Error: " + ex.Message);
			}
			
			Console.WriteLine("Connected to " + "\\\\" + sComputer);

			try
			{
				AceStringManager asm = new AceStringManager(sTrusteeSid, this.m_bAccessAllowed, this.m_bRecursive);
				string sddl=asm.ReturnAceString(this.m_uiAceFlags);

				// Retrieve SD of a namespace
				ManagementPath mp = new ManagementPath(m_sNameSpace + ":__SystemSecurity");
				ObjectGetOptions options = new ObjectGetOptions(null, new TimeSpan(0, 0, 0, 25), true);
				ManagementClass systemSecurity = new ManagementClass(m_ms, mp, options);
				try
				{
					ManagementBaseObject outParams = systemSecurity.InvokeMethod("GetSD", null, null);
					if ((uint)outParams["ReturnValue"] != 0)
					{
						throw new Exception("ChangeNamespaceSecurity.Modify error, GetSD returns: " + outParams["ReturnValue"]);
					}    

					// Convert SD from SECURITY_DESCRIPTOR structure format to a string we can view
					
					bRes = ConvertSecurityDescriptorToStringSecurityDescriptor((byte[])outParams["SD"], 1,
						SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | 
						SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION |
						SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION |
						SECURITY_INFORMATION.SACL_SECURITY_INFORMATION,
						out pStringSD, out iStringSDSize);

					if (!bRes) 
					{
						iError=Marshal.GetLastWin32Error();
						throw new Exception("ConvertSecurityDescriptorToStringSecurityDescriptor API Error: " + iError);
					}

					stringSD=Marshal.PtrToStringAuto(pStringSD);
				
					Console.WriteLine("Original {0} namespace security:", m_sNameSpace);
					Console.WriteLine(stringSD);
	                
					stringSD += "(" + sddl + ")";

					// Convert SD from a string back to SECURITY_DESCRIPTOR structure format the OS can use

					bRes = ConvertStringSecurityDescriptorToSecurityDescriptor(stringSD, 1, out pSystemSD, 
						out iSystemSDSize);

					if (!bRes) 
					{
						iError=Marshal.GetLastWin32Error();
						throw new Exception("ConvertStringSecurityDescriptorToSecurityDescriptor API Error: " + iError);
					}

					byte[] securityDescriptor = new byte[iSystemSDSize];
					Marshal.Copy(pSystemSD,securityDescriptor, 0, iSystemSDSize);

					//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)	
					{
						throw new Exception("ChangeNamespaceSecurity.Modify error, SetSD returns: " + outParams["ReturnValue"]);
					}
					Console.WriteLine("\nNew string security descriptor has been set");
				}
				catch (Exception ex)
				{
					throw new Exception("ChangeNamespaceSecurity.Modify error: " + ex.Message);
				}
				finally
				{
					systemSecurity.Dispose();
				}
			}
			finally
			{
				// Free unmanaged memory
				if (pSystemSD != IntPtr.Zero)
				{
					//Free from global heap
					Marshal.FreeHGlobal(pSystemSD);
					// set ptr to zero
					pSystemSD = IntPtr.Zero;
				}
				if (pStringSD != IntPtr.Zero)
				{
					Marshal.FreeHGlobal(pStringSD);
					pStringSD = IntPtr.Zero;
				}
			}
		}
/*-----------------------------------------------------------------------------
						getSidStringFromName
						
Given a string representing the account name, return back a SID in string format.
  
-----------------------------------------------------------------------------*/

		public string getSidStringFromName(string sAccount)
		{
			StringBuilder sbDomain;				// Domain name.
			Int32 iDomainSize;					// Domain name size.
			Int32 iSidSize;						// Size of the returned SID.
			IntPtr pAccountSid = IntPtr.Zero;	// Sid of account
			IntPtr pSid = IntPtr.Zero;			// Set ptr to zero.
			int iError;							// API error			
			SID_NAME_USE snu;  
			string sSid = "";

			iSidSize=0;
			sbDomain = new StringBuilder();
			iDomainSize=0;
			

			// The 1st time this will fail, but we can then alloc necessary sid buffer size
			LookupAccountName(null, sAccount, pAccountSid, ref iSidSize, sbDomain, ref iDomainSize, out snu);

			pAccountSid=Marshal.AllocHGlobal(iSidSize);

			// Try a 2nd time with proper buffer size...
			if(!LookupAccountName(null, sAccount, pAccountSid, ref iSidSize, sbDomain, ref iDomainSize, out snu))
			{
				iError=Marshal.GetLastWin32Error();
				// free up allocation
				Marshal.FreeHGlobal(pAccountSid);
				throw new Exception("LookupAccountName error: " + iError.ToString());
			}
			else
			{
				if(!ConvertSidToStringSid(pAccountSid, ref sSid))
				{
					iError=Marshal.GetLastWin32Error();
					// free up allocation
					Marshal.FreeHGlobal(pAccountSid);
					throw new Exception("ConvertSidToStringSid error: " + iError.ToString());
				}
			}

			Marshal.FreeHGlobal(pAccountSid);
			return sSid;
		}

		/*-----------------------------------------------------
		 Interop structures and functions
		-----------------------------------------------------*/

		[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
			);

		// Get SID of given trustee
		[DllImport("AdvAPI32.DLL", CharSet=CharSet.Auto, SetLastError=true )]
		public static extern Boolean LookupAccountName(String lpSystemName, String lpAccountName,
			IntPtr Sid, ref Int32 cbSid, StringBuilder ReferencedDomainName,
			ref Int32 cchReferencedDomainName, out SID_NAME_USE peUse);

		// Get string SID equivilent of SID structure
		[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		internal static extern bool ConvertSidToStringSid(IntPtr sid,
			[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);

		// This enumeration determines the use of the account.
		public enum SID_NAME_USE 
		{
			SidTypeUser = 1,
			SidTypeGroup,
			SidTypeDomain,
			SidTypeAlias,
			SidTypeWellKnownGroup,
			SidTypeDeletedAccount,
			SidTypeInvalid,
			SidTypeUnknown,
			SidTypeComputer
		};
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Software developer for the past 10 years in the Windows environment. Married, with two teenagers, and no money!

Comments and Discussions