Beispiel #1
0
        private static int DecryptNtlm(
            SafeDeleteContext securityContext,
            byte[] buffer,
            int offset,
            int count,
            bool isConfidential,
            out int newOffset,
            uint sequenceNumber)
        {
            const int ntlmSignatureLength = 16;

            // For the most part the arguments are verified in Decrypt().
            if (count < ntlmSignatureLength)
            {
                NetEventSource.Fail(null, "Argument 'count' out of range.");
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            TwoSecurityBuffers buffers = default;
            var securityBuffer         = MemoryMarshal.CreateSpan(ref buffers._item0, 2);

            securityBuffer[0] = new SecurityBuffer(buffer, offset, ntlmSignatureLength, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(buffer, offset + ntlmSignatureLength, count - ntlmSignatureLength, SecurityBufferType.SECBUFFER_DATA);

            int errorCode;
            SecurityBufferType realDataType = SecurityBufferType.SECBUFFER_DATA;

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

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

            if (securityBuffer[1].type != realDataType)
            {
                throw new InternalException(securityBuffer[1].type);
            }

            newOffset = securityBuffer[1].offset;
            return(securityBuffer[1].size);
        }
        internal static SecurityStatusPal InitializeSecurityContext(
            ref SafeFreeCredentials credentialsHandle,
            ref SafeDeleteContext securityContext,
            string spn,
            ContextFlagsPal requestedContextFlags,
            byte[] incomingBlob,
            ChannelBinding channelBinding,
            ref byte[] resultBlob,
            ref ContextFlagsPal contextFlags)
        {
#if netstandard
            Span <SecurityBuffer> inSecurityBufferSpan = new SecurityBuffer[2];
#else
            TwoSecurityBuffers    twoSecurityBuffers   = default;
            Span <SecurityBuffer> inSecurityBufferSpan = MemoryMarshal.CreateSpan(ref twoSecurityBuffers._item0, 2);
#endif

            int inSecurityBufferSpanLength = 0;
            if (incomingBlob != null && channelBinding != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);
                inSecurityBufferSpan[1]    = new SecurityBuffer(channelBinding);
                inSecurityBufferSpanLength = 2;
            }
            else if (incomingBlob != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);
                inSecurityBufferSpanLength = 1;
            }
            else if (channelBinding != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(channelBinding);
                inSecurityBufferSpanLength = 1;
            }
            inSecurityBufferSpan = inSecurityBufferSpan.Slice(0, inSecurityBufferSpanLength);

            var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN);

            Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero;
            // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe.
            SafeDeleteSslContext    sslContext = (SafeDeleteSslContext)securityContext;
            Interop.SECURITY_STATUS winStatus  = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext(
                GlobalSSPI.SSPIAuth,
                ref credentialsHandle,
                ref sslContext,
                spn,
                ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags),
                Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP,
                inSecurityBufferSpan,
                ref outSecurityBuffer,
                ref outContextFlags);
            securityContext = sslContext;
            resultBlob      = outSecurityBuffer.token;
            contextFlags    = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags);
            return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus));
        }
Beispiel #3
0
        internal static int VerifySignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count)
        {
            // validate offset within length
            if (offset < 0 || offset > (buffer == null ? 0 : buffer.Length))
            {
                NetEventSource.Info("Argument 'offset' out of range.");
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            // validate count within offset and end of buffer
            if (count < 0 ||
                count > (buffer == null ? 0 : buffer.Length - offset))
            {
                NetEventSource.Info("Argument 'count' out of range.");
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            // setup security buffers for ssp call
            // one points at signed data
            // two will receive payload if signature is valid
#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(buffer, offset, count, SecurityBufferType.SECBUFFER_STREAM);
            securityBuffer[1] = new SecurityBuffer(0, SecurityBufferType.SECBUFFER_DATA);

            // call SSP function
            int errorCode = SSPIWrapper.VerifySignature(
                GlobalSSPI.SSPIAuth,
                securityContext,
                securityBuffer,
                0);
            // throw if error
            if (errorCode != 0)
            {
                NetEventSource.Info($"VerifySignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}");
                throw new Win32Exception(errorCode);
            }

            // not sure why this is here - retained from Encrypt code above
            if (securityBuffer[1].type != SecurityBufferType.SECBUFFER_DATA)
            {
                throw new InternalException(securityBuffer[1].type);
            }

            // return validated payload size
            return(securityBuffer[1].size);
        }
Beispiel #4
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);
        }
Beispiel #5
0
        internal static int Decrypt(
            SafeDeleteContext securityContext,
            byte[] buffer,
            int offset,
            int count,
            bool isConfidential,
            bool isNtlm,
            out int newOffset,
            uint sequenceNumber)
        {
            if (offset < 0 || offset > (buffer == null ? 0 : buffer.Length))
            {
                NetEventSource.Fail(null, "Argument 'offset' out of range.");
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (count < 0 || count > (buffer == null ? 0 : buffer.Length - offset))
            {
                NetEventSource.Fail(null, "Argument 'count' out of range.");
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            if (isNtlm)
            {
                return(DecryptNtlm(securityContext, buffer, offset, count, isConfidential, out newOffset, sequenceNumber));
            }

            //
            // Kerberos and up
            //
            TwoSecurityBuffers buffers = default;
            var securityBuffer         = MemoryMarshal.CreateSpan(ref buffers._item0, 2);

            securityBuffer[0] = new SecurityBuffer(buffer, offset, count, SecurityBufferType.SECBUFFER_STREAM);
            securityBuffer[1] = new SecurityBuffer(0, SecurityBufferType.SECBUFFER_DATA);

            int errorCode;

            if (isConfidential)
            {
                errorCode = SSPIWrapper.DecryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber);
            }
            else
            {
                errorCode = SSPIWrapper.VerifySignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber);
            }

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

            if (securityBuffer[1].type != SecurityBufferType.SECBUFFER_DATA)
            {
                throw new InternalException(securityBuffer[1].type);
            }

            newOffset = securityBuffer[1].offset;
            return(securityBuffer[1].size);
        }