LsaOpenPolicy

C# Signature:

[DllImport("advapi32.dll", SetLastError=true, PreserveSig=true)]
static extern uint LsaOpenPolicy(
   ref LSA_UNICODE_STRING SystemName,
   ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
   uint DesiredAccess,
   out IntPtr PolicyHandle
);

VB Signature:

Declare Unicode Function LsaOpenPolicy Lib "advapi32.dll" ( _
    ByRef SystemName As LSA_UNICODE_STRING, _
    ByRef ObjectAttributes As LSA_OBJECT_ATTRIBUTES, _
    ByVal DesiredAccess As Int32, _
    ByRef PolicyHandle As IntPtr) As Int32

Sample Code:

public static uint SetRight( string inAccountName, string inPrivilegeName )
{
    uint aWinErrorCode = 0; //contains the last error

    //pointer an size for the SID
    IntPtr aSid = IntPtr.Zero;
    int aSidSize = 0;

    //StringBuilder and size for the domain name
    StringBuilder aDomainName = new StringBuilder();
    int aNameSize = 0;
    //account-type variable for lookup
    int aAccountType = 0;

    //get required buffer size
    LookupAccountName( String.Empty, inAccountName, aSid, ref aSidSize, aDomainName, ref aNameSize, ref aAccountType );

    //allocate buffers
    aDomainName = new StringBuilder( aNameSize );
    aSid = Marshal.AllocHGlobal( aSidSize );

    //lookup the SID for the account
    bool aResult = LookupAccountName( String.Empty, inAccountName, aSid, ref aSidSize, aDomainName, ref aNameSize, ref aAccountType );

    if ( aResult )
    {
        //initialize an empty unicode-string
        LSA_UNICODE_STRING aSystemName = new LSA_UNICODE_STRING();
        //combine all policies
        uint aAccess = (uint)(
            LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
            LSA_AccessPolicy.POLICY_CREATE_ACCOUNT |
            LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE |
            LSA_AccessPolicy.POLICY_CREATE_SECRET |
            LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION |
            LSA_AccessPolicy.POLICY_LOOKUP_NAMES |
            LSA_AccessPolicy.POLICY_NOTIFICATION | 
            LSA_AccessPolicy.POLICY_SERVER_ADMIN |
            LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS |
            LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
            LSA_AccessPolicy.POLICY_TRUST_ADMIN |
            LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION |
            LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
            );
        //initialize a pointer for the policy handle
        IntPtr aPolicyHandle = IntPtr.Zero;

        //these attributes are not used, but LsaOpenPolicy wants them to exists
        LSA_OBJECT_ATTRIBUTES aObjectAttributes = new LSA_OBJECT_ATTRIBUTES();
        aObjectAttributes.Length = 0;
        aObjectAttributes.RootDirectory = IntPtr.Zero;
        aObjectAttributes.Attributes = 0;
        aObjectAttributes.SecurityDescriptor = IntPtr.Zero;
        aObjectAttributes.SecurityQualityOfService = IntPtr.Zero;            

        //get a policy handle
        uint aOpenPolicyResult = LsaOpenPolicy(ref aSystemName, ref aObjectAttributes, aAccess, out aPolicyHandle);
        aWinErrorCode = LsaNtStatusToWinError( aOpenPolicyResult );

        if( aWinErrorCode == Win32Constants.STATUS_SUCCESS )
        {
            //Now that we have the SID an the policy,
            //we can add rights to the account.
            //initialize an unicode-string for the privilege name
            LSA_UNICODE_STRING[] aUserRightsLSAString = new LSA_UNICODE_STRING[1];
            aUserRightsLSAString[0] = new LSA_UNICODE_STRING();
            aUserRightsLSAString[0].Buffer = Marshal.StringToHGlobalUni( inPrivilegeName );
            aUserRightsLSAString[0].Length = ( UInt16 )( inPrivilegeName.Length * UnicodeEncoding.CharSize );
            aUserRightsLSAString[0].MaximumLength = ( UInt16 )( ( inPrivilegeName.Length + 1 ) * UnicodeEncoding.CharSize );

            //add the right to the account
            uint aLSAResult = LsaAddAccountRights( aPolicyHandle, aSid, aUserRightsLSAString, 1 );
            aWinErrorCode = LsaNtStatusToWinError( aLSAResult );

            LsaClose( aPolicyHandle );
        }
        FreeSid( aSid );

    }
    else
    {
        aWinErrorCode = (uint)GetLastError();
    }

    return aWinErrorCode;
}

Alternate Sample Code:

// This was started from the sample code above (which I originally found on code project).

    [StructLayout(LayoutKind.Sequential)]
    internal struct LSA_UNICODE_STRING
    {
        public UInt16 Length;
        public UInt16 MaximumLength;
        public IntPtr Buffer;

        public void SetTo(string str)
        {
            Buffer = Marshal.StringToHGlobalUni(str);
            Length = (UInt16)(str.Length * UnicodeEncoding.CharSize);
            MaximumLength = (UInt16)(Length + UnicodeEncoding.CharSize);
            //Console.WriteLine("SetTo: {2} ({3}) Length: {0} Max: {1}", Length, MaximumLength, str, str.Length);
        }

        public override string ToString()
        {
            string str = Marshal.PtrToStringUni(Buffer, Length/UnicodeEncoding.CharSize);
            //Console.WriteLine("ToString: {2} ({3}) Length: {0} Max: {1}", Length, MaximumLength, str, str.Length);
            return str;
        }

        public void Clean()
        {
            //Console.WriteLine("Clean Length: {0} Max: {1}", Length, MaximumLength);
            if (Buffer != IntPtr.Zero)
                Marshal.FreeHGlobal(Buffer);
            Buffer = IntPtr.Zero;
            Length = 0;
            MaximumLength = 0;
        }
    };

    public class LSAStringMarshaler : ICustomMarshaler
    {
        Hashtable myAllocated = new Hashtable();

        private static LSAStringMarshaler marshaler = new LSAStringMarshaler();
        public static ICustomMarshaler GetInstance(string cookie)
        {
            return marshaler;
        }

        public object MarshalNativeToManaged(System.IntPtr pNativeData)
        {
            if (pNativeData != IntPtr.Zero)
            {
                LSA_UNICODE_STRING lus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(pNativeData, typeof(LSA_UNICODE_STRING));
                return lus.ToString();
            }
            return null;
        }

        private static readonly int nativeSize = IntPtr.Size + sizeof(UInt16) + sizeof(UInt16);

        public System.IntPtr MarshalManagedToNative(object ManagedObj)
        {
            LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
            IntPtr memory = Marshal.AllocHGlobal(nativeSize);
            myAllocated[memory] = memory;
            //Console.WriteLine("MarshalManagedToNative");
            lus.SetTo((string)ManagedObj);
            Marshal.StructureToPtr(lus, memory, true);
            return memory;
        }

        public void CleanUpManagedData(object ManagedObj)
        {
            //Console.WriteLine("CCC Cleanup Managed Data");            
        }

        public int GetNativeDataSize()
        {
            return nativeSize;
        }

        public void CleanUpNativeData(System.IntPtr pNativeData)
        {            
            //Console.WriteLine("CCC Cleanup Native Data");            

            if (myAllocated.ContainsKey(pNativeData))
            {
                myAllocated.Remove(pNativeData);
                LSA_UNICODE_STRING lus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(pNativeData, typeof(LSA_UNICODE_STRING));
                lus.Clean();
                Marshal.FreeHGlobal(pNativeData);
            }
        }
    }

    public class LSAPolicy : IDisposable
    {
        private IntPtr policy;

        [Flags]
        public enum LSA_AccessPolicy : long
        {
            POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
            POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
            POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
            POLICY_TRUST_ADMIN = 0x00000008L,
            POLICY_CREATE_ACCOUNT = 0x00000010L,
            POLICY_CREATE_SECRET = 0x00000020L,
            POLICY_CREATE_PRIVILEGE = 0x00000040L,
            POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
            POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
            POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
            POLICY_SERVER_ADMIN = 0x00000400L,
            POLICY_LOOKUP_NAMES = 0x00000800L,
            POLICY_NOTIFICATION = 0x00001000L
        }

Alternate Sample Code:

public LSAPolicy() : this (
            LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
            LSA_AccessPolicy.POLICY_CREATE_ACCOUNT |
            LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE |
            LSA_AccessPolicy.POLICY_CREATE_SECRET |
            LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION |
            LSA_AccessPolicy.POLICY_LOOKUP_NAMES |
            LSA_AccessPolicy.POLICY_NOTIFICATION |
            LSA_AccessPolicy.POLICY_SERVER_ADMIN |
            LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS |
            LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
            LSA_AccessPolicy.POLICY_TRUST_ADMIN |
            LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION |
            LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
            )
        {}

        public LSAPolicy(LSA_AccessPolicy access)
        {
            //initialize an empty unicode-string
            string systemName = null;

            //these attributes are not used, but LsaOpenPolicy wants them to exist
            // (MSDN: "the structure members are not used, initalize them to NULL or zero")
            LSA_OBJECT_ATTRIBUTES ObjectAttributes = new LSA_OBJECT_ATTRIBUTES();
            ObjectAttributes.Length = 0;
            ObjectAttributes.RootDirectory = IntPtr.Zero;
            ObjectAttributes.Attributes = 0;
            ObjectAttributes.SecurityDescriptor = IntPtr.Zero;
            ObjectAttributes.SecurityQualityOfService = IntPtr.Zero;

            //get a policy handle
            UInt32 resultPolicy = LsaOpenPolicy(ref systemName, ref ObjectAttributes, (int)access, out policy);
            UInt32 winErrorCode = LsaNtStatusToWinError(resultPolicy);

            if (winErrorCode != 0)
            {
                throw new Win32Exception(winErrorCode, "OpenPolicy failed: ");
            }

        }

        ~LSAPolicy()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Dispose(bool disposing)
        {
            if (policy != IntPtr.Zero)
            {
                LsaClose(policy);
                policy = IntPtr.Zero;
            }
        }

        public string RetrievePrivateData(string key)
        {
            string result = null;
            UInt32 ntstatus = LsaRetrievePrivateData(policy, key, ref result);
            UInt32 winErrorCode = LsaNtStatusToWinError(ntstatus);
            if (winErrorCode != 0)
            {
                throw new Exception("RetreivePrivateData failed: " + winErrorCode);
            }
            return result;
        }

        public void StorePrivateData(string key, string value)
        {
            UInt32 ntstatus = LsaStorePrivateData(policy, key, value);
            UInt32 winErrorCode = LsaNtStatusToWinError(ntstatus);
            if (winErrorCode != 0)
            {
                throw new Exception("RetreivePrivateData failed: " + winErrorCode);
            }
        }

        [DllImport("advapi32.dll")]
        private static extern UInt32 LsaRetrievePrivateData(
            IntPtr policyHandle,
            [MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef=typeof(LSAStringMarshaler))] string KeyName,
            [MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef=typeof(LSAStringMarshaler))] ref string PrivateData
        );

        [DllImport("advapi32.dll")]
        private static extern uint LsaStorePrivateData(
        IntPtr policyHandle,
            [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LSAStringMarshaler))]  string KeyName,
            [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LSAStringMarshaler))]  string PrivateData
        );

        [DllImport("advapi32.dll")]
        private static extern long LsaClose(IntPtr ObjectHandle);

        [StructLayout(LayoutKind.Sequential)]
        private struct LSA_OBJECT_ATTRIBUTES
        {
            public int Length;
            public IntPtr RootDirectory;
            public LSA_UNICODE_STRING ObjectName;
            public UInt32 Attributes;
            public IntPtr SecurityDescriptor;
            public IntPtr SecurityQualityOfService;
        }

        [DllImport("advapi32.dll", PreserveSig=true)]
        private static extern UInt32 LsaOpenPolicy(
            [MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef=typeof(LSAStringMarshaler))] ref string SystemName,
            ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
            Int32 DesiredAccess,
            out IntPtr PolicyHandle
        );

        [DllImport("advapi32.dll")]
        private static extern UInt32 LsaNtStatusToWinError(UInt32 status);

    }

