コード例 #1
0
        internal static PipeSecurity?CreatePipeSecurity()
        {
            if (PlatformInformation.IsRunningOnMono)
            {
                // Pipe security and additional access rights constructor arguments
                //  are not supported by Mono
                // https://github.com/dotnet/roslyn/pull/30810
                // https://github.com/mono/mono/issues/11406
                return(null);
            }

            var security = new PipeSecurity();
            SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;

            // Restrict access to just this account.
            PipeAccessRule rule = new PipeAccessRule(
                identifier,
                PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance,
                AccessControlType.Allow
                );

            security.AddAccessRule(rule);
            security.SetOwner(identifier);
            return(security);
        }
コード例 #2
0
        /// <summary>
        /// Create an instance of the pipe. This might be the first instance, or a subsequent instance.
        /// There always needs to be an instance of the pipe created to listen for a new client connection.
        /// </summary>
        /// <returns>The pipe instance or throws an exception.</returns>
        private NamedPipeServerStream ConstructPipe(string pipeName)
        {
            CompilerServerLogger.Log("Constructing pipe '{0}'.", pipeName);

            SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;
            PipeSecurity       security   = new PipeSecurity();

            // Restrict access to just this account.
            PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow);

            security.AddAccessRule(rule);
            security.SetOwner(identifier);

            NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                PipeTransmissionMode.Byte,
                PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                PipeBufferSize, // Default input buffer
                PipeBufferSize, // Default output buffer
                security,
                HandleInheritability.None);

            CompilerServerLogger.Log("Successfully constructed pipe '{0}'.", pipeName);

            return(pipeStream);
        }
コード例 #3
0
        /// <summary>
        /// Instantiates an endpoint to act as a client
        /// </summary>
        /// <param name="pipeName">The name of the pipe to which we should connect.</param>
        internal void InternalConstruct(string pipeName)
        {
            ErrorUtilities.VerifyThrowArgumentLength(pipeName, nameof(pipeName));

            _debugCommunications = (Environment.GetEnvironmentVariable("MSBUILDDEBUGCOMM") == "1");

            _status           = LinkStatus.Inactive;
            _asyncDataMonitor = new object();
            _sharedReadBuffer = InterningBinaryReader.CreateSharedBuffer();

            _packetStream = new MemoryStream();
            _binaryWriter = new BinaryWriter(_packetStream);

#if FEATURE_PIPE_SECURITY && FEATURE_NAMED_PIPE_SECURITY_CONSTRUCTOR
            if (!NativeMethodsShared.IsMono)
            {
                SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;
                PipeSecurity       security   = new PipeSecurity();

                // Restrict access to just this account.  We set the owner specifically here, and on the
                // pipe client side they will check the owner against this one - they must have identical
                // SIDs or the client will reject this server.  This is used to avoid attacks where a
                // hacked server creates a less restricted pipe in an attempt to lure us into using it and
                // then sending build requests to the real pipe client (which is the MSBuild Build Manager.)
                PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite, AccessControlType.Allow);
                security.AddAccessRule(rule);
                security.SetOwner(identifier);

                _pipeServer = new NamedPipeServerStream
                              (
                    pipeName,
                    PipeDirection.InOut,
                    1, // Only allow one connection at a time.
                    PipeTransmissionMode.Byte,
                    PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                    PipeBufferSize, // Default input buffer
                    PipeBufferSize, // Default output buffer
                    security,
                    HandleInheritability.None
                              );
            }
            else
#endif
            {
                _pipeServer = new NamedPipeServerStream
                              (
                    pipeName,
                    PipeDirection.InOut,
                    1, // Only allow one connection at a time.
                    PipeTransmissionMode.Byte,
                    PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                    PipeBufferSize, // Default input buffer
                    PipeBufferSize  // Default output buffer
                              );
            }
        }
コード例 #4
0
        private void StartNamedPipeServer()
        {
            if (!StartServer)
            {
                return;
            }

#if NETCOREAPP2_1 || NETCOREAPP3_1 || NET5_0
            if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
            {
                throw new PlatformNotSupportedException("The communication with the first instance is only supported on Windows");
            }

            _server = new NamedPipeServerStream(
                PipeName,
                PipeDirection.In,
                NamedPipeServerStream.MaxAllowedServerInstances,
                PipeTransmissionMode.Message,
                PipeOptions.CurrentUserOnly);
#elif NET461
            using (var currentIdentity = WindowsIdentity.GetCurrent())
            {
                var identifier = currentIdentity.Owner;

                // Grant full control to the owner so multiple servers can be opened.
                // Full control is the default per MSDN docs for CreateNamedPipe.
                var rule         = new PipeAccessRule(identifier, PipeAccessRights.FullControl, AccessControlType.Allow);
                var pipeSecurity = new PipeSecurity();

                pipeSecurity.AddAccessRule(rule);
                pipeSecurity.SetOwner(identifier);

                _server = new NamedPipeServerStream(
                    PipeName,
                    PipeDirection.In,
                    NamedPipeServerStream.MaxAllowedServerInstances,
                    PipeTransmissionMode.Message,
                    PipeOptions.Asynchronous,
                    0,
                    0,
                    pipeSecurity);
            }
#else
#error Platform not supported
#endif
            try
            {
                _server.BeginWaitForConnection(Listen, state: null !); // TODO-NULLABLE https://github.com/dotnet/runtime/pull/42442
            }
            catch (ObjectDisposedException)
            {
                // The server was disposed before getting a connection
            }
        }
コード例 #5
0
        internal static NamedPipeServerStream CreateNamedPipeServer(string pipeName, int?inputBufferSize = null, int?outputBufferSize = null, int maxNumberOfServerInstances = 1, bool allowNewInstances = false)
        {
            inputBufferSize ??= PipeBufferSize;
            outputBufferSize ??= PipeBufferSize;

#if FEATURE_PIPE_SECURITY && FEATURE_NAMED_PIPE_SECURITY_CONSTRUCTOR
            if (!NativeMethodsShared.IsMono)
            {
                SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;
                PipeSecurity       security   = new PipeSecurity();

                // Restrict access to just this account.  We set the owner specifically here, and on the
                // pipe client side they will check the owner against this one - they must have identical
                // SIDs or the client will reject this server.  This is used to avoid attacks where a
                // hacked server creates a less restricted pipe in an attempt to lure us into using it and
                // then sending build requests to the real pipe client (which is the MSBuild Build Manager.)

                PipeAccessRights rights = PipeAccessRights.ReadWrite;
                if (allowNewInstances)
                {
                    rights |= PipeAccessRights.CreateNewInstance;
                }

                PipeAccessRule rule = new PipeAccessRule(identifier, rights, AccessControlType.Allow);
                security.AddAccessRule(rule);
                security.SetOwner(identifier);

                return(new NamedPipeServerStream
                       (
                           pipeName,
                           PipeDirection.InOut,
                           maxNumberOfServerInstances, // Only allow one connection at a time.
                           PipeTransmissionMode.Byte,
                           PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                           inputBufferSize.Value,  // Default input buffer
                           outputBufferSize.Value, // Default output buffer
                           security,
                           HandleInheritability.None
                       ));
            }
#endif
            return(new NamedPipeServerStream
                   (
                       pipeName,
                       PipeDirection.InOut,
                       maxNumberOfServerInstances, // Only allow one connection at a time.
                       PipeTransmissionMode.Byte,
                       PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                       inputBufferSize.Value, // Default input buffer
                       outputBufferSize.Value // Default output buffer
                   ));
        }
コード例 #6
0
        // This is the code we use in the Create method called by the NamedPipeServerStream constructor
        private PipeSecurity GetPipeSecurityForCurrentUserOnly()
        {
            PipeSecurity security = new PipeSecurity();

            using WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
            SecurityIdentifier identifier = currentIdentity.Owner;
            PipeAccessRule     rule       = new PipeAccessRule(identifier, PipeAccessRights.FullControl, AccessControlType.Allow);

            security.AddAccessRule(rule);
            security.SetOwner(identifier);

            return(security);
        }
