簡體   English   中英

NamedPipeClientStream 在 Connect 上拋出 UnauthorizedAccessException

[英]NamedPipeClientStream throws UnauthorizedAccessException on Connect

在將“寫入”管道連接到正在運行的服務時,其他人都遇到了同樣的問題:UnauthorizedAccessException。 我嘗試了所有解決方案,但沒有任何方法可以使其成功連接。

該方案是在系統托盤中運行一個低完整性 C#/WPF 應用程序,它使用命名管道從 Windows 服務獲取通知,並可以告訴服務取消某些操作或等待更多數據(這就是為什么它需要一個寫管道來服務)。 從服務的管道讀取工作正常,我使用了兩個管道對象(一個從服務到客戶端,另一個從客戶端到服務)。

該服務在域用戶的帳戶下運行,但無論它在什么環境下運行,包括本地系統,管道都無法連接。

服務器管道是這樣創建的:

PipeSecurity ps = new PipeSecurity();

// Production service runs under current user credentials.
ps.AddAccessRule(new PipeAccessRule(WindowsIdentity.GetCurrent().User, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));

// Test service runs under local system credentials.
ps.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));

// Add world just for the hell of it, still won't work.
ps.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), PipeAccessRights.FullControl, AccessControlType.Allow));

this.readPipe = new NamedPipeServerStream(clientPipeName, PipeDirection.In);
this.writePipe = new NamedPipeServerStream(serverPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.None, 1024, 1024, ps);

客戶端管道是這樣創建的:

this.readPipe = new NamedPipeClientStream(".", serverPipeName, PipeDirection.In);
this.writePipe = new NamedPipeClientStream(".", clientPipeName, PipeDirection.Out);

// This doesn't make a difference.
//this.writePipe = new NamedPipeClientStream(".", clientPipeName, PipeAccessRights.FullControl, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None);

不想讓這個開放,因為這已經解決了,下面的代碼正在生產中。

  • 服務器管道必須具有精心構造的 ACL 列表,以允許來自低完整性客戶端管道的連接,只要用戶經過身份驗證或管理員。 請參閱 CreateNativePipeSecurity()。
  • 像往常一樣創建客戶端管道

    /// <summary> /// Creates the client and server pipes. /// </summary> private void CreatePipes() { string serverPipeName = string.Format("{0}server", this.pipeName); string clientPipeName = string.Format("{0}client", this.pipeName); if (this.readPipe != null) { this.readPipe.Dispose(); } if (this.writePipe != null) { this.writePipe.Dispose(); } if (this.server) { // Create a write pipe for sending notifications to client. this.writePipe = new NamedPipeServerStream(clientPipeName, PipeDirection.Out); // Create a read pipe for receiving notifications from the client. // Creating a pipe to high integrity process from low integrity process requires native access list creation (.NET bug). NativeMethods.SECURITY_ATTRIBUTES securityAttributes = this.CreateNativePipeSecurity(); IntPtr securityAttributesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(securityAttributes)); Marshal.StructureToPtr(securityAttributes, securityAttributesPtr, false); string nativePipeName = string.Format(@"\\\\.\\pipe\\{0}", serverPipeName); SafePipeHandle nativePipe = NativeMethods.CreateNamedPipe( nativePipeName, NativeMethods.PipeOpenMode.PIPE_ACCESS_INBOUND, 0, NativeMethods.PipeInstances.PIPE_UNLIMITED_INSTANCES, 0, 0, NativeMethods.PipeWait.NMPWAIT_WAIT_FOREVER, securityAttributesPtr); int error = Marshal.GetLastWin32Error(); Marshal.FreeHGlobal(securityAttributesPtr); if (nativePipe.IsInvalid) { throw new Win32Exception(error); } this.readPipe = new NamedPipeServerStream(PipeDirection.In, false, false, nativePipe); } else { // Create a read pipe for receiving notifications from server. this.readPipe = new NamedPipeClientStream(".", clientPipeName, PipeDirection.In); // Create a write pipe for sending notifications to the server. this.writePipe = new NamedPipeClientStream(".", serverPipeName, PipeDirection.Out); } } /// <summary> /// Generate security attributes to allow low integrity process to connect to high integrity service. /// </summary> /// <returns>A structure filled with proper attributes.</returns> private NativeMethods.SECURITY_ATTRIBUTES CreateNativePipeSecurity() { // Define the SDDL for the security descriptor. string sddl = "D:" + // Discretionary ACL "(A;OICI;GRGW;;;AU)" + // Allow read/write to authenticated users "(A;OICI;GA;;;BA)"; // Allow full control to administrators IntPtr securityDescriptor = IntPtr.Zero; if (NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptor( sddl, 1, out securityDescriptor, IntPtr.Zero) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } NativeMethods.SECURITY_ATTRIBUTES sa = new NativeMethods.SECURITY_ATTRIBUTES(); sa.nLength = Marshal.SizeOf(sa); sa.lpSecurityDescriptor = securityDescriptor; sa.bInheritHandle = 0; return sa; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM