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 (_targetName != null) { _targetName.Dispose(); _targetName = null; } if (_acceptorCredential != null) { _acceptorCredential.Dispose(); _acceptorCredential = null; } } base.Dispose(disposing); }
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 SecurityStatusPal AcceptSecurityContext( SafeFreeCredentials?credentialsHandle, ref SafeDeleteContext?securityContext, ContextFlagsPal requestedContextFlags, byte[]?incomingBlob, ChannelBinding?channelBinding, ref byte[] resultBlob, ref ContextFlagsPal contextFlags) { if (securityContext == null) { securityContext = new SafeDeleteNegoContext((SafeFreeNegoCredentials)credentialsHandle !); } SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)securityContext; try { SafeGssContextHandle?contextHandle = negoContext.GssContext; bool done = GssAcceptSecurityContext( ref contextHandle, negoContext.AcceptorCredential, incomingBlob, out resultBlob, out uint outputFlags, out bool isNtlmUsed); Debug.Assert(resultBlob != null, "Unexpected null buffer returned by GssApi"); 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 !); } contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop( (Interop.NetSecurityNative.GssFlags)outputFlags, isServer: true); SecurityStatusPalErrorCode errorCode; if (done) { if (NetEventSource.Log.IsEnabled()) { string protocol = isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"; NetEventSource.Info(securityContext, $"AcceptSecurityContext: actual protocol = {protocol}"); } negoContext.SetAuthenticationPackage(isNtlmUsed); errorCode = (isNtlmUsed && resultBlob.Length > 0) ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.CompleteNeeded; } else { errorCode = SecurityStatusPalErrorCode.ContinueNeeded; } return(new SecurityStatusPal(errorCode)); } catch (Interop.NetSecurityNative.GssApiException gex) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, gex); } return(new SecurityStatusPal(GetErrorCode(gex), gex)); } catch (Exception ex) { if (NetEventSource.Log.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, byte[]?incomingBlob, ref byte[]?resultBuffer, ref ContextFlagsPal outFlags) { bool isNtlmOnly = credential.IsNtlmOnly; 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 !); } 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.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); 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.Log.IsEnabled()) { NetEventSource.Error(null, ex); } return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex)); } }
internal static partial Status GetUser( out Status minorStatus, SafeGssContextHandle?acceptContextHandle, ref GssBuffer token);
public void SetGssContext(SafeGssContextHandle context) { Debug.Assert(context != null && !context.IsInvalid, "Invalid context passed to SafeDeleteNegoContext"); _context = context; }
private static unsafe partial Status GetMic( out Status minorStatus, SafeGssContextHandle?contextHandle, byte *inputBytes, int inputLength, ref GssBuffer outBuffer);