コード例 #7
0
        private void StartNamedPipeServer()
        {
            if (!StartServer)
            {
                return;
            }

#if NETCOREAPP2_1 || NETCOREAPP3_0
            _server = new NamedPipeServerStream(
                PipeName,
                PipeDirection.In,
                NamedPipeServerStream.MaxAllowedServerInstances,
                PipeTransmissionMode.Message,
                PipeOptions.CurrentUserOnly);
#elif NET461
            using (var currentIdentity = WindowsIdentity.GetCurrent())
            {
                var identifier = currentIdentity.Owner;

                // Grant full control to the owner so multiple servers can be opened.
                // Full control is the default per MSDN docs for CreateNamedPipe.
                var rule         = new PipeAccessRule(identifier, PipeAccessRights.FullControl, AccessControlType.Allow);
                var pipeSecurity = new PipeSecurity();

                pipeSecurity.AddAccessRule(rule);
                pipeSecurity.SetOwner(identifier);

                _server = new NamedPipeServerStream(
                    PipeName,
                    PipeDirection.In,
                    NamedPipeServerStream.MaxAllowedServerInstances,
                    PipeTransmissionMode.Message,
                    PipeOptions.Asynchronous,
                    0,
                    0,
                    pipeSecurity);
            }
#else
#error Platform not supported
#endif
            try
            {
                _server.BeginWaitForConnection(Listen, state: null);
            }
            catch (ObjectDisposedException)
            {
                // The server was disposed before getting a connection
            }
        }
コード例 #8
0
ファイル: CommandService.cs プロジェクト: stevencohn/OneMore
        private NamedPipeServerStream CreateSecuredPipe()
        {
            var user     = WindowsIdentity.GetCurrent().User;
            var security = new PipeSecurity();

            security.AddAccessRule(new PipeAccessRule(
                                       user, PipeAccessRights.FullControl, AccessControlType.Allow));

            security.SetOwner(user);
            security.SetGroup(user);

            return(new NamedPipeServerStream(
                       pipe, PipeDirection.In, 1,
                       PipeTransmissionMode.Byte, PipeOptions.Asynchronous,
                       MaxBytes, MaxBytes, security));
        }
コード例 #9
0
        /// <summary>
        /// Create an instance of the pipe. This might be the first instance, or a subsequent instance.
        /// There always needs to be an instance of the pipe created to listen for a new client connection.
        /// </summary>
        /// <returns>The pipe instance or throws an exception.</returns>
        private NamedPipeServerStream ConstructPipe(string pipeName)
        {
            CompilerServerLogger.Log("Constructing pipe '{0}'.", pipeName);

#if NET46
            SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;
            PipeSecurity       security   = new PipeSecurity();

            // Restrict access to just this account.
            PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow);
            security.AddAccessRule(rule);
            security.SetOwner(identifier);

            NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                PipeTransmissionMode.Byte,
                PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                PipeBufferSize, // Default input buffer
                PipeBufferSize, // Default output buffer
                security,
                HandleInheritability.None);
#else
            // The overload of NamedPipeServerStream with the PipeAccessRule
            // parameter was removed in netstandard. However, the default
            // constructor does not provide WRITE_DAC, so attempting to use
            // SetAccessControl will always fail. So, completely ignore ACLs on
            // netcore, and trust that our `ClientAndOurIdentitiesMatch`
            // verification will catch any invalid connections.
            // Issue to add WRITE_DAC support:
            // https://github.com/dotnet/corefx/issues/24040
            NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                PipeTransmissionMode.Byte,
                PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                PipeBufferSize,  // Default input buffer
                PipeBufferSize); // Default output buffer
#endif

            CompilerServerLogger.Log("Successfully constructed pipe '{0}'.", pipeName);

            return(pipeStream);
        }
コード例 #10
0
        PipeSecurity makePipeSecurity()
        {
            var pipeSecurity = new PipeSecurity();
            var admins       = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
            var system       = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);

            if (IsElevated)
            {
                pipeSecurity.SetOwner(admins);
                pipeSecurity.SetGroup(system);
            }
            pipeSecurity.AddAccessRule(new PipeAccessRule(admins, PipeAccessRights.FullControl, AccessControlType.Allow));
            pipeSecurity.AddAccessRule(new PipeAccessRule(system, PipeAccessRights.FullControl, AccessControlType.Allow));
            pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null),
                                                          PipeAccessRights.ReadWrite, AccessControlType.Allow));
            return(pipeSecurity);
        }
