4

ファイルにSECURITY_IDENTIFIER構造のオブジェクトがあります。この構造から所有者SIDを取得する必要があります。これを行うために、GetSecurityDescriptorOwnerWinAPI関数を呼び出して作成しますSystem.Security.Principal.SecurityIdentifier(IntPtrを引数としてオーバーロードします)

問題は、ファイル内のこの構造が時々壊れているため、GetSecurityDescriptorOwnerから取得したポインターが無効であるということです。これはIntPtr.Zeroではなく、無効であるため、タイプのオブジェクトを作成すると、SecurityIdentifierが取得されますAccessViolationException。これは、単純なtry-catchでは.NET4ではキャッチできません。

私はそのような例外を捕らえることができる属性を知っているので、当分の間それを使用しましたが、私はこの解決策が好きではありません。Corrupted State Exceptions(CSE)をキャッチすることはお勧めしませんが、他の解決策はありません。このWinAPI関数は無効なポインタを返し、有効性を確認する方法がわかりません。何か案は?

アップデート

WinAPI

BOOL WINAPI GetSecurityDescriptorOwner(
  _In_   PSECURITY_DESCRIPTOR pSecurityDescriptor,
  _Out_  PSID *pOwner,
  _Out_  LPBOOL lpbOwnerDefaulted
);

外部定義

[DllImport("Advapi32.dll")]
static extern bool GetSecurityDescriptorOwner(
   IntPtr pSecurityDescriptor,
   out IntPtr owner,
   out bool defaulted);

アップデート

private static SecurityIdentifier GetSecurityIdentifier()
{
    // Allocate managed buffer for invalid security descriptor structure (20 bytes)
    int[] b = new int[5] {1, 1, 1, 1, 1};

    // Allocate unmanaged memory for security descriptor 
    IntPtr descriptorPtr = Marshal.AllocHGlobal(b.Length);

    // Copy invalid security descriptor structure to the unmanaged buffer
    Marshal.Copy(b, 0, descriptorPtr, b.Length);

    IntPtr ownerSid;
    bool defaulted;

    if (GetSecurityDescriptorGroup(descriptorPtr, out ownerSid, out defaulted))
    {
        // GetSecurityDescriptorGroup returns true, but `ownerSid` is `1`
        // Marshal.GetLastWin32Error returns 0 here
        return new SecurityIdentifier(ownerSid);
    }

    return null;
}

このコードは、SecurityIdentifierコンストラクターからCorruptedStateExceptionsをスローすることがあります。解決策はありますか?

4

2 に答える 2

1

電話してみましたIsValidSecurityDescriptorか?

[DllImport("Advapi32.dll")]
static extern bool IsValidSecurityDescriptor(IntPtr pSecurityDescriptor);


if (IsValidSecurityDescriptor(descriptorPtr) && 
    GetSecurityDescriptorOwner(descriptorPtr, out ownerSid, out defaulted))
{
     return new SecurityIdentifier(ownerSid);
}
于 2012-09-07T07:41:55.487 に答える
0

更新しました:

代わりにこれを試してください:

    [DllImport("Advapi32.dll")]
    static extern bool GetSecurityDescriptorOwner(
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)]
       Int32[] securityDescriptor,
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] 
       out Byte[] owner,
       out Boolean defaulted);


    [DllImport("Advapi32.dll")]
    static extern bool IsValidSecurityDescriptor(
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] 
        Int32[] securityDescriptor);

    private static SecurityIdentifier GetSecurityIdentifier()
    {
        // Allocate managed buffer for invalid security descriptor structure (20 bytes)
        Int32[] b = new[] { 1, 1, 1, 1, 1 };

        Byte[] ownerSid;
        bool defaulted;

        if (IsValidSecurityDescriptor(b) &&
            GetSecurityDescriptorOwner(b, out ownerSid, out defaulted))
        {
            return new SecurityIdentifier(ownerSid, 0);
        }

        return null;
    }

    static void Main()
    {
        for (Int32 index = 0; index < 1000; index++)
        {
            SecurityIdentifier identifier = GetSecurityIdentifier();
            String text = identifier == null ? "(none)" : identifier.Value;
            Console.WriteLine(text);
        }

        Console.ReadKey();
    }
于 2012-09-06T19:22:32.487 に答える