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
};
}
}