OpenEvent/OpenFileMapping失败,错误代码为ERROR_ACCESS_DENIED。

6
我正在开发一个开源的.NET程序集(WinSCP .NET程序集),它会生成一个本地(C++)应用程序,并通过事件和文件映射对象与其通信。
该程序集使用Process类生成应用程序,没有特殊设置。程序集创建了一些事件(使用EventWaitHandle)和文件映射(使用PInvoked CreateFileMapping),应用程序使用OpenEventOpenFileMapping打开这些内容。
在大多数情况下,它都可以正常工作。但现在我遇到了一个用户,在Windows Server 2008 R2 64位上的ASPX应用程序中使用该程序集时出现了问题。
在他的情况下,OpenEventOpenFileMapping都返回NULL,而GetLastError返回ERROR_ACCESS_DENIED
我尝试通过明确授予当前用户对事件对象和应用程序代码所需的访问权限(而不是原始的EVENT_ALL_ACCESS)来改进汇编代码,如Microsoft Docs example所示。但这并没有帮助解决问题,因此我甚至没有尝试对文件映射对象进行相同的操作。
创建事件的C#代码如下:
EventWaitHandleSecurity security = new EventWaitHandleSecurity();

string user = Environment.UserDomainName + "\\" + Environment.UserName;

EventWaitHandleAccessRule rule;
rule =
    new EventWaitHandleAccessRule(
        user, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
        AccessControlType.Allow);
security.AddAccessRule(rule);
rule =
    new EventWaitHandleAccessRule(
        user, EventWaitHandleRights.ChangePermissions, AccessControlType.Deny);
security.AddAccessRule(rule);

new EventWaitHandle(
    false, EventResetMode.AutoReset, name, out createdNew, security);

“打开”事件的C++代码如下:

OpenEvent(EVENT_MODIFY_STATE, false, name);

(对于其他事件,访问级别是SYNCHRONIZE,具体取决于需要。)
我还尝试在对象名称前添加Global\前缀。如预期所料,这并没有解决问题。
有人知道是什么原因导致OpenEvent(或CreateFileMapping)出现“访问被拒绝”的错误吗?

抱歉,我没有正确理解情况。问题可能是您正在受限制的令牌下运行,即某个进程可以以这种方式运行,以至于它没有用户帐户的完全访问权限。您可能需要检查安全令牌以找出哪些SID已启用,以便适当地设置对象权限,抱歉,我不确定如何在.NET中执行此操作。另一种方法是安排子进程继承现有的对象句柄,而不是打开新的句柄;同样,我不知道您如何在.NET中执行此操作。 - Harry Johnston
如果事件和映射文件是使用不允许所有人访问的ACL创建的,则像ASP.NET这样的受限上下文可能无法打开它。我首先建议使用显式权限为ASP.NET进程运行的用户打开事件和映射文件。 - Peter Ritchie
@PeterRitchie:您是否知道在使用受限令牌运行的ASPX应用程序中,Everyone SID 是否已启用?我相当确定用户帐户的SID不会启用。最好的选择是登录SID,但我不太确定如何从您的令牌中提取该SID。 - Harry Johnston
在受限服务的情况下,我可能错了,但我认为令牌中没有任何众所周知或可预测的SID。唯一的选择是提取登录SID,可以通过将TokenLogonSid选项传递给GetTokenInformation来实现。(注:我的术语不正确,技术上有“限制SID”和“拒绝SID”,但没有“禁用SID”。) - Harry Johnston
谢谢您的评论。那么在.Net代码中,我应该尝试使用OpenProcessToken获取当前进程的令牌,将其传递给GetTokenInformation并使用检索到的SID用于来自文章《创建新对象的安全描述符》的代码? - Martin Prikryl
显示剩余8条评论
1个回答

1
我的猜测是,该事件是由匿名用户或已登录用户创建的,具体取决于网站的设置方式。但子进程是使用基本进程用户启动的。可以通过使用进程监视器并查看事件句柄的acl来检查这一点,以查看创建者是谁。然后查看子进程以查看它作为谁运行。
如果是这种情况,则可以更新事件的acl以包括基本进程。除此之外,您可能仍需要在前缀中添加“global”,以确保事件可以跨用户边界使用。

谢谢。我会尝试一下。 - Martin Prikryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接