コード例 #11
0
ファイル: AutoRebuildService.cs プロジェクト: jnm2/AspNetCore
        private Task AddBuildServiceNamedPipeServerAsync()
        {
            return(Task.Factory.StartNew(async() =>
            {
                try
                {
                    var identity = WindowsIdentity.GetCurrent();
                    var identifier = identity.Owner;
                    var security = new PipeSecurity();

                    // Restrict access to just this account.
                    var rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow);
                    security.AddAccessRule(rule);
                    security.SetOwner(identifier);

                    // And our current elevation level
                    var principal = new WindowsPrincipal(identity);
                    var isServerElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);

                    using (var serverPipe = new NamedPipeServerStream(
                               _pipeName,
                               PipeDirection.InOut,
                               NamedPipeServerStream.MaxAllowedServerInstances,
                               PipeTransmissionMode.Byte,
                               PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                               0x10000, // 64k input buffer
                               0x10000, // 64k output buffer
                               security,
                               HandleInheritability.None))
                    {
                        // As soon as we receive a connection, spin up another background
                        // listener to wait for the next connection
                        await serverPipe.WaitForConnectionAsync();
                        _ = AddBuildServiceNamedPipeServerAsync();

                        await HandleRequestAsync(serverPipe, isServerElevated);
                    }
                }
                catch (Exception ex)
                {
                    await AttemptLogErrorAsync(
                        $"Error in Blazor AutoRebuildService:\n{ex.Message}\n{ex.StackTrace}");
                }
            }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default));
        }
コード例 #12
0
        /// <summary>
        /// Create an instance of the pipe. This might be the first instance, or a subsequent instance.
        /// There always needs to be an instance of the pipe created to listen for a new client connection.
        /// </summary>
        /// <returns>The pipe instance, or NULL if the pipe couldn't be created..</returns>
        private NamedPipeServerStream ConstructPipe()
        {
            // Add the process ID onto the pipe name so each process gets a unique pipe name.
            // The client must user this algorithm too to connect.
            string pipeName = basePipeName + Process.GetCurrentProcess().Id.ToString();

            try
            {
                CompilerServerLogger.Log("Constructing pipe '{0}'.", pipeName);

                SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;
                PipeSecurity       security   = new PipeSecurity();

                // Restrict access to just this account.
                PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow);
                security.AddAccessRule(rule);
                security.SetOwner(identifier);

                NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                    pipeName,
                    PipeDirection.InOut,
                    NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                    PipeTransmissionMode.Byte,
                    PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                    PipeBufferSize, // Default input buffer
                    PipeBufferSize, // Default output buffer
                    security,
                    HandleInheritability.None);

                CompilerServerLogger.Log("Successfully constructed pipe '{0}'.", pipeName);

                return(pipeStream);
            }
            catch (Exception e)
            {
                // Windows may not create the pipe for a number of reasons.
                CompilerServerLogger.LogException(e, string.Format("Construction of pipe '{0}' failed", pipeName));
                return(null);
            }
        }
コード例 #13
0
        // Workaround: create the pipe via API call
        // we have to do it this way, since NamedPipeServerStream() for netstd still lacks a few CTORs
        // and _stream.SetAccessControl(pipesec); only keeps throwing ACCESS_DENIED errors at us
        // References:
        // - https://github.com/dotnet/corefx/issues/30170 (closed, continued in 31190)
        // - https://github.com/dotnet/corefx/issues/31190 System.IO.Pipes.AccessControl package does not work
        // - https://github.com/dotnet/corefx/issues/24040 NamedPipeServerStream: Provide support for WRITE_DAC
        // - https://github.com/dotnet/corefx/issues/34400 Have a mechanism for lower privileged user to connect to a privileged user's pipe
        private static SafePipeHandle CreatePipeNative(string name, int inbuf, int outbuf)
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return(null); // Windows only
            }
            var pinningHandle = new GCHandle();

            try
            {
                // owner gets full access, everyone else read/write
                var pipesec = new PipeSecurity();
                using (var currentIdentity = WindowsIdentity.GetCurrent())
                {
                    var sidOwner = currentIdentity.Owner;
                    var sidWorld = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

                    pipesec.SetOwner(sidOwner);
                    pipesec.AddAccessRule(new PipeAccessRule(sidOwner, PipeAccessRights.FullControl, AccessControlType.Allow));
                    pipesec.AddAccessRule(new PipeAccessRule(sidWorld, PipeAccessRights.ReadWrite, AccessControlType.Allow));
                }

                // create a security descriptor and assign it to the security attribs
                var    secAttrs = new SECURITY_ATTRIBUTES();
                byte[] sdBytes  = pipesec.GetSecurityDescriptorBinaryForm();
                pinningHandle = GCHandle.Alloc(sdBytes, GCHandleType.Pinned);
                unsafe
                {
                    fixed(byte *pSD = sdBytes)
                    {
                        secAttrs.lpSecurityDescriptor = (IntPtr)pSD;
                    }
                }

                // a bunch of constants we will need shortly
                const int PIPE_ACCESS_DUPLEX       = 0x00000003;
                const int FILE_FLAG_OVERLAPPED     = 0x40000000;
                const int WRITE_DAC                = 0x00040000;
                const int PIPE_TYPE_BYTE           = 0x00000000;
                const int PIPE_READMODE_BYTE       = 0x00000000;
                const int PIPE_UNLIMITED_INSTANCES = 255;

                // create the pipe via API call
                var rawHandle = CreateNamedPipe(
                    @"\\.\pipe\" + name,
                    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,
                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
                    PIPE_UNLIMITED_INSTANCES, (uint)inbuf, (uint)outbuf,
                    5 * 1000,
                    secAttrs
                    );

                // make a SafePipeHandle() from it
                var handle = new SafePipeHandle(rawHandle, true);
                if (handle.IsInvalid)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                // return it (to be packaged)
                return(handle);
            }
            finally
            {
                if (pinningHandle.IsAllocated)
                {
                    pinningHandle.Free();
                }
            }
        }
コード例 #14
0
        /// <summary>
        /// Create an instance of the pipe. This might be the first instance, or a subsequent instance.
        /// There always needs to be an instance of the pipe created to listen for a new client connection.
        /// </summary>
        /// <returns>The pipe instance or throws an exception.</returns>
        private NamedPipeServerStream ConstructPipe(string pipeName)
        {
            CompilerServerLogger.Log("Constructing pipe '{0}'.", pipeName);

#if NET472
            PipeSecurity security;
            PipeOptions  pipeOptions = PipeOptions.Asynchronous | PipeOptions.WriteThrough;

            if (!PlatformInformation.IsRunningOnMono)
            {
                security = new PipeSecurity();
                SecurityIdentifier identifier = WindowsIdentity.GetCurrent().Owner;

                // Restrict access to just this account.
                PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow);
                security.AddAccessRule(rule);
                security.SetOwner(identifier);
            }
            else
            {
                // Pipe security and additional access rights constructor arguments
                //  are not supported by Mono
                // https://github.com/dotnet/roslyn/pull/30810
                // https://github.com/mono/mono/issues/11406
                security = null;
                // This enum value is implemented by Mono to restrict pipe access to
                //  the current user
                const int CurrentUserOnly = unchecked ((int)0x20000000);
                pipeOptions |= (PipeOptions)CurrentUserOnly;
            }

            NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                PipeTransmissionMode.Byte,
                pipeOptions,
                PipeBufferSize, // Default input buffer
                PipeBufferSize, // Default output buffer
                security,
                HandleInheritability.None);
#else
            // The overload of NamedPipeServerStream with the PipeAccessRule
            // parameter was removed in netstandard. However, the default
            // constructor does not provide WRITE_DAC, so attempting to use
            // SetAccessControl will always fail. So, completely ignore ACLs on
            // netcore, and trust that our `ClientAndOurIdentitiesMatch`
            // verification will catch any invalid connections.
            // Issue to add WRITE_DAC support:
            // https://github.com/dotnet/corefx/issues/24040
            NamedPipeServerStream pipeStream = new NamedPipeServerStream(
                pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances, // Maximum connections.
                PipeTransmissionMode.Byte,
                PipeOptions.Asynchronous | PipeOptions.WriteThrough,
                PipeBufferSize,  // Default input buffer
                PipeBufferSize); // Default output buffer
#endif

            CompilerServerLogger.Log("Successfully constructed pipe '{0}'.", pipeName);

            return(pipeStream);
        }
コード例 #15
0
        // https://github.com/dotnet/corefx/blob/e753ecfe12d6af9b7fec5dee154395e7d29caed9/src/System.IO.Pipes/src/System/IO/Pipes/NamedPipeServerStream.Windows.cs#L31-L108
        private static SafePipeHandle CreatePipeHandle(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
                                                       PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
                                                       PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
        {
            Debug.Assert(pipeName != null && pipeName.Length != 0, "fullPipeName is null or empty");
            Debug.Assert(direction >= PipeDirection.In && direction <= PipeDirection.InOut, "invalid pipe direction");
            Debug.Assert(inBufferSize >= 0, "inBufferSize is negative");
            Debug.Assert(outBufferSize >= 0, "outBufferSize is negative");
            Debug.Assert((maxNumberOfServerInstances >= 1 && maxNumberOfServerInstances <= 254) || (maxNumberOfServerInstances == MaxAllowedServerInstances), "maxNumberOfServerInstances is invalid");
            Debug.Assert(transmissionMode >= PipeTransmissionMode.Byte && transmissionMode <= PipeTransmissionMode.Message, "transmissionMode is out of range");

            string fullPipeName = Path.GetFullPath(@"\\.\pipe\" + pipeName);

            // Make sure the pipe name isn't one of our reserved names for anonymous pipes.
            if (string.Equals(fullPipeName, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentOutOfRangeException(nameof(pipeName));
            }

            if ((options & PipeOptions.CurrentUserOnly) != 0)
            {
                Debug.Assert(pipeSecurity == null);

                using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent())
                {
                    SecurityIdentifier identifier = currentIdentity.Owner;

                    // Grant full control to the owner so multiple servers can be opened.
                    // Full control is the default per MSDN docs for CreateNamedPipe.
                    PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.FullControl, AccessControlType.Allow);
                    pipeSecurity = new PipeSecurity();

                    pipeSecurity.AddAccessRule(rule);
                    pipeSecurity.SetOwner(identifier);
                }

                // PipeOptions.CurrentUserOnly is special since it doesn't match directly to a corresponding Win32 valid flag.
                // Remove it, while keeping others untouched since historically this has been used as a way to pass flags to CreateNamedPipe
                // that were not defined in the enumeration.
                options &= ~PipeOptions.CurrentUserOnly;
            }

            int openMode = (int)direction |
                           (int)(maxNumberOfServerInstances == 1 ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0) |
                           (int)options |
                           (int)additionalAccessRights;

            // We automatically set the ReadMode to match the TransmissionMode.
            int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1;

            // Convert -1 to 255 to match win32 (we asserted that it is between -1 and 254).
            if (maxNumberOfServerInstances == MaxAllowedServerInstances)
            {
                maxNumberOfServerInstances = 255;
            }

            var pinningHandle = new GCHandle();

            try
            {
                SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability, pipeSecurity, ref pinningHandle);
                SafePipeHandle      handle   = CreateNamedPipe(fullPipeName, openMode, pipeModes,
                                                               maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs);

                if (handle.IsInvalid)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                return(handle);
            }
            finally
            {
                if (pinningHandle.IsAllocated)
                {
                    pinningHandle.Free();
                }
            }
        }
コード例 #16
0
        public async Task RunAsync()
        {
            _namedPipeClient = new NamedPipeClientStream(".", "CosmosSerial1", PipeDirection.InOut);

            var pipeSecurity = new PipeSecurity();

            var identity = WindowsIdentity.GetCurrent().User;

            var pipeAccessRule = new PipeAccessRule(
                identity,
                PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance,
                AccessControlType.Allow);

            pipeSecurity.AddAccessRule(pipeAccessRule);
            pipeSecurity.SetOwner(identity);

            _namedPipeServer = new NamedPipeServerStream(
                "CosmosSerial",
                PipeDirection.InOut,
                1,
                PipeTransmissionMode.Byte,
                PipeOptions.None,
                256,
                256,
                pipeSecurity,
                HandleInheritability.None);

            _ = Task.Run(WaitForNamedPipeConnections);

            using (var reader = new StreamReader(_tcpClient.GetStream()))
            {
                while (_tcpClient.Connected)
                {
                    if (_tcpClient.Available > 0)
                    {
                        var command = await reader.ReadLineAsync().ConfigureAwait(false);

                        var parts = command.Split(';');

                        switch (parts[0])
                        {
                        case "CreateVirtualMachine":
                            CreateVirtualMachine(parts[1], parts[2], parts[3]);
                            break;

                        case "RemoveVirtualMachine":
                            RemoveVirtualMachine(parts[1]);
                            break;

                        case "StartVirtualMachine":
                            StartVirtualMachine(parts[1]);
                            break;

                        case "StopVirtualMachine":
                            StopVirtualMachine(parts[1]);
                            break;
                        }

                        reader.BaseStream.WriteByte(0x20);
                    }
                    else
                    {
                        await Task.Delay(1000).ConfigureAwait(false);
                    }
                }
            }
        }