internal static extern Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, bool isNtlmOnly, SafeGssNameHandle?targetName, uint reqFlags, byte[]?inputBytes, int inputLength, ref GssBuffer token, out uint retFlags, out bool isNtlmUsed);
private static partial Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, [MarshalAs(UnmanagedType.Bool)] bool isNtlmOnly, SafeGssNameHandle?targetName, uint reqFlags, ref byte inputBytes, int inputLength, ref GssBuffer token, out uint retFlags, [MarshalAs(UnmanagedType.Bool)] out bool isNtlmUsed);
private static bool GssAcceptSecurityContext( ref SafeGssContextHandle?context, SafeGssCredHandle credential, byte[]?buffer, out byte[] outputBuffer, out uint outFlags, out bool isNtlmUsed) { Debug.Assert(credential != null); bool newContext = false; if (context == null) { newContext = true; context = new SafeGssContextHandle(); } Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; try { Interop.NetSecurityNative.Status minorStatus; status = Interop.NetSecurityNative.AcceptSecContext(out minorStatus, credential, ref context, buffer, buffer?.Length ?? 0, ref token, out outFlags, out isNtlmUsed); if ((status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) && (status != Interop.NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { if (newContext) { context.Dispose(); context = null; } throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } outputBuffer = token.ToByteArray(); } finally { token.Dispose(); } return(status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE); }
internal static bool EstablishSecurityContext( ref SafeGssContextHandle context, SafeGssCredHandle credential, bool isNtlm, SafeGssNameHandle targetName, Interop.NetSecurityNative.GssFlags inFlags, byte[] buffer, out byte[] outputBuffer, out uint outFlags) { outputBuffer = null; outFlags = 0; // EstablishSecurityContext is called multiple times in a session. // In each call, we need to pass the context handle from the previous call. // For the first call, the context handle will be null. if (context == null) { context = new SafeGssContextHandle(); } Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; try { Interop.NetSecurityNative.Status minorStatus; status = NetSecurityNative.InitSecContext(out minorStatus, credential, ref context, isNtlm, targetName, (uint)inFlags, buffer, (buffer == null) ? 0 : buffer.Length, ref token, out outFlags); if ((status != NetSecurityNative.Status.GSS_S_COMPLETE) && (status != NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { throw new NetSecurityNative.GssApiException(status, minorStatus); } outputBuffer = token.ToByteArray(); } finally { token.Dispose(); } return(status == NetSecurityNative.Status.GSS_S_COMPLETE); }
internal static Status UnwrapBuffer( out Status minorStatus, SafeGssContextHandle contextHandle, byte[] inputBytes, int offset, int count, ref GssBuffer outBuffer) { Debug.Assert(inputBytes != null, "inputBytes must be valid value"); Debug.Assert(offset >= 0 && offset <= inputBytes.Length, "offset must be valid"); Debug.Assert(count >= 0 && count <= inputBytes.Length, "count must be valid"); return(Unwrap(out minorStatus, contextHandle, inputBytes, offset, count, ref outBuffer)); }
public SafeDeleteNegoContext(SafeFreeNegoCredentials credential, string targetName) : this(credential) { try { _targetName = SafeGssNameHandle.CreateTarget(targetName); _context = new SafeGssContextHandle(); } catch { Dispose(); throw; } }
internal static Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, bool isNtlmOnly, IntPtr cbt, int cbtSize, SafeGssNameHandle targetName, uint reqFlags, byte[] inputBytes, int inputLength, ref GssBuffer token, out uint retFlags, out int isNtlmUsed) => throw new PlatformNotSupportedException();
internal static extern Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, bool isNtlmOnly, IntPtr cbt, int cbtSize, bool isNtlmFallback, SafeGssNameHandle targetNameKerberos, SafeGssNameHandle targetNameNtlm, uint reqFlags, byte[] inputBytes, int inputLength, ref GssBuffer token, out uint retFlags, out bool isNtlmUsed);
protected override void Dispose(bool disposing) { if (disposing) { if (null != _context) { _context.Dispose(); _context = null; } if (_targetName != null) { _targetName.Dispose(); _targetName = null; } } base.Dispose(disposing); }
public SafeDeleteNegoContext(SafeFreeNegoCredentials credential, string targetName) : base(IntPtr.Zero) { try { _targetName = SafeGssNameHandle.CreateTarget(targetName); _context = new SafeGssContextHandle(); } catch { Dispose(); throw; } _credential = credential; bool ignore = false; _credential.DangerousAddRef(ref ignore); }
internal static Status AcceptSecContext( out Status minorStatus, SafeGssCredHandle acceptorCredHandle, ref SafeGssContextHandle acceptContextHandle, ReadOnlySpan <byte> inputBytes, ref GssBuffer token, out uint retFlags, out bool isNtlmUsed) { return(AcceptSecContext( out minorStatus, acceptorCredHandle, ref acceptContextHandle, ref MemoryMarshal.GetReference(inputBytes), inputBytes.Length, ref token, out retFlags, out isNtlmUsed)); }
private static string GetUser( ref SafeDeleteContext securityContext) { SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)securityContext; try { SafeGssContextHandle contextHandle = negoContext.GssContext; return(GssGetUser(ref contextHandle)); } catch (Exception ex) { if (NetEventSource.IsEnabled) { NetEventSource.Error(null, ex); } throw; } }
private static bool EstablishSecurityContext( ref SafeGssContextHandle context, byte[] buffer, out byte[] outputBuffer) { outputBuffer = null; // EstablishSecurityContext is called multiple times in a session. // In each call, we need to pass the context handle from the previous call. // For the first call, the context handle will be null. if (context == null) { context = new SafeGssContextHandle(); } Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; try { Interop.NetSecurityNative.Status minorStatus; status = Interop.NetSecurityNative.AcceptSecContext(out minorStatus, ref context, buffer, (buffer == null) ? 0 : buffer.Length, ref token); if ((status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) && (status != Interop.NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } outputBuffer = token.ToByteArray(); } finally { token.Dispose(); } return(status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE); }
internal static NegotiateAuthenticationStatusCode Unwrap( SafeDeleteContext securityContext, ReadOnlySpan <byte> input, IBufferWriter <byte> outputWriter, out bool isEncrypted) { SafeGssContextHandle gssContext = ((SafeDeleteNegoContext)securityContext).GssContext !; Interop.NetSecurityNative.GssBuffer decryptedBuffer = default(Interop.NetSecurityNative.GssBuffer); try { Interop.NetSecurityNative.Status minorStatus; Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.UnwrapBuffer(out minorStatus, gssContext, out isEncrypted, input, ref decryptedBuffer); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { return(status switch { Interop.NetSecurityNative.Status.GSS_S_BAD_SIG => NegotiateAuthenticationStatusCode.MessageAltered, _ => NegotiateAuthenticationStatusCode.InvalidToken }); }
private static byte[] GssWrap( SafeGssContextHandle context, ref bool encrypt, ReadOnlySpan <byte> buffer) { Interop.NetSecurityNative.GssBuffer encryptedBuffer = default; try { Interop.NetSecurityNative.Status minorStatus; Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.WrapBuffer(out minorStatus, context, ref encrypt, buffer, ref encryptedBuffer); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } return(encryptedBuffer.ToByteArray()); } finally { encryptedBuffer.Dispose(); } }
private static byte[] WrapMessage(SafeGssContextHandle context, byte[] message) { Interop.NetSecurityNative.GssBuffer wrapped = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; try { Interop.NetSecurityNative.Status minorStatus; status = Interop.NetSecurityNative.WrapBuffer(out minorStatus, context, false, message, 0, message.Length, ref wrapped); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } return(wrapped.ToByteArray()); } finally { wrapped.Dispose(); } }
private static int GssUnwrap( SafeGssContextHandle context, out bool encrypt, Span <byte> buffer) { Interop.NetSecurityNative.GssBuffer decryptedBuffer = default(Interop.NetSecurityNative.GssBuffer); try { Interop.NetSecurityNative.Status minorStatus; Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.UnwrapBuffer(out minorStatus, context, out encrypt, buffer, ref decryptedBuffer); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } decryptedBuffer.Span.CopyTo(buffer); return(decryptedBuffer.Span.Length); } finally { decryptedBuffer.Dispose(); } }
internal static int Decrypt( SafeDeleteContext securityContext, Span <byte> buffer, bool isConfidential, bool isNtlm, out int newOffset) { SafeGssContextHandle gssContext = ((SafeDeleteNegoContext)securityContext).GssContext !; if (isNtlm && !isConfidential) { const int NtlmSignatureLength = 16; if (buffer.Length < NtlmSignatureLength) { Debug.Fail("Argument 'count' out of range."); throw new Interop.NetSecurityNative.GssApiException(Interop.NetSecurityNative.Status.GSS_S_DEFECTIVE_TOKEN, 0); } Interop.NetSecurityNative.Status minorStatus; Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.VerifyMic( out minorStatus, gssContext, buffer.Slice(NtlmSignatureLength), buffer.Slice(0, NtlmSignatureLength)); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } newOffset = NtlmSignatureLength; return(buffer.Length - NtlmSignatureLength); } newOffset = 0; return(GssUnwrap(gssContext, out _, buffer)); }
private static string GssGetUser( ref SafeGssContextHandle context) { Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); try { Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.GetUser(out var minorStatus, context, ref token); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } ReadOnlySpan <byte> tokenBytes = token.Span; int length = tokenBytes.Length; if (length > 0 && tokenBytes[length - 1] == '\0') { // Some GSS-API providers (gss-ntlmssp) include the terminating null with strings, so skip that. tokenBytes = tokenBytes.Slice(0, length - 1); } #if NETSTANDARD2_0 return(Encoding.UTF8.GetString(tokenBytes.ToArray(), 0, tokenBytes.Length)); #else return(Encoding.UTF8.GetString(tokenBytes)); #endif } finally { token.Dispose(); } }
protected override void Dispose(bool disposing) { if (disposing) { if (null != _context) { _context.Dispose(); _context = null; } if (_targetNameKerberos != null) { _targetNameKerberos.Dispose(); _targetNameKerberos = null; } if (_targetNameNtlm != null) { _targetNameNtlm.Dispose(); _targetNameNtlm = null; } } base.Dispose(disposing); }
private static string GssGetUser( ref SafeGssContextHandle context) { Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); try { Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.GetUser(out var minorStatus, context, ref token); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } return(Encoding.UTF8.GetString(token.ToByteArray())); } finally { token.Dispose(); } }
private static bool GssInitSecurityContext( ref SafeGssContextHandle?context, SafeGssCredHandle credential, bool isNtlm, ChannelBinding?channelBinding, SafeGssNameHandle?targetName, Interop.NetSecurityNative.GssFlags inFlags, byte[]?buffer, out byte[]?outputBuffer, out uint outFlags, out bool isNtlmUsed) { outputBuffer = null; outFlags = 0; // EstablishSecurityContext is called multiple times in a session. // In each call, we need to pass the context handle from the previous call. // For the first call, the context handle will be null. bool newContext = false; if (context == null) { newContext = true; context = new SafeGssContextHandle(); } Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; try { Interop.NetSecurityNative.Status minorStatus; if (channelBinding != null) { // If a TLS channel binding token (cbt) is available then get the pointer // to the application specific data. int appDataOffset = Marshal.SizeOf <SecChannelBindings>(); Debug.Assert(appDataOffset < channelBinding.Size); IntPtr cbtAppData = channelBinding.DangerousGetHandle() + appDataOffset; int cbtAppDataSize = channelBinding.Size - appDataOffset; status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential, ref context, isNtlm, cbtAppData, cbtAppDataSize, targetName, (uint)inFlags, buffer, (buffer == null) ? 0 : buffer.Length, ref token, out outFlags, out isNtlmUsed); } else { status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential, ref context, isNtlm, targetName, (uint)inFlags, buffer, (buffer == null) ? 0 : buffer.Length, ref token, out outFlags, out isNtlmUsed); } if ((status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) && (status != Interop.NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { if (newContext) { context.Dispose(); context = null; } throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); } outputBuffer = token.ToByteArray(); } finally { token.Dispose(); } return(status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE); }
internal static extern Status AcceptSecContext( out Status minorStatus, ref SafeGssContextHandle acceptContextHandle, byte[] inputBytes, int inputLength, ref GssBuffer token);
private static SecurityStatusPal EstablishSecurityContext( SafeFreeNegoCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlagsPal inFlags, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlagsPal outFlags) { bool isNtlmOnly = credential.IsNtlmOnly; if (context == null) { // Empty target name causes the failure on Linux, hence passing a non-empty string context = isNtlmOnly ? new SafeDeleteNegoContext(credential, credential.UserName) : new SafeDeleteNegoContext(credential, targetName); } SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)context; try { Interop.NetSecurityNative.GssFlags inputFlags = ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(inFlags, isServer: false); uint outputFlags; int isNtlmUsed; SafeGssContextHandle contextHandle = negoContext.GssContext; bool done = GssInitSecurityContext( ref contextHandle, credential.GssCredential, isNtlmOnly, negoContext.TargetName, inputFlags, inputBuffer?.token, out outputBuffer.token, out outputFlags, out isNtlmUsed); Debug.Assert(outputBuffer.token != null, "Unexpected null buffer returned by GssApi"); outputBuffer.size = outputBuffer.token.Length; outputBuffer.offset = 0; outFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop((Interop.NetSecurityNative.GssFlags)outputFlags, isServer: false); Debug.Assert(negoContext.GssContext == null || contextHandle == negoContext.GssContext); // Save the inner context handle for further calls to NetSecurity Debug.Assert(negoContext.GssContext == null || contextHandle == negoContext.GssContext); if (null == negoContext.GssContext) { negoContext.SetGssContext(contextHandle); } // Populate protocol used for authentication if (done) { negoContext.SetAuthenticationPackage(Convert.ToBoolean(isNtlmUsed)); } SecurityStatusPalErrorCode errorCode = done ? (negoContext.IsNtlmUsed && outputBuffer.size > 0 ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.CompleteNeeded) : SecurityStatusPalErrorCode.ContinueNeeded; return(new SecurityStatusPal(errorCode)); } catch (Exception ex) { if (NetEventSource.IsEnabled) { NetEventSource.Error(null, ex); } return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex)); } }
private static SecurityStatusPal EstablishSecurityContext( SafeFreeNegoCredentials credential, ref SafeDeleteContext?context, ChannelBinding?channelBinding, string?targetName, ContextFlagsPal inFlags, ReadOnlySpan <byte> incomingBlob, out byte[]?resultBuffer, ref ContextFlagsPal outFlags) { bool isNtlmOnly = credential.IsNtlmOnly; resultBuffer = null; if (context == null) { if (NetEventSource.Log.IsEnabled()) { string protocol = isNtlmOnly ? "NTLM" : "SPNEGO"; NetEventSource.Info(context, $"requested protocol = {protocol}, target = {targetName}"); } context = new SafeDeleteNegoContext(credential, targetName !); } Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); Interop.NetSecurityNative.Status status; Interop.NetSecurityNative.Status minorStatus; SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)context; SafeGssContextHandle contextHandle = negoContext.GssContext; try { Interop.NetSecurityNative.GssFlags inputFlags = ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(inFlags, isServer: false); uint outputFlags; bool isNtlmUsed; if (channelBinding != null) { // If a TLS channel binding token (cbt) is available then get the pointer // to the application specific data. int appDataOffset = Marshal.SizeOf <SecChannelBindings>(); Debug.Assert(appDataOffset < channelBinding.Size); IntPtr cbtAppData = channelBinding.DangerousGetHandle() + appDataOffset; int cbtAppDataSize = channelBinding.Size - appDataOffset; status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential.GssCredential, ref contextHandle, isNtlmOnly, cbtAppData, cbtAppDataSize, negoContext.TargetName, (uint)inputFlags, incomingBlob, ref token, out outputFlags, out isNtlmUsed); } else { status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential.GssCredential, ref contextHandle, isNtlmOnly, negoContext.TargetName, (uint)inputFlags, incomingBlob, ref token, out outputFlags, out isNtlmUsed); } if ((status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) && (status != Interop.NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { if (negoContext.GssContext.IsInvalid) { context.Dispose(); } Interop.NetSecurityNative.GssApiException gex = new Interop.NetSecurityNative.GssApiException(status, minorStatus); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, gex); } resultBuffer = Array.Empty <byte>(); return(new SecurityStatusPal(GetErrorCode(gex), gex)); } resultBuffer = token.ToByteArray(); if (status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { if (NetEventSource.Log.IsEnabled()) { string protocol = isNtlmOnly ? "NTLM" : isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"; NetEventSource.Info(context, $"actual protocol = {protocol}"); } // Populate protocol used for authentication negoContext.SetAuthenticationPackage(isNtlmUsed); } Debug.Assert(resultBuffer != null, "Unexpected null buffer returned by GssApi"); outFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop( (Interop.NetSecurityNative.GssFlags)outputFlags, isServer: false); SecurityStatusPalErrorCode errorCode = status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.ContinueNeeded; return(new SecurityStatusPal(errorCode)); } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, ex); } return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex)); } finally { token.Dispose(); // Save the inner context handle for further calls to NetSecurity // // For the first call `negoContext.GssContext` is invalid and we expect the // inital handle to be returned from InitSecContext. For any subsequent // call the handle should stay the same or it can be destroyed by the native // InitSecContext call. Debug.Assert( negoContext.GssContext == contextHandle || negoContext.GssContext.IsInvalid || contextHandle.IsInvalid); negoContext.SetGssContext(contextHandle); } }
internal static SecurityStatusPal AcceptSecurityContext( SafeFreeCredentials?credentialsHandle, ref SafeDeleteContext?securityContext, ContextFlagsPal requestedContextFlags, ReadOnlySpan <byte> incomingBlob, ChannelBinding?channelBinding, ref byte[] resultBlob, out int resultBlobLength, ref ContextFlagsPal contextFlags) { securityContext ??= new SafeDeleteNegoContext((SafeFreeNegoCredentials)credentialsHandle !); SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)securityContext; SafeGssContextHandle contextHandle = negoContext.GssContext; Interop.NetSecurityNative.GssBuffer token = default(Interop.NetSecurityNative.GssBuffer); try { Interop.NetSecurityNative.Status status; Interop.NetSecurityNative.Status minorStatus; status = Interop.NetSecurityNative.AcceptSecContext(out minorStatus, negoContext.AcceptorCredential, ref contextHandle, incomingBlob, ref token, out uint outputFlags, out bool isNtlmUsed); if ((status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) && (status != Interop.NetSecurityNative.Status.GSS_S_CONTINUE_NEEDED)) { if (negoContext.GssContext.IsInvalid) { contextHandle.Dispose(); } Interop.NetSecurityNative.GssApiException gex = new Interop.NetSecurityNative.GssApiException(status, minorStatus); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, gex); } resultBlobLength = 0; return(new SecurityStatusPal(GetErrorCode(gex), gex)); } resultBlob = token.ToByteArray(); Debug.Assert(resultBlob != null, "Unexpected null buffer returned by GssApi"); contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop( (Interop.NetSecurityNative.GssFlags)outputFlags, isServer: true); resultBlobLength = resultBlob.Length; SecurityStatusPalErrorCode errorCode; if (status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { if (NetEventSource.Log.IsEnabled()) { string protocol = isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"; NetEventSource.Info(securityContext, $"AcceptSecurityContext: actual protocol = {protocol}"); } negoContext.SetAuthenticationPackage(isNtlmUsed); errorCode = SecurityStatusPalErrorCode.OK; } else { errorCode = SecurityStatusPalErrorCode.ContinueNeeded; } return(new SecurityStatusPal(errorCode)); } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, ex); } resultBlobLength = 0; return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex)); } finally { token.Dispose(); // Save the inner context handle for further calls to NetSecurity // // For the first call `negoContext.GssContext` is invalid and we expect the // inital handle to be returned from AcceptSecContext. For any subsequent // call the handle should stay the same or it can be destroyed by the native // AcceptSecContext call. Debug.Assert( negoContext.GssContext == contextHandle || negoContext.GssContext.IsInvalid || contextHandle.IsInvalid); negoContext.SetGssContext(contextHandle); } }
public void SetGssContext(SafeGssContextHandle context) { Debug.Assert(context != null && !context.IsInvalid, "Invalid context passed to SafeDeleteNegoContext"); _context = context; }
internal static extern Status GetUser( out Status minorStatus, SafeGssContextHandle acceptContextHandle, ref GssBuffer token);
internal static Status AcceptSecContext( out Status minorStatus, ref SafeGssContextHandle acceptContextHandle, byte[] inputBytes, int inputLength, ref GssBuffer token) => throw new NotSupportedException();
private static SecurityStatusPal EstablishSecurityContext( SafeFreeNegoCredentials credential, ref SafeDeleteContext context, ChannelBinding channelBinding, string targetName, ContextFlagsPal inFlags, byte[] incomingBlob, ref byte[] resultBuffer, ref ContextFlagsPal outFlags) { bool isNtlmOnly = credential.IsNtlmOnly; if (context == null) { if (NetEventSource.IsEnabled) { string protocol = isNtlmOnly ? "NTLM" : "SPNEGO"; NetEventSource.Info(null, $"requested protocol = {protocol}, target = {targetName}"); } context = new SafeDeleteNegoContext(credential, targetName); } SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)context; try { Interop.NetSecurityNative.GssFlags inputFlags = ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(inFlags, isServer: false); uint outputFlags; bool isNtlmUsed; SafeGssContextHandle contextHandle = negoContext.GssContext; bool done = GssInitSecurityContext( ref contextHandle, credential.GssCredential, isNtlmOnly, channelBinding, negoContext.TargetName, inputFlags, incomingBlob, out resultBuffer, out outputFlags, out isNtlmUsed); if (done) { if (NetEventSource.IsEnabled) { string protocol = isNtlmOnly ? "NTLM" : isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"; NetEventSource.Info(null, $"actual protocol = {protocol}"); } // Populate protocol used for authentication negoContext.SetAuthenticationPackage(isNtlmUsed); } Debug.Assert(resultBuffer != null, "Unexpected null buffer returned by GssApi"); outFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop( (Interop.NetSecurityNative.GssFlags)outputFlags, isServer: false); Debug.Assert(negoContext.GssContext == null || contextHandle == negoContext.GssContext); // Save the inner context handle for further calls to NetSecurity Debug.Assert(negoContext.GssContext == null || contextHandle == negoContext.GssContext); if (null == negoContext.GssContext) { negoContext.SetGssContext(contextHandle); } SecurityStatusPalErrorCode errorCode = done ? (negoContext.IsNtlmUsed && resultBuffer.Length > 0 ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.CompleteNeeded) : SecurityStatusPalErrorCode.ContinueNeeded; return(new SecurityStatusPal(errorCode)); } catch (Exception ex) { if (NetEventSource.IsEnabled) { NetEventSource.Error(null, ex); } return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex)); } }