コード例 #1
0
        private static byte[] GetSpnegoTokenResponseBytes(byte[] mechanismOutput, NTStatus status, byte[]?mechanismIdentifier)
        {
            SimpleProtectedNegotiationTokenResponse tokenResponse = new SimpleProtectedNegotiationTokenResponse();

            if (status == NTStatus.STATUS_SUCCESS)
            {
                tokenResponse.NegState = NegState.AcceptCompleted;
            }
            else if (status == NTStatus.SEC_I_CONTINUE_NEEDED)
            {
                tokenResponse.NegState = NegState.AcceptIncomplete;
            }
            else
            {
                tokenResponse.NegState = NegState.Reject;
            }
            tokenResponse.SupportedMechanism = mechanismIdentifier;
            tokenResponse.ResponseToken      = mechanismOutput;
            return(tokenResponse.GetBytes());
        }
コード例 #2
0
        public virtual NTStatus AcceptSecurityContext(ref GssContext?context, byte[] inputToken, out byte[]?outputToken)
        {
            outputToken = null;
            SimpleProtectedNegotiationToken?spnegoToken = null;

            try
            {
                spnegoToken = SimpleProtectedNegotiationToken.ReadToken(inputToken, 0, false);
            }
            catch
            {
                // ignored
            }

            if (spnegoToken != null)
            {
                if (spnegoToken is SimpleProtectedNegotiationTokenInit tokenInit)
                {
                    if (tokenInit.MechanismTypeList.Count == 0)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }

                    // RFC 4178: Note that in order to avoid an extra round trip, the first context establishment token
                    // of the initiator's preferred mechanism SHOULD be embedded in the initial negotiation message.
                    byte[]        preferredMechanism   = tokenInit.MechanismTypeList[0];
                    IGssMechanism?mechanism            = FindMechanism(preferredMechanism);
                    bool          isPreferredMechanism = (mechanism != null);
                    if (!isPreferredMechanism)
                    {
                        mechanism = FindMechanism(tokenInit.MechanismTypeList);
                    }

                    if (mechanism == null)
                    {
                        return(NTStatus.SEC_E_SECPKG_NOT_FOUND);
                    }
                    NTStatus status;
                    context = new GssContext(mechanism, null);
                    if (isPreferredMechanism)
                    {
                        status      = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenInit.MechanismToken, out byte[] mechanismOutput);
                        outputToken = GetSpnegoTokenResponseBytes(mechanismOutput, status, mechanism.Identifier);
                    }
                    else
                    {
                        status      = NTStatus.SEC_I_CONTINUE_NEEDED;
                        outputToken = GetSpnegoTokenResponseBytes(null, status, mechanism.Identifier);
                    }
                    return(status);
                }
                else // SimpleProtectedNegotiationTokenResponse
                {
                    if (context == null)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }
                    IGssMechanism mechanism = context.Mechanism;
                    SimpleProtectedNegotiationTokenResponse tokenResponse = (SimpleProtectedNegotiationTokenResponse)spnegoToken;
                    NTStatus status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenResponse.ResponseToken, out byte[] mechanismOutput);
                    outputToken = GetSpnegoTokenResponseBytes(mechanismOutput, status, null);
                    return(status);
                }
            }

            // [MS-SMB] The Windows GSS implementation supports raw Kerberos / NTLM messages in the SecurityBlob.
            // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication.
            if (!AuthenticationMessageUtils.IsSignatureValid(inputToken))
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken);
            IGssMechanism?  ntlmAuthenticationProvider = FindMechanism(NtlmSspIdentifier);

            if (ntlmAuthenticationProvider == null)
            {
                return(NTStatus.SEC_E_SECPKG_NOT_FOUND);
            }

            if (messageType == MessageTypeName.Negotiate)
            {
                context = new GssContext(ntlmAuthenticationProvider, null);
            }

            if (context == null)
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            return(ntlmAuthenticationProvider.AcceptSecurityContext(ref context.MechanismContext, inputToken, out outputToken));
        }