2016-01-28 6 views
0

У меня такая же проблема, как и все остальные при подключении «write» к запущенной службе: UnauthorizedAccessException. Я пробовал каждое решение, и ничто не может заставить его успешно подключиться.NamedPipeClientStream выбрасывает UnauthorizedAccessException при подключении

В сценарии имеется приложение с низкой степенью целостности C#/WPF, работающее в системном трее, которое получает уведомления от службы Windows с использованием именованных каналов и может сообщить службе об отмене определенных операций или дождаться получения большего количества данных (поэтому канал записи в службу). Чтение из трубы службы отлично работает, и я использую два объекта pipe (один - от службы к клиенту, другой - от клиента к сервису).

Служба работает под учетной записью пользователя домена, но труба не может подключиться независимо от того, в чём она работает, включая локальную систему.

трубы сервера создаются следующим образом:

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); 

Демонстрационный проект доступен здесь, если вы можете посмотреть на мой вопрос, так что вы не» т придется сделать его самостоятельно:

Pipes Solution with ReadMe

ответ

1

не хотел оставить это открытым, так как это было решено, и следующий код находится в производстве.

  • В серверной трубе должен быть тщательно составлен список 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; 
    }