2011-04-11 3 views
1

P/Invoke를 사용하여 .NET에서 SetEntriesInAcl 메소드를 호출하는 작업 예제가 있습니까?작동중인 SetEntriesInAcl interop을 사용하는 작동중인 .NET 예제

호출 할 때 87 오류가 계속 발생하고 잘못된 결과를 얻을 수 없습니다. 여기

내 정의입니다 :

다음
private enum FileAccessRights 
{ 
    FILE_READ_DATA = 0x0001, 
} 
private enum AccessMode 
{ 
    GRANT_ACCESS = 1, 
    REVOKE_ACCESS = 4, 
} 

private enum InheritanceFlags 
{ 
    NO_INHERITANCE = 0x0, 
} 

private enum TrusteeForm 
{ 
    TRUSTEE_IS_SID = 0, 
} 

private enum TrusteeType 
{ 
    TRUSTEE_IS_USER = 1, 
} 
private struct ExplicitAccess 
{ 
    public FileAccessRights AccessPermissions; 
    public AccessMode AccessMode; 
    public InheritanceFlags Inheritance; 
    public Trustee Trustee; 
} 

private struct Trustee 
{ 
    public IntPtr MultipleTrustee; 
    public int MultipleTrusteeOperation; 
    public TrusteeForm TrusteeForm; 
    public TrusteeType TrusteeType; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string Name; 
} 
[DllImport("advapi32.dll", SetLastError = true)] 
static extern int SetEntriesInAcl(int countOfExplicitEntries, ref ExplicitAccess explicitEntry, IntPtr oldAcl, out IntPtr newAcl); 

내가 그것을 호출하는 방법입니다

SecurityIdentifier sid = GetSid(); 
    var ea = new ExplicitAccess 
    { 
     AccessPermissions = FileAccessRights.FILE_READ_DATA, 
     AccessMode = AccessMode.GRANT_ACCESS, 
     Inheritance = InheritanceFlags.NO_INHERITANCE, 
     Trustee = new Trustee 
     { 
     TrusteeForm = TrusteeForm.TRUSTEE_IS_SID, 
     TrusteeType = TrusteeType.TRUSTEE_IS_USER, 
     Name = sid.Value 
     } 
    }; 

    IntPtr newAcl; 
    int res = SetEntriesInAcl(1, ref ea, currentAcl, out newAcl); 

I 오류 87 (잘못된 매개 변수)를 얻고 유지하고 이유를 알고하지 않습니다.

앞서 모든 선한 사마리아 인에게 감사드립니다.

EDIT1는

내가 ACL을 변경하기위한 새로운 관리 API를 사용 기쁠 것, 누군가가 나 표시되면 어떻게 인증서와 관련된 개인 키 컨테이너의 ACL을 수정해야하는 경우에. 이 시나리오에서 관리되는 API를 사용하는 방법이 명확하지 않습니다.

답변

0

Interop 호출을 통해이 작업을 수행해야한다는 동일한 요구 사항이있었습니다. (실패, 같은 근본적인 이유 다른 오류 코드) Using SetEntriesInAcl in C# : error 1332

그것은 유니 코드 지원 대 ANSI과 관련이있다

을 당신이 필요합니다 : 나는 관련 대답이있는 내가 여기에 검색하고 발견 P-Invoke 메서드 정의에서 올바른 CharSet을 사용합니다.

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
static extern uint SetEntriesInAcl(
    int cCountOfExplicitEntries, 
    ref EXPLICIT_ACCESS pListOfExplicitEntries, 
    IntPtr OldAcl, 
    out IntPtr NewAcl); 

또 다른 확실한 점은 CharSet이 모든 구조체 및 메서드 정의에 대해 일관성이 있다는 것입니다. 실제로 우리의 서비스는 유니 코드 문자 집합을 모두 지원하는 서버에서 실행되기 때문에 CharSet를 CharSet.Unicode로 변경했습니다.

