コード例 #1
0
        private static byte[]? GetNegotiatedApplicationProtocol(SafeDeleteContext context)
        {
            Interop.SecPkgContext_ApplicationProtocol alpnContext = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPISecureChannel, context, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL, ref alpnContext);

            // Check if the context returned is alpn data, with successful negotiation.
            if (success &&
                alpnContext.ProtoNegoExt == Interop.ApplicationProtocolNegotiationExt.ALPN &&
                alpnContext.ProtoNegoStatus == Interop.ApplicationProtocolNegotiationStatus.Success)
            {
                if (alpnContext.Protocol.SequenceEqual(s_http1))
                {
                    return(s_http1);
                }
                else if (alpnContext.Protocol.SequenceEqual(s_http2))
                {
                    return(s_http2);
                }
                else if (alpnContext.Protocol.SequenceEqual(s_http3))
                {
                    return(s_http3);
                }

                return(alpnContext.Protocol.ToArray());
            }

            return(null);
        }
コード例 #2
0
        public void UpdateSslConnectionInfo(SafeDeleteContext securityContext)
        {
            SecPkgContext_ConnectionInfo interopConnectionInfo = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(
                GlobalSSPI.SSPISecureChannel,
                securityContext,
                Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CONNECTION_INFO,
                ref interopConnectionInfo);

            Debug.Assert(success);

            TlsCipherSuite           cipherSuite = default;
            SecPkgContext_CipherInfo cipherInfo  = default;

            success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CIPHER_INFO, ref cipherInfo);
            if (success)
            {
                cipherSuite = (TlsCipherSuite)cipherInfo.dwCipherSuite;
            }

            Protocol        = interopConnectionInfo.Protocol;
            DataCipherAlg   = interopConnectionInfo.DataCipherAlg;
            DataKeySize     = interopConnectionInfo.DataKeySize;
            DataHashAlg     = interopConnectionInfo.DataHashAlg;
            DataHashKeySize = interopConnectionInfo.DataHashKeySize;
            KeyExchangeAlg  = interopConnectionInfo.KeyExchangeAlg;
            KeyExchKeySize  = interopConnectionInfo.KeyExchKeySize;

            TlsCipherSuite = cipherSuite;

            ApplicationProtocol = GetNegotiatedApplicationProtocol(securityContext);
        }
コード例 #3
0
        internal static string?QueryContextAuthenticationPackage(SafeDeleteContext securityContext)
        {
            SecPkgContext_NegotiationInfoW ctx = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO, typeof(SafeFreeContextBuffer), out SafeHandle? sspiHandle, ref ctx);

            using (sspiHandle)
            {
                return(success ? NegotiationInfoClass.GetAuthenticationPackageName(sspiHandle !, (int)ctx.NegotiationState) : null);
            }
        }
コード例 #4
0
        internal static unsafe int Wrap(SafeDeleteContext securityContext, ReadOnlySpan <byte> buffer, [NotNull] ref byte[]?output, bool isConfidential)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            // alloc new output buffer if not supplied or too small
            int resultSize = buffer.Length + sizes.cbMaxSignature;

            if (output == null || output.Length < resultSize)
            {
                output = new byte[resultSize];
            }

            // make a copy of user data for in-place encryption
            buffer.CopyTo(output.AsSpan(sizes.cbMaxSignature, buffer.Length));

            fixed(byte *outputPtr = output)
            {
                // Prepare buffers TOKEN(signature), DATA and Padding.
                Interop.SspiCli.SecBuffer *unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[2];
                Interop.SspiCli.SecBuffer *tokenBuffer     = &unmanagedBuffer[0];
                Interop.SspiCli.SecBuffer *dataBuffer      = &unmanagedBuffer[1];
                tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
                tokenBuffer->pvBuffer   = (IntPtr)(outputPtr);
                tokenBuffer->cbBuffer   = sizes.cbMaxSignature;
                dataBuffer->BufferType  = SecurityBufferType.SECBUFFER_DATA;
                dataBuffer->pvBuffer    = (IntPtr)(outputPtr + sizes.cbMaxSignature);
                dataBuffer->cbBuffer    = buffer.Length;

                Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(2)
                {
                    pBuffers = unmanagedBuffer
                };

                uint qop       = isConfidential ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
                int  errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(securityContext, ref sdcInOut, qop);

                if (errorCode != 0)
                {
                    Exception e = new Win32Exception(errorCode);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, e);
                    }
                    throw new Win32Exception(errorCode);
                }

                // return signed size
                return(tokenBuffer->cbBuffer + dataBuffer->cbBuffer);
            }
        }
コード例 #5
0
        internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, [AllowNull] ref byte[] output)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            // alloc new output buffer if not supplied or too small
            int resultSize = count + sizes.cbMaxSignature;

            if (output == null || output.Length < resultSize)
            {
                output = new byte[resultSize];
            }

            // make a copy of user data for in-place encryption
            Buffer.BlockCopy(buffer, offset, output, sizes.cbMaxSignature, count);

            // setup security buffers for ssp call
#if NETSTANDARD2_0
            Span <SecurityBuffer> securityBuffer = new SecurityBuffer[2];
#else
            TwoSecurityBuffers    stackBuffer    = default;
            Span <SecurityBuffer> securityBuffer = MemoryMarshal.CreateSpan(ref stackBuffer._item0, 2);
