Exemplo n.º 1
0
 internal unsafe static extern int AcceptSecurityContext(
     ref SSPIHandle credentialHandle,
     [In] void *inContextPtr,
     [In] SecurityBufferDescriptor inputBuffer,
     [In] ContextFlags inFlags,
     [In] Endianness endianness,
     ref SSPIHandle outContextPtr,
     [In, Out] SecurityBufferDescriptor outputBuffer,
     [In, Out] ref ContextFlags attributes,
     out long timeStamp
     );
Exemplo n.º 2
0
 internal unsafe static extern int InitializeSecurityContextW(
     ref SSPIHandle credentialHandle,
     [In] void *inContextPtr,
     [In] byte *targetName,
     [In] ContextFlags inFlags,
     [In] int reservedI,
     [In] Endianness endianness,
     [In] SecurityBufferDescriptor inputBuffer,
     [In] int reservedII,
     ref SSPIHandle outContextPtr,
     [In, Out] SecurityBufferDescriptor outputBuffer,
     [In, Out] ref ContextFlags attributes,
     out long timeStamp
     );
        internal static unsafe void Encrypt <T>(this T context, WritableBuffer outBuffer, ReadableBuffer buffer) where T : ISecureContext
        {
            outBuffer.Ensure(context.TrailerSize + context.HeaderSize + buffer.Length);
            void *outBufferPointer;

            outBuffer.Memory.TryGetPointer(out outBufferPointer);

            buffer.CopyTo(outBuffer.Memory.Slice(context.HeaderSize, buffer.Length));

            var securityBuff = stackalloc SecurityBuffer[4];
            SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(4);

            securityBuff[0].size         = context.HeaderSize;
            securityBuff[0].type         = SecurityBufferType.Header;
            securityBuff[0].tokenPointer = outBufferPointer;

            securityBuff[1].size         = buffer.Length;
            securityBuff[1].type         = SecurityBufferType.Data;
            securityBuff[1].tokenPointer = (byte *)outBufferPointer + context.HeaderSize;

            securityBuff[2].size         = context.TrailerSize;
            securityBuff[2].type         = SecurityBufferType.Trailer;
            securityBuff[2].tokenPointer = (byte *)outBufferPointer + context.HeaderSize + buffer.Length;

            securityBuff[3].size         = 0;
            securityBuff[3].tokenPointer = null;
            securityBuff[3].type         = SecurityBufferType.Empty;

            sdcInOut.UnmanagedPointer = securityBuff;

            var handle = context.ContextHandle;
            var result = (SecurityStatus)InteropSspi.EncryptMessage(ref handle, 0, sdcInOut, 0);

            if (result == 0)
            {
                outBuffer.Advance(context.HeaderSize + context.TrailerSize + buffer.Length);
            }
            else
            {
                //Zero out the output buffer before throwing the exception to stop any data being sent in the clear
                //By a misbehaving underlying channel
                Span <byte> memoryToClear = new Span <byte>(outBufferPointer, context.HeaderSize + context.TrailerSize + buffer.Length);
                byte *      empty         = stackalloc byte[context.HeaderSize + context.TrailerSize + buffer.Length];
                memoryToClear.Set(empty, context.HeaderSize + context.TrailerSize + buffer.Length);
                throw new InvalidOperationException($"There was an issue encrypting the data {result}");
            }
        }
        private static unsafe SecurityStatus DecryptMessage(void *buffer, ref int offset, ref int count, SSPIHandle context)
        {
            var securityBuff = stackalloc SecurityBuffer[4];
            SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(4);

            securityBuff[0].size         = count;
            securityBuff[0].tokenPointer = buffer;
            securityBuff[0].type         = SecurityBufferType.Data;
            securityBuff[1].size         = 0;
            securityBuff[1].tokenPointer = null;
            securityBuff[1].type         = SecurityBufferType.Empty;
            securityBuff[2].size         = 0;
            securityBuff[2].tokenPointer = null;
            securityBuff[2].type         = SecurityBufferType.Empty;
            securityBuff[3].size         = 0;
            securityBuff[3].tokenPointer = null;
            securityBuff[3].type         = SecurityBufferType.Empty;

            sdcInOut.UnmanagedPointer = securityBuff;

            var errorCode = (SecurityStatus)InteropSspi.DecryptMessage(ref context, sdcInOut, 0, null);

            if (errorCode == 0)
            {
                for (int i = 0; i < 4; i++)
                {
                    if (securityBuff[i].type == SecurityBufferType.Data)
                    {
                        //we have found the data lets find the offset
                        offset = (int)((byte *)securityBuff[i].tokenPointer - (byte *)buffer);
                        if (offset > (count - 1))
                        {
                            throw new OverflowException();
                        }
                        count = securityBuff[i].size;
                        return(errorCode);
                    }
                }
            }
            throw new InvalidOperationException($"There was an error ncrypting the data {errorCode}");
        }
