public byte[] ProcessContextMessage(ReadableBuffer messageBuffer)
        {
            if (messageBuffer.Length == 0)
            {
                return(null);
            }
            SecurityBufferDescriptor input     = new SecurityBufferDescriptor(3);
            SecurityBuffer *         inputBuff = stackalloc SecurityBuffer[3];

            void *arrayPointer;

            if (messageBuffer.IsSingleSpan)
            {
                messageBuffer.First.TryGetPointer(out arrayPointer);
            }
            else
            {
                if (messageBuffer.Length > SecurityContext.MaxStackAllocSize)
                {
                    throw new OverflowException($"We need to create a buffer on the stack of size {messageBuffer.Length} but the max is {SecurityContext.MaxStackAllocSize}");
                }
                byte *tempBytes = stackalloc byte[messageBuffer.Length];
                messageBuffer.CopyTo(new Span <byte>(tempBytes, messageBuffer.Length));
                arrayPointer = tempBytes;
            }

            inputBuff[0] = new SecurityBuffer()
            {
                tokenPointer = arrayPointer,
                type         = SecurityBufferType.Token,
                size         = messageBuffer.Length
            };

            inputBuff[1] = new SecurityBuffer()
            {
                size         = 0,
                tokenPointer = null,
                type         = SecurityBufferType.Empty
            };

            if (_securityContext.LengthOfSupportedProtocols > 0)
            {
                inputBuff[2].size         = _securityContext.LengthOfSupportedProtocols;
                inputBuff[2].tokenPointer = (void *)_securityContext.AlpnSupportedProtocols;
                inputBuff[2].type         = SecurityBufferType.ApplicationProtocols;
            }
            else
            {
                inputBuff[2].size         = 0;
                inputBuff[2].tokenPointer = null;
                inputBuff[2].type         = SecurityBufferType.Empty;
            }
            input.UnmanagedPointer = inputBuff;

            SecurityBufferDescriptor output     = new SecurityBufferDescriptor(3);
            SecurityBuffer *         outputBuff = stackalloc SecurityBuffer[3];

            outputBuff[0].size         = 0;
            outputBuff[0].tokenPointer = null;
            outputBuff[0].type         = SecurityBufferType.Token;
            outputBuff[1].size         = 0;
            outputBuff[1].tokenPointer = null;
            outputBuff[1].type         = SecurityBufferType.Alert;
            outputBuff[2].size         = 0;
            outputBuff[2].tokenPointer = null;
            outputBuff[2].type         = SecurityBufferType.Empty;
            output.UnmanagedPointer    = outputBuff;

            ContextFlags flags = default(ContextFlags);
            long         timestamp;
            var          handle = _securityContext.CredentialsHandle;
            void *       contextptr;
            var          localPointer = _contextPointer;

            if (_contextPointer.handleHi == IntPtr.Zero && _contextPointer.handleLo == IntPtr.Zero)
            {
                contextptr = null;
            }
            else
            {
                contextptr = &localPointer;
            }
            var errorCode = (SecurityStatus)InteropSspi.AcceptSecurityContext(ref handle, contextptr, input, SecurityContext.ServerRequiredFlags, Endianness.Native, ref _contextPointer, output, ref flags, out timestamp);

            _contextPointer = localPointer;

            if (errorCode == SecurityStatus.ContinueNeeded || errorCode == SecurityStatus.OK)
            {
                byte[] outArray = null;
                if (outputBuff[0].size > 0)
                {
                    outArray = new byte[outputBuff[0].size];
                    Marshal.Copy((IntPtr)outputBuff[0].tokenPointer, outArray, 0, outputBuff[0].size);
                    InteropSspi.FreeContextBuffer((IntPtr)outputBuff[0].tokenPointer);
                }
                if (errorCode == SecurityStatus.OK)
                {
                    ContextStreamSizes ss;
                    //We have a valid context so lets query it for info
                    InteropSspi.QueryContextAttributesW(ref _contextPointer, ContextAttribute.StreamSizes, out ss);
                    _headerSize  = ss.header;
                    _trailerSize = ss.trailer;

                    if (_securityContext.LengthOfSupportedProtocols > 0)
                    {
                        _negotiatedProtocol = ApplicationProtocols.FindNegotiatedProtocol(_contextPointer);
                    }
                    _readyToSend = true;
                }
                return(outArray);
            }
            throw new InvalidOperationException($"We failed to build a server context {errorCode}");
        }
