public void Dispose()
 {
     if (_contextPointer.IsValid)
     {
         InteropSspi.DeleteSecurityContext(ref _contextPointer);
     }
 }
Exemple #2
0
 public void Dispose()
 {
     InteropSspi.FreeCredentialsHandle(ref _credsHandle);
     if (_alpnHandle.IsAllocated)
     {
         _alpnHandle.Free();
     }
 }
Exemple #3
0
        private unsafe void GetCredentials()
        {
            CredentialUse   direction;
            CredentialFlags flags;

            if (_isServer)
            {
                direction = CredentialUse.Inbound;
                flags     = CredentialFlags.UseStrongCrypto | CredentialFlags.SendAuxRecord;
            }
            else
            {
                direction = CredentialUse.Outbound;
                flags     = CredentialFlags.ValidateManual | CredentialFlags.NoDefaultCred | CredentialFlags.SendAuxRecord | CredentialFlags.UseStrongCrypto;
            }

            var creds = new SecureCredential()
            {
                rootStore               = IntPtr.Zero,
                phMappers               = IntPtr.Zero,
                palgSupportedAlgs       = IntPtr.Zero,
                cMappers                = 0,
                cSupportedAlgs          = 0,
                dwSessionLifespan       = 0,
                reserved                = 0,
                dwMinimumCipherStrength = 0, //this is required to force encryption
                dwMaximumCipherStrength = 0,
                version          = SecureCredential.CurrentVersion,
                dwFlags          = flags,
                certContextArray = IntPtr.Zero,
                cCreds           = 0
            };
            IntPtr certPointer;

            if (_isServer)
            {
                creds.grbitEnabledProtocols = InteropSspi.ServerProtocolMask;
                certPointer = _serverCertificate.Handle;
                //pointer to the pointer
                IntPtr certPointerPointer = new IntPtr(&certPointer);
                creds.certContextArray = certPointerPointer;
                creds.cCreds           = 1;
            }
            else
            {
                creds.grbitEnabledProtocols = InteropSspi.ClientProtocolMask;
            }

            long           timestamp = 0;
            SecurityStatus code      = (SecurityStatus)InteropSspi.AcquireCredentialsHandleW(null, SecurityPackage, (int)direction, null, ref creds, null, null, ref _credsHandle, out timestamp);

            if (code != 0)
            {
                throw new InvalidOperationException("Could not acquire the credentials");
            }
        }
Exemple #4
0
        internal static unsafe ProtocolIds FindNegotiatedProtocol(SSPIHandle context)
        {
            ContextApplicationProtocol protoInfo;

            InteropSspi.QueryContextAttributesW(ref context, ContextAttribute.ApplicationProtocol, out protoInfo);

            if (protoInfo.ProtoNegoStatus != ApplicationProtocolNegotiationStatus.Success)
            {
                throw new InvalidOperationException("Could not negotiate a mutal application protocol");
            }
            return(GetNegotiatedProtocol(protoInfo.ProtocolId, protoInfo.ProtocolIdSize));
        }
        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}");
            }
        }
Exemple #6
0
        private unsafe void CreateAuthentication(ApplicationProtocols.ProtocolIds alpnSupportedProtocols)
        {
            int         numberOfPackages;
            SecPkgInfo *secPointer = null;

            if (alpnSupportedProtocols > 0)
            {
                _alpnSupportedProtocols = ApplicationProtocols.GetBufferForProtocolId(alpnSupportedProtocols);
                _alpnHandle             = GCHandle.Alloc(_alpnSupportedProtocols, GCHandleType.Pinned);
            }
            try
            {
                if (InteropSspi.EnumerateSecurityPackagesW(out numberOfPackages, out secPointer) != 0)
                {
                    throw new InvalidOperationException("Unable to enumerate security packages");
                }
                var size = sizeof(SecPkgInfo);

                for (int i = 0; i < numberOfPackages; i++)
                {
                    var package = secPointer[i];
                    var name    = Marshal.PtrToStringUni(package.Name);
                    if (name == SecurityPackage)
                    {
                        _maxTokenSize = package.cbMaxToken;

                        //The correct security package is available
                        _initOkay = true;
                        GetCredentials();
                        return;
                    }
                }
                throw new InvalidOperationException($"Unable to find the security package named {SecurityPackage}");
            }
            finally
            {
                if (secPointer != null)
                {
                    InteropSspi.FreeContextBuffer((IntPtr)secPointer);
                }
            }
        }
        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}");
        }
        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}");
        }
Exemple #9
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();
                }
            }
        }