Example #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());
        }
Example #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);
            }
            catch
            {
            }

            if (spnegoToken != null)
            {
                if (spnegoToken is SimpleProtectedNegotiationTokenInit)
                {
                    SimpleProtectedNegotiationTokenInit tokenInit = (SimpleProtectedNegotiationTokenInit)spnegoToken;
                    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)
                    {
                        NTStatus status;
                        context = new GSSContext(mechanism, null);
                        if (isPreferredMechanism)
                        {
                            byte[] mechanismOutput;
                            status      = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenInit.MechanismToken, out mechanismOutput);
                            outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier);
                        }
                        else
                        {
                            status      = NTStatus.SEC_I_CONTINUE_NEEDED;
                            outputToken = GetSPNEGOTokenResponseBytes(null, status, mechanism.Identifier);
                        }
                        return(status);
                    }
                    return(NTStatus.SEC_E_SECPKG_NOT_FOUND);
                }
                else // SimpleProtectedNegotiationTokenResponse
                {
                    if (context == null)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }
                    IGSSMechanism mechanism = context.Mechanism;
                    SimpleProtectedNegotiationTokenResponse tokenResponse = (SimpleProtectedNegotiationTokenResponse)spnegoToken;
                    byte[]   mechanismOutput;
                    NTStatus status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenResponse.ResponseToken, out mechanismOutput);
                    outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, null);
                    return(status);
                }
            }
            else
            {
                // [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))
                {
                    MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken);
                    IGSSMechanism   ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
                    if (ntlmAuthenticationProvider != null)
                    {
                        if (messageType == MessageTypeName.Negotiate)
                        {
                            context = new GSSContext(ntlmAuthenticationProvider, null);
                        }

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

                        NTStatus status = ntlmAuthenticationProvider.AcceptSecurityContext(ref context.MechanismContext, inputToken, out outputToken);
                        return(status);
                    }
                    else
                    {
                        return(NTStatus.SEC_E_SECPKG_NOT_FOUND);
                    }
                }
            }
            return(NTStatus.SEC_E_INVALID_TOKEN);
        }