有没有人有一个使用P / Invoke在.NET中调用SetEntriesInAcl方法的工作示例?
我在调用时一直收到错误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);
我一直收到错误87(参数无效),不知道为什么。
非常感谢所有好撒玛利亚人。
EDIT1
如果有人告诉我如何修改与证书关联的私钥容器的Acl,我将很高兴使用新的托管API来更改Acl。目前还不清楚如何在这种情况下使用托管API。
答案 0 :(得分:1)
我对你的Interop问题没有答案,但.Net现在使用System.Security.AccessControl命名空间支持托管代码中的ACL。有关示例,请参阅http://msdn.microsoft.com/en-us/library/ms229078.aspx。
这可能比滚动您自己的互操作更容易使用。
答案 1 :(得分:0)
我有同样的要求通过Interop调用来做到这一点。我找到了我在这里搜索的相关答案:
(不同的错误代码,失败的相同根本原因) Using SetEntriesInAcl in C# : error 1332
它与ANSI与Unicode的支持有关,你需要在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对于所有结构和方法定义都是一致的。事实上,因为我们的服务在所有支持Unicode字符集的服务器上运行,所以我们将CharSet全部更改为CharSet.Unicode。
此外,我们需要确保我们编组字符串参数的非托管类型与Unicode字符集匹配(例如,C ++ / native中的宽字符类型)。下面我们使用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 = $@"\\{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);
}
}
(..为什么要让你挖掘所有那些愚蠢的互操作枚举和结构定义?)
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);
}