또한 문자열 매개 변수를 정렬하는 관리되지 않는 유형이 유니 코드 문자 집합 (예 : C++/네이티브의 와이드 char 유형)과 일치해야합니다. 아래에서는 UnmanagedType.LPWStr을 사용합니다.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
internal struct TRUSTEE 
{ 
    public IntPtr MultipleTrustee; 
    public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation; 
    public TRUSTEE_FORM TrusteeForm; 
    public TRUSTEE_TYPE TrusteeType; 
    [MarshalAs(UnmanagedType.LPWStr)] public string Name; 
} 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
internal static extern uint GetNamedSecurityInfo(
    [MarshalAs(UnmanagedType.LPWStr)] string pObjectName, 
    SE_OBJECT_TYPE ObjectType, 
    SECURITY_INFORMATION SecurityInfo, 
    out IntPtr pSidOwner, 
    out IntPtr pSidGroup, 
    out IntPtr pDacl, 
    out IntPtr pSacl, 
    out IntPtr pSecurityDescriptor); 

(이것은 공유 경로에 대한 권한을 설정하는 코드를 작업을위한 것입니다 그러나 당신이 당신이 필요로 얻을 도움이 될 수 있습니다) :

public static void SetReadOnlySharePermissions(string serverName, string shareName, string wellKnownGroupName, DfsSharePermission permissions) 
    { 
     IntPtr sidOwnerPtr = IntPtr.Zero; 
     IntPtr groupOwnerPtr = IntPtr.Zero; 
     IntPtr saclPtr = IntPtr.Zero; 
     IntPtr oldDacl = IntPtr.Zero; 
     IntPtr oldSecurityDescriptor = IntPtr.Zero; 
     string shareObjectName = [email protected]"\\{serverName}\{shareName}"; 

     uint securityObjectQueryResult = NetShareInterop.GetNamedSecurityInfo(
      shareObjectName, 
      NetShareInterop.SE_OBJECT_TYPE.SE_LMSHARE, 
      NetShareInterop.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, 
      out sidOwnerPtr, 
      out groupOwnerPtr, 
      out oldDacl, 
      out saclPtr, 
      out oldSecurityDescriptor); 

     if (securityObjectQueryResult != 0) 
     { 
      throw new Win32Exception((int)securityObjectQueryResult); 
     } 

     // Default permissions = ReadOnly 
     uint shareAccessPermissions = (uint)NetShareInterop.ACCESS_MASK.SHARE_ACCESS_READ; 
     switch (permissions) 
     { 
      case DfsSharePermission.FullControl: 
       shareAccessPermissions = (uint)NetShareInterop.ACCESS_MASK.SHARE_ACCESS_FULL; 
       break; 
      case DfsSharePermission.ReadWrite: 
       shareAccessPermissions = (uint)NetShareInterop.ACCESS_MASK.SHARE_ACCESS_WRITE; 
       break; 
     } 

     NetShareInterop.EXPLICIT_ACCESS access = new NetShareInterop.EXPLICIT_ACCESS() 
     { 
      AccessMode = (uint)NetShareInterop.ACCESS_MODE.SET_ACCESS, 
      AccessPermissions = shareAccessPermissions, 
      Inheritance = (uint)NetShareInterop.ACCESS_INHERITANCE.SUB_CONTAINERS_AND_OBJECTS_INHERIT, 
      trustee = new NetShareInterop.TRUSTEE() 
      { 
       Name = wellKnownGroupName, 
       TrusteeForm = NetShareInterop.TRUSTEE_FORM.TRUSTEE_IS_NAME, 
       TrusteeType = NetShareInterop.TRUSTEE_TYPE.TRUSTEE_IS_WELL_KNOWN_GROUP 
      } 
     }; 

     IntPtr newDacl; 
     int initializeAclEntriesResult = NetShareInterop.SetEntriesInAcl(1, ref access, oldDacl, out newDacl); 
     if (initializeAclEntriesResult != 0) 
     { 
      throw new Win32Exception(initializeAclEntriesResult); 
     } 

     uint setSecurityResult = NetShareInterop.SetNamedSecurityInfo(
      shareObjectName, 
      NetShareInterop.SE_OBJECT_TYPE.SE_LMSHARE, 
      NetShareInterop.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, 
      IntPtr.Zero, 
      IntPtr.Zero, 
      newDacl, 
      IntPtr.Zero); 

     if (setSecurityResult != 0) 
     { 
      throw new Win32Exception((int)setSecurityResult); 
     } 
    } 

(.. 그리고 당신은 왜 모든 발굴하기 그 바보 interop 열거 형 및 구조체 정의?)

internal static class NetShareInterop 
{ 
    private const CharSet DefaultCharSet = CharSet.Unicode; 