VB.Net Sample Code:

' Check to see if the Deny permission already exists
    Public Function CheckTS(ByVal PC As String) As Boolean
    Dim ret, Access, sidsize, count, i As Integer
    Dim SystemName, DenyTSRights As LSA_UNICODE_STRING
    Dim ObjectAttr As LSA_OBJECT_ATTRIBUTES
    Dim Policy, EveryoneSID, EnumBuf, ptr As IntPtr
    Dim LsaInfo As LSA_ENUMERATION_INFORMATION
    Dim ans As Boolean

    ' build a well-known SID for "Everyone"
    sidsize = SECURITY_MAX_SID_SIZE
    EveryoneSID = Marshal.AllocHGlobal(sidsize)
    If CreateWellKnownSid(WinWorldSid, IntPtr.Zero, EveryoneSID, sidsize) = False Then
        ret = Marshal.GetLastWin32Error()
        Throw New Win32Exception(ret)
    End If

    ' setup the parameters for the LsaOpenPolicy API
    ObjectAttr.Length = Marshal.SizeOf(ObjectAttr)
    SystemName.Length = PC.Length * UnicodeEncoding.CharSize
    SystemName.MaximumLength = (PC.Length + 1) * UnicodeEncoding.CharSize
    SystemName.Buffer = Marshal.StringToHGlobalUni(PC)
    Access = POLICY_ALL_ACCESS

    ' open a policy handle on the remote PC
    ret = LsaOpenPolicy(SystemName, ObjectAttr, Access, Policy)
    If ret <> 0 Then
        Throw New Win32Exception(LsaNtStatusToWinError(ret))
    End If

    ' clean up
    Marshal.FreeHGlobal(SystemName.Buffer)

    ' Setup the input parameters for the LsaEnumerateAccountsWithUserRight API
    DenyTSRights.Length = SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME.Length * UnicodeEncoding.CharSize
    DenyTSRights.MaximumLength = (SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME.Length + 1) * UnicodeEncoding.CharSize
    DenyTSRights.Buffer = Marshal.StringToHGlobalUni(SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME)

    ' do it!
    ret = LsaEnumerateAccountsWithUserRight(Policy, DenyTSRights, EnumBuf, count)
    If ret <> 0 Then
        Marshal.FreeHGlobal(DenyTSRights.Buffer)
        LsaClose(Policy)
        ' if there are no matching entries
        If ret = STATUS_NO_MORE_ENTRIES Then
        Return False
        End If
        Throw New Win32Exception(LsaNtStatusToWinError(ret))
    End If

    ' check to see if the Everyone SID is currently in the list
    ans = False
    For i = 0 To count - 1
        ptr = New IntPtr(EnumBuf.ToInt32 + (i * Marshal.SizeOf(LsaInfo)))
        LsaInfo = CType(Marshal.PtrToStructure(ptr, GetType(LSA_ENUMERATION_INFORMATION)), LSA_ENUMERATION_INFORMATION)
        If EqualSid(LsaInfo.Sid, EveryoneSID) Then
        ans = True
        Exit For
        End If
    Next

    ' clean up
    LsaFreeMemory(EnumBuf)
    Marshal.FreeHGlobal(DenyTSRights.Buffer)
    LsaClose(Policy)

    Return ans
    End Function

Última actualización