public void Dispose() { if (_contextPointer.IsValid) { InteropSspi.DeleteSecurityContext(ref _contextPointer); } }
public void Dispose() { InteropSspi.FreeCredentialsHandle(ref _credsHandle); if (_alpnHandle.IsAllocated) { _alpnHandle.Free(); } }
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"); } }
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}"); } }
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}"); }
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(); } } }