Esempio n. 2
0
        public byte[] ProcessContextMessage(ReadableBuffer messageBuffer)
        {
            GCHandle handleForAllocation = default(GCHandle);

            try
            {
                SecurityBufferDescriptor output     = new SecurityBufferDescriptor(2);
                SecurityBuffer *         outputBuff = stackalloc SecurityBuffer[2];
                outputBuff[0].size         = 0;
                outputBuff[0].tokenPointer = null;
                outputBuff[0].type         = SecurityBufferType.Token;
                outputBuff[1].type         = SecurityBufferType.Alert;
                outputBuff[1].size         = 0;
                outputBuff[1].tokenPointer = null;

                output.UnmanagedPointer = outputBuff;

                var        handle      = _securityContext.CredentialsHandle;
                SSPIHandle localhandle = _contextPointer;
                void *     contextptr;
                void *     newContextptr;
                if (_contextPointer.handleHi == IntPtr.Zero && _contextPointer.handleLo == IntPtr.Zero)
                {
                    contextptr    = null;
                    newContextptr = &localhandle;
                }
                else
                {
                    contextptr    = &localhandle;
                    newContextptr = null;
                }

                ContextFlags unusedAttributes = default(ContextFlags);
                SecurityBufferDescriptor *pointerToDescriptor = null;

                if (messageBuffer.Length > 0)
                {
                    SecurityBufferDescriptor input     = new SecurityBufferDescriptor(2);
                    SecurityBuffer *         inputBuff = stackalloc SecurityBuffer[2];
                    inputBuff[0].size = messageBuffer.Length;
                    inputBuff[0].type = SecurityBufferType.Token;

                    if (messageBuffer.IsSingleSpan)
                    {
                        void *arrayPointer;
                        messageBuffer.First.TryGetPointer(out arrayPointer);
                        inputBuff[0].tokenPointer = arrayPointer;
                    }
                    else
                    {
                        if (messageBuffer.Length <= SecurityContext.MaxStackAllocSize)
                        {
                            byte *      tempBuffer = stackalloc byte[messageBuffer.Length];
                            Span <byte> tmpSpan    = new Span <byte>(tempBuffer, messageBuffer.Length);
                            messageBuffer.CopyTo(tmpSpan);
                            inputBuff[0].tokenPointer = tempBuffer;
                        }
                        else
                        {
                            //We have to allocate... sorry
                            byte[]      tempBuffer = new byte[messageBuffer.Length];
                            Span <byte> tmpSpan    = new Span <byte>(tempBuffer);
                            messageBuffer.CopyTo(tmpSpan);
                            handleForAllocation       = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned);
                            inputBuff[0].tokenPointer = (void *)handleForAllocation.AddrOfPinnedObject();
                        }
                    }

                    outputBuff[1].type         = SecurityBufferType.Empty;
                    outputBuff[1].size         = 0;
                    outputBuff[1].tokenPointer = null;

                    input.UnmanagedPointer = inputBuff;
                    pointerToDescriptor    = &input;
                }
                else
                {
                    if (_securityContext.LengthOfSupportedProtocols > 0)
                    {
                        SecurityBufferDescriptor input     = new SecurityBufferDescriptor(1);
                        SecurityBuffer *         inputBuff = stackalloc SecurityBuffer[1];
                        inputBuff[0].size = _securityContext.LengthOfSupportedProtocols;

                        inputBuff[0].tokenPointer = (void *)_securityContext.AlpnSupportedProtocols;

                        inputBuff[0].type = SecurityBufferType.ApplicationProtocols;

                        input.UnmanagedPointer = inputBuff;
                        pointerToDescriptor    = &input;
                    }
                }

                long           timestamp = 0;
                SecurityStatus errorCode = (SecurityStatus)InteropSspi.InitializeSecurityContextW(ref handle, contextptr, _securityContext.HostName, SecurityContext.RequiredFlags | ContextFlags.InitManualCredValidation, 0, Endianness.Native, pointerToDescriptor, 0, newContextptr, output, ref unusedAttributes, out timestamp);

                _contextPointer = localhandle;

                if (errorCode == SecurityStatus.ContinueNeeded || errorCode == SecurityStatus.OK)
                {
                    byte[] outArray = null;
                    if (outputBuff[0].size > 0)
                    {
                        outArray = new byte[outputBuff[0].size];
                        Marshal.Copy((IntPtr)outputBuff[0].tokenPointer, outArray, 0, outputBuff[0].size);
                        InteropSspi.FreeContextBuffer((IntPtr)outputBuff[0].tokenPointer);
                    }
                    if (errorCode == SecurityStatus.OK)
                    {
                        ContextStreamSizes ss;
                        //We have a valid context so lets query it for info
                        InteropSspi.QueryContextAttributesW(ref _contextPointer, ContextAttribute.StreamSizes, out ss);
                        _headerSize  = ss.header;
                        _trailerSize = ss.trailer;

                        if (_securityContext.LengthOfSupportedProtocols > 0)
                        {
                            _negotiatedProtocol = ApplicationProtocols.FindNegotiatedProtocol(_contextPointer);
                        }
                        _readyToSend = true;
                    }
                    return(outArray);
                }

                throw new InvalidOperationException($"An error occured trying to negoiate a session {errorCode}");
            }
            finally
            {
                if (handleForAllocation.IsAllocated)
                {
                    handleForAllocation.Free();
                }
            }
        }