Exemplo n.º 5
0
 internal unsafe static extern int CompleteAuthToken(
     [In] void *inContextPtr,
     [In, Out] SecurityBufferDescriptor inputBuffers
     );
Exemplo n.º 6
0
 internal static unsafe extern int DecryptMessage(
     [In] ref SSPIHandle contextHandle,
     [In, Out] SecurityBufferDescriptor inputOutput,
     [In] uint sequenceNumber,
     uint *qualityOfProtection
     );
Exemplo n.º 7
0
 internal static extern int EncryptMessage(
     ref SSPIHandle contextHandle,
     [In] uint qualityOfProtection,
     [In, Out] SecurityBufferDescriptor inputOutput,
     [In] uint sequenceNumber
     );
Exemplo n.º 8
0
 internal static extern int ApplyControlToken(ref SSPIHandle contextHandle, [In][Out] SecurityBufferDescriptor outputBuffer);
Exemplo n.º 9
0
        public static unsafe int EncryptDecryptHelper(SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber, bool encrypt, bool isGssBlob)
        {
            SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(input.Length);
            SecurityBufferStruct[] unmanagedBuffer = new SecurityBufferStruct[input.Length];
            byte[][] buffers = new byte[input.Length][];
            fixed (void* unmanagedBufferPtr = unmanagedBuffer)
            {
                sdcInOut.UnmanagedPointer = unmanagedBufferPtr;
                GCHandle[] pinnedBuffers = new GCHandle[input.Length];
                try
                {
                    for (int i = 0; i < input.Length; ++i)
                    {
                        SecurityBuffer iBuffer = input[i];
                        unmanagedBuffer[i].count = iBuffer.size;
                        unmanagedBuffer[i].type = iBuffer.type;
                        if (iBuffer.token == null || iBuffer.token.Length == 0)
                        {
                            unmanagedBuffer[i].token = IntPtr.Zero;
                        }
                        else
                        {
                            pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned);
                            unmanagedBuffer[i].token = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset);
                            buffers[i] = iBuffer.token;
                        }
                    }
                    int errorCode;
                    if (encrypt)
                    {
                        errorCode = SafeDeleteContext.EncryptMessage(context, sdcInOut, sequenceNumber);
                    }
                    else
                    {
                        errorCode = SafeDeleteContext.DecryptMessage(context, sdcInOut, sequenceNumber);
                    }
                    // Marshalling back returned sizes (do not marshal the "token" field)
                    for (int i = 0; i < input.Length; ++i)
                    {
                        SecurityBuffer iBuffer = input[i];
                        iBuffer.size = unmanagedBuffer[i].count;
                        iBuffer.type = unmanagedBuffer[i].type;
                        if (iBuffer.size == 0)
                        {
                            iBuffer.offset = 0;
                            iBuffer.token = null;
                        }
                        else if (isGssBlob && !encrypt && iBuffer.type == BufferType.Data)
                        {
                            iBuffer.token = DiagnosticUtility.Utility.AllocateByteArray(iBuffer.size);
                            Marshal.Copy(unmanagedBuffer[i].token, iBuffer.token, 0, iBuffer.size);
                        }
                        else checked
                            {
                                // Find the buffer this is inside of.  Usually they all point inside buffer 0.
                                int j;
                                for (j = 0; j < input.Length; j++)
                                {
                                    if (buffers[j] == null)
                                    {
                                        continue;
                                    }

                                    byte* bufferAddress = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0);
                                    if ((byte*)unmanagedBuffer[i].token >= bufferAddress &&
                                        (byte*)unmanagedBuffer[i].token + iBuffer.size <= bufferAddress + buffers[j].Length)
                                    {
                                        iBuffer.offset = (int)((byte*)unmanagedBuffer[i].token - bufferAddress);
                                        iBuffer.token = buffers[j];
                                        break;
                                    }
                                }

                                if (j >= input.Length)
                                {
                                    iBuffer.size = 0;
                                    iBuffer.offset = 0;
                                    iBuffer.token = null;
                                }
                                if (!(iBuffer.offset >= 0 && iBuffer.offset <= (iBuffer.token == null ? 0 : iBuffer.token.Length)))
                                {
                                    DiagnosticUtility.DebugAssert(SR.GetString(SR.SspiWrapperEncryptDecryptAssert1, iBuffer.offset));
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SspiWrapperEncryptDecryptAssert1, iBuffer.offset)));

                                }
                                if (!(iBuffer.size >= 0 && iBuffer.size <= (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset)))
                                {
                                    DiagnosticUtility.DebugAssert(SR.GetString(SR.SspiWrapperEncryptDecryptAssert2, iBuffer.size));
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SspiWrapperEncryptDecryptAssert2, iBuffer.size)));
                                }
                            }
                    }
                    return errorCode;
                }
                finally
                {
                    for (int i = 0; i < pinnedBuffers.Length; ++i)
                    {
                        if (pinnedBuffers[i].IsAllocated)
                        {
                            pinnedBuffers[i].Free();
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        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}");
        }
Exemplo n.º 11
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();
                }
            }
        }