    internal enum ACCESS_MODE : uint 
    { 
     NOT_USED_ACCESS = 0, 
     GRANT_ACCESS, 
     SET_ACCESS, 
     REVOKE_ACCESS, 
     SET_AUDIT_SUCCESS, 
     SET_AUDIT_FAILURE 
    } 

    internal enum ACCESS_MASK : uint 
    { 
     GENERIC_ALL = 0x10000000, //268435456, 
     GENERIC_READ = 0x80000000, //2147483648L, 
     GENERIC_WRITE = 0x40000000, //1073741824, 
     GENERIC_EXECUTE = 0x20000000, //536870912, 
     STANDARD_RIGHTS_READ = 0x00020000, //131072 
     STANDARD_RIGHTS_WRITE = 0x00020000, 
     SHARE_ACCESS_READ = 0x1200A9, // 1179817 
     SHARE_ACCESS_WRITE = 0x1301BF, // 1245631 
     SHARE_ACCESS_FULL = 0x1f01ff // 2032127 
    } 

    internal enum ACCESS_INHERITANCE : uint 
    { 
     NO_INHERITANCE = 0, 
     OBJECT_INHERIT_ACE = 0x1, 
     CONTAINER_INHERIT_ACE = 0x2, 
     NO_PROPAGATE_INHERIT_ACE = 0x4, 
     INHERIT_ONLY_ACE = 0x8, 
     INHERITED_ACE = 0x10, 
     SUB_OBJECTS_ONLY_INHERIT = ACCESS_INHERITANCE.OBJECT_INHERIT_ACE | ACCESS_INHERITANCE.INHERIT_ONLY_ACE, 
     SUB_CONTAINERS_ONLY_INHERIT = ACCESS_INHERITANCE.CONTAINER_INHERIT_ACE | ACCESS_INHERITANCE.INHERIT_ONLY_ACE, 
     SUB_CONTAINERS_AND_OBJECTS_INHERIT = ACCESS_INHERITANCE.CONTAINER_INHERIT_ACE | ACCESS_INHERITANCE.OBJECT_INHERIT_ACE, 
    } 

    internal enum MULTIPLE_TRUSTEE_OPERATION 
    { 
     NO_MULTIPLE_TRUSTEE, 
     TRUSTEE_IS_IMPERSONATE 
    } 

    internal enum NetError : uint 
    { 
     NERR_Success = 0, 
     NERR_UnknownDevDir = 0x00000844, 
     NERR_RedirectedPath = 0x00000845, 
     NERR_DuplicateShare = 0x00000846, 
     NERR_NetNameNotFound = 0x00000906, 
     NERR_DfsNoSuchVolume = 0x00000A66 
    } 

    internal enum SE_OBJECT_TYPE 
    { 
     SE_UNKNOWN_OBJECT_TYPE = 0, 
     SE_FILE_OBJECT, 
     SE_SERVICE, 
     SE_PRINTER, 
     SE_REGISTRY_KEY, 
     SE_LMSHARE, 
     SE_KERNEL_OBJECT, 
     SE_WINDOW_OBJECT, 
     SE_DS_OBJECT, 
     SE_DS_OBJECT_ALL, 
     SE_PROVIDER_DEFINED_OBJECT, 
     SE_WMIGUID_OBJECT, 
     SE_REGISTRY_WOW64_32KEY 
    } 

    [Flags] 
    internal enum SECURITY_INFORMATION : uint 
    { 
     OWNER_SECURITY_INFORMATION = 0x00000001, 
     GROUP_SECURITY_INFORMATION = 0x00000002, 
     DACL_SECURITY_INFORMATION = 0x00000004, 
     SACL_SECURITY_INFORMATION = 0x00000008, 
     UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000, 
     UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000, 
     PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000, 
     PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 
    } 

    internal enum SHARE_TYPE : uint 
    { 
     STYPE_DISKTREE = 0, 
     STYPE_PRINTQ = 1, 
     STYPE_DEVICE = 2, 
     STYPE_IPC = 3, 
     STYPE_TEMPORARY = 0x40000000, 
     STYPE_SPECIAL = 0x80000000, 
    } 

    internal enum TRUSTEE_FORM 
    { 
     TRUSTEE_IS_SID = 0, 
     TRUSTEE_IS_NAME, 
     TRUSTEE_BAD_FORM, 
     TRUSTEE_IS_OBJECTS_AND_SID, 
     TRUSTEE_IS_OBJECTS_AND_NAME 
    } 

    internal enum TRUSTEE_TYPE 
    { 
     TRUSTEE_IS_UNKNOWN = 0, 
     TRUSTEE_IS_USER, 
     TRUSTEE_IS_GROUP, 
     TRUSTEE_IS_DOMAIN, 
     TRUSTEE_IS_ALIAS, 
     TRUSTEE_IS_WELL_KNOWN_GROUP, 
     TRUSTEE_IS_DELETED, 
     TRUSTEE_IS_INVALID, 
     TRUSTEE_IS_COMPUTER 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = DefaultCharSet)] 
    internal struct SHARE_INFO_502 
    { 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_netname; 
     public SHARE_TYPE shi502_type; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_remark; 
     public int shi502_permissions; 
     public int shi502_max_uses; 
     public int shi502_current_uses; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_path; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_passwd; 
     public int shi502_reserved; 
     public IntPtr shi502_security_descriptor; 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = DefaultCharSet)] 
    internal struct EXPLICIT_ACCESS 
    { 
     public uint AccessPermissions; 
     public uint AccessMode; 
     public uint Inheritance; 
     public TRUSTEE trustee; 
    } 

    //Platform independent (32 & 64 bit) - use Pack = 0 for both platforms. IntPtr works as well. 
    [StructLayout(LayoutKind.Sequential, CharSet = DefaultCharSet)] 
    internal struct TRUSTEE 
    { 
     public IntPtr MultipleTrustee; 
     public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation; 
     public TRUSTEE_FORM TrusteeForm; 
     public TRUSTEE_TYPE TrusteeType; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string Name; 
    } 

    [DllImport("advapi32.dll", CharSet = DefaultCharSet, SetLastError = true)] 
    internal static extern uint GetNamedSecurityInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string pObjectName, 
     SE_OBJECT_TYPE ObjectType, 
     SECURITY_INFORMATION SecurityInfo, 
     out IntPtr pSidOwner, 
     out IntPtr pSidGroup, 
     out IntPtr pDacl, 
     out IntPtr pSacl, 
     out IntPtr pSecurityDescriptor); 

    [DllImport("Netapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    internal static extern NetError NetShareAdd(

     [MarshalAs(UnmanagedType.LPWStr)] string strServer, 
     Int32 dwLevel, 
     ref SHARE_INFO_502 buf, 
     out uint parm_err 
    ); 

    [DllImport("netapi32.dll", CharSet = DefaultCharSet, SetLastError = true)] 
    internal static extern NetError NetShareDel(
     [MarshalAs(UnmanagedType.LPWStr)] string strServer, 
     [MarshalAs(UnmanagedType.LPWStr)] string strNetName, 
     int reserved //must be 0 
    ); 

    [DllImport("advapi32.dll", CharSet = DefaultCharSet, SetLastError = true)] 
    internal static extern uint SetNamedSecurityInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string pObjectName, 
     SE_OBJECT_TYPE ObjectType, 
     SECURITY_INFORMATION SecurityInfo, 
     IntPtr psidOwner, 
     IntPtr psidGroup, 
     IntPtr pDacl, 
     IntPtr pSacl); 

    [DllImport("advapi32.dll", CharSet = DefaultCharSet, SetLastError = true)] 
    internal static extern int SetEntriesInAcl(
     int cCountOfExplicitEntries, 
     ref EXPLICIT_ACCESS pListOfExplicitEntries, 
     IntPtr OldAcl, 
     out IntPtr NewAcl); 
} 
1

Interop 질문에 대한 답변이 없지만 .Net은 이제 System.Security.AccessControl 네임 스페이스를 사용하여 관리되는 코드에서 ACL을 지원합니다. 예를 들어 http://msdn.microsoft.com/en-us/library/ms229078.aspx을 참조하십시오.

이것은 자신의 interop을 돌리는 것보다 사용하기가 더 쉽습니다.

+0

좋은. 인증서와 연결된 개인 키 컨테이너의 ACL을 수정해야합니다. 이 시나리오에서 관리되는 API를 사용하는 방법이 명확하지 않습니다. – mark

+0

+1 나를 더 멀리보고 이끌어 내고 - http : // stackoverflow.co.kr/questions/425688/set-to-the-private-key-file-of-x-509-net에서 인증서 읽기 권한 설정 – mark

관련 문제