#endif
            securityBuffer[0] = new SecurityBuffer(output, 0, sizes.cbMaxSignature, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, sizes.cbMaxSignature, count, SecurityBufferType.SECBUFFER_DATA);

            // call SSP Function
            int errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);

            // throw if error
            if (errorCode != 0)
            {
                NetEventSource.Info($"MakeSignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}");
                throw new Win32Exception(errorCode);
            }

            // return signed size
            return(securityBuffer[0].size + securityBuffer[1].size);
        }
コード例 #6
0
        internal static int Encrypt(
            SafeDeleteContext securityContext,
            byte[] buffer,
            int offset,
            int count,
            bool isConfidential,
            bool isNtlm,
            ref byte[] output,
            uint sequenceNumber)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            try
            {
                int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer);

                if (count > maxCount || count < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount));
                }
            }
            catch (Exception e) when(!ExceptionCheck.IsFatal(e))
            {
                NetEventSource.Fail(null, "Arguments out of range.");
                throw;
            }

            int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            Buffer.BlockCopy(buffer, offset, output, 4 + sizes.cbSecurityTrailer, count);

            // Prepare buffers TOKEN(signature), DATA and Padding.
            ThreeSecurityBuffers buffers = default;
            var securityBuffer           = MemoryMarshal.CreateSpan(ref buffers._item0, 3);

            securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA);
            securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING);

            int errorCode;

            if (isConfidential)
            {
                errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber);
            }
            else
            {
                if (isNtlm)
                {
                    securityBuffer[1].type |= SecurityBufferType.SECBUFFER_READONLY;
                }

                errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);
            }

            if (errorCode != 0)
            {
                Exception e = new Win32Exception(errorCode);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(null, e);
                }
                throw e;
            }

            // Compacting the result.
            resultSize = securityBuffer[0].size;
            bool forceCopy = false;

            if (resultSize != sizes.cbSecurityTrailer)
            {
                forceCopy = true;
                Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size);
            }

            resultSize += securityBuffer[1].size;
            if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.cbSecurityTrailer)))
            {
                Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size);
            }

            resultSize += securityBuffer[2].size;
            unchecked
            {
                output[0] = (byte)((resultSize) & 0xFF);
                output[1] = (byte)(((resultSize) >> 8) & 0xFF);
                output[2] = (byte)(((resultSize) >> 16) & 0xFF);
                output[3] = (byte)(((resultSize) >> 24) & 0xFF);
            }

            return(resultSize + 4);
        }
コード例 #7
0
        internal static unsafe int Encrypt(
            SafeDeleteContext securityContext,
            ReadOnlySpan <byte> buffer,
            bool isConfidential,
            bool isNtlm,
            [NotNull] ref byte[]?output)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer);

            if (buffer.Length > maxCount)
            {
                throw new ArgumentOutOfRangeException(nameof(buffer.Length), SR.Format(SR.net_io_out_range, maxCount));
            }

            int resultSize = buffer.Length + sizes.cbSecurityTrailer + sizes.cbBlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            buffer.CopyTo(output.AsSpan(4 + sizes.cbSecurityTrailer));

            fixed(byte *outputPtr = output)
            {
                // Prepare buffers TOKEN(signature), DATA and Padding.
                Interop.SspiCli.SecBuffer *unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3];
                Interop.SspiCli.SecBuffer *tokenBuffer     = &unmanagedBuffer[0];
                Interop.SspiCli.SecBuffer *dataBuffer      = &unmanagedBuffer[1];
                Interop.SspiCli.SecBuffer *paddingBuffer   = &unmanagedBuffer[2];
                tokenBuffer->BufferType   = SecurityBufferType.SECBUFFER_TOKEN;
                tokenBuffer->pvBuffer     = (IntPtr)(outputPtr + 4);
                tokenBuffer->cbBuffer     = sizes.cbSecurityTrailer;
                dataBuffer->BufferType    = SecurityBufferType.SECBUFFER_DATA;
                dataBuffer->pvBuffer      = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer);
                dataBuffer->cbBuffer      = buffer.Length;
                paddingBuffer->BufferType = SecurityBufferType.SECBUFFER_PADDING;
                paddingBuffer->pvBuffer   = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer + buffer.Length);
                paddingBuffer->cbBuffer   = sizes.cbBlockSize;

                Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(3)
                {
                    pBuffers = unmanagedBuffer
                };

                if (isNtlm && !isConfidential)
                {
                    dataBuffer->BufferType |= SecurityBufferType.SECBUFFER_READONLY;
                }

                uint qop       = isConfidential ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
                int  errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(securityContext, ref sdcInOut, qop);

                if (errorCode != 0)
                {
                    Exception e = new Win32Exception(errorCode);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, e);
                    }
                    throw new Win32Exception(errorCode);
                }

                // Compacting the result.
                resultSize = tokenBuffer->cbBuffer;
                bool forceCopy = false;

                if (resultSize != sizes.cbSecurityTrailer)
                {
                    forceCopy = true;
                    output.AsSpan(4 + sizes.cbSecurityTrailer, dataBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, dataBuffer->cbBuffer));
                }

                resultSize += dataBuffer->cbBuffer;
                if (paddingBuffer->cbBuffer != 0 && (forceCopy || resultSize != (buffer.Length + sizes.cbSecurityTrailer)))
                {
                    output.AsSpan(4 + sizes.cbSecurityTrailer + buffer.Length, paddingBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, paddingBuffer->cbBuffer));
                }

                resultSize += paddingBuffer->cbBuffer;
                BinaryPrimitives.WriteInt32LittleEndian(output, resultSize);

                return(resultSize + 4);
            }
        }