/// <summary>
        /// Update SMB_COM_SESSION_SETUP response.
        /// </summary>
        /// <param name="connection">It represents the SMB connection.</param>
        /// <param name="sessionId">
        /// Set this value to 0 to request a new session setup, or set this value to a previously established session
        /// identifier to request the re-authentication of an existing session.
        /// </param>
        /// <param name="messageId">This is used to associate a response with a request.</param>
        public static void UpdateSessionSetupResponse(
            SmbConnection connection,
            int messageId,
            int sessionId)
        {
            SessionSetupRequest request = (SessionSetupRequest)connection.sentRequest[messageId];

            connection.sessionList.Add(sessionId, new SmbSession(sessionId, SessionState.Valid));
            connection.sessionId++;
            connection.SutNextReceiveSequenceNumber++;

            if (connection.isSignEnable(connection.clientSignState, connection.sutSignState))
            {
                if (request.accountType == AccountType.Admin)
                {
                    connection.isSigningActive = true;
                }
                else if (request.accountType == AccountType.Guest)
                {
                    connection.isSigningActive = false;
                }
            }

            connection.SutSendSequenceNumber.Remove(messageId);
            connection.sentRequest.Remove(messageId);
        }
Пример #2
0
        public byte[] GetAnonymousLoginSecurityBuffer()
        {
            if (!m_isConnected)
            {
                throw new InvalidOperationException("A connection must be successfully established before attempting login");
            }

            byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, string.Empty, AuthenticationMethod.NTLMv2);
            if (negotiateMessage == null)
            {
                return(null);
            }

            var request = new SessionSetupRequest
            {
                SecurityMode   = SecurityMode.SigningEnabled,
                SecurityBuffer = negotiateMessage
            };

            TrySendCommand(request);
            var response = WaitForCommand(SMB2CommandName.SessionSetup);

            if (response != null &&
                response.Header.Status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED &&
                response is SessionSetupResponse ssr)
            {
                return(ssr.SecurityBuffer);
            }
            return(null);
        }
Пример #3
0
        public NTStatus Login(string domainName, string userName, string password, AuthenticationMethod authenticationMethod)
        {
            if (!m_isConnected)
            {
                throw new InvalidOperationException("A connection must be successfully established before attempting login");
            }

            byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
            if (negotiateMessage == null)
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            SessionSetupRequest request = new SessionSetupRequest();

            request.SecurityMode   = SecurityMode.SigningEnabled;
            request.SecurityBuffer = negotiateMessage;
            TrySendCommand(request);
            SMB2Command response = WaitForCommand(SMB2CommandName.SessionSetup);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED && response is SessionSetupResponse)
                {
                    byte[] authenticateMessage = NTLMAuthenticationHelper.GetAuthenticateMessage(((SessionSetupResponse)response).SecurityBuffer, domainName, userName, password, authenticationMethod, out m_sessionKey);
                    if (authenticateMessage == null)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }

                    m_sessionID            = response.Header.SessionID;
                    request                = new SessionSetupRequest();
                    request.SecurityMode   = SecurityMode.SigningEnabled;
                    request.SecurityBuffer = authenticateMessage;
                    TrySendCommand(request);
                    response = WaitForCommand(SMB2CommandName.SessionSetup);
                    if (response != null)
                    {
                        m_isLoggedIn = (response.Header.Status == NTStatus.STATUS_SUCCESS);
                        if (m_isLoggedIn)
                        {
                            m_signingKey = SMB2Cryptography.GenerateSigningKey(m_sessionKey, m_dialect, null);
                            if (m_dialect == SMB2Dialect.SMB300)
                            {
                                m_encryptSessionData = (((SessionSetupResponse)response).SessionFlags & SessionFlags.EncryptData) > 0;
                                m_encryptionKey      = SMB2Cryptography.GenerateClientEncryptionKey(m_sessionKey, SMB2Dialect.SMB300, null);
                                m_decryptionKey      = SMB2Cryptography.GenerateClientDecryptionKey(m_sessionKey, SMB2Dialect.SMB300, null);
                            }
                        }
                        return(response.Header.Status);
                    }
                }
                else
                {
                    return(response.Header.Status);
                }
            }
            return(NTStatus.STATUS_INVALID_SMB);
        }
        /// <summary>
        /// Update SMB_COM_SESSION_SETUP request.
        /// </summary>
        /// <param name="connection">It represents the SMB connection.</param>
        /// <param name="smbRequest">It represents the SMB request.</param>
        public static void UpdateSessionSetupRequest(SmbConnection connection, SmbRequest smbRequest)
        {
            SessionSetupRequest req = smbRequest as SessionSetupRequest;

            connection.SutSendSequenceNumber.Add(smbRequest.messageId);
            connection.sentRequest.Add(smbRequest.messageId, smbRequest);
            connection.clientCapabilities = req.capabilities;
            connection.accountType        = req.accountType;
        }
Пример #5
0
        public async Task <NTStatus> LoginAsync(string domainName, string userName, string password, AuthenticationMethod authenticationMethod, CancellationToken cancellationToken)
        {
            if (!m_isConnected)
            {
                throw new InvalidOperationException("A connection must be successfully established before attempting login");
            }

            byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
            if (negotiateMessage == null)
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            SessionSetupRequest request = new SessionSetupRequest();

            request.SecurityMode   = SecurityMode.SigningEnabled;
            request.SecurityBuffer = negotiateMessage;
            await TrySendCommandAsync(request, cancellationToken);

            SMB2Command response = WaitForCommand(SMB2CommandName.SessionSetup);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED && response is SessionSetupResponse)
                {
                    byte[] authenticateMessage = NTLMAuthenticationHelper.GetAuthenticateMessage(((SessionSetupResponse)response).SecurityBuffer, domainName, userName, password, authenticationMethod, out m_sessionKey);
                    if (authenticateMessage == null)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }

                    m_sessionID            = response.Header.SessionID;
                    request                = new SessionSetupRequest();
                    request.SecurityMode   = SecurityMode.SigningEnabled;
                    request.SecurityBuffer = authenticateMessage;
                    await TrySendCommandAsync(request, cancellationToken);

                    response = WaitForCommand(SMB2CommandName.SessionSetup);
                    if (response != null)
                    {
                        m_isLoggedIn = (response.Header.Status == NTStatus.STATUS_SUCCESS);
                        return(response.Header.Status);
                    }
                }
                else
                {
                    return(response.Header.Status);
                }
            }
            return(NTStatus.STATUS_INVALID_SMB);
        }
Пример #6
0
        SMB2Message SendSessionSetupRequest(ulong mid, ulong sessionId, byte[] secData)
        {
            SMB2Header  smb2Header  = new SMB2Header(ESMB2Command.SESSION_SETUP, SMB2HeaderFlags.None, mid, 0, sessionId);
            SMB2Body    smb2Body    = new SessionSetupRequest(secData);
            SMB2Message smb2Message = new SMB2Message(smb2Header, smb2Body);

            SMBTransport.SendDatas(smb2Message.DumpBinary());
            var sm = GetMessage(mid);

            if (sm.SMB2Header.Status != NTStateType.Success && sm.SMB2Header.Status != NTStateType.MoreProcessingRequired)
            {
                throw new Exception("SessionSetup Status error:" + sm.SMB2Header.Status);
            }
            return(sm);
        }
Пример #7
0
        internal static SMB2Command GetSessionSetupResponse(SessionSetupRequest request, GSSProvider securityProvider, SMB2ConnectionState state)
        {
            // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication.
            SessionSetupResponse response = new SessionSetupResponse();

            byte[]   outputToken;
            NTStatus status = securityProvider.AcceptSecurityContext(ref state.AuthenticationContext, request.SecurityBuffer, out outputToken);

            if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.SEC_I_CONTINUE_NEEDED)
            {
                string userName    = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
                string domainName  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
                string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
                string osVersion   = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
                state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), NTStatus: {4}", userName, domainName, machineName, osVersion, status);
                return(new ErrorResponse(request.CommandName, status));
            }

            if (outputToken != null)
            {
                response.SecurityBuffer = outputToken;
            }

            // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED
            if (request.Header.SessionID == 0)
            {
                ulong?sessionID = state.AllocateSessionID();
                if (!sessionID.HasValue)
                {
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS));
                }
                response.Header.SessionID = sessionID.Value;
            }

            if (status == NTStatus.SEC_I_CONTINUE_NEEDED)
            {
                response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
            }
            else // status == STATUS_SUCCESS
            {
                string userName    = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
                string domainName  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
                string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
                string osVersion   = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
                byte[] sessionKey  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[];
                object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken);
                bool?  isGuest     = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?;
                if (!isGuest.HasValue || !isGuest.Value)
                {
                    state.LogToServer(Severity.Information, "Session Setup: User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}', OS version: '{3}').", userName, domainName, machineName, osVersion);
                    bool        signingRequired = (request.SecurityMode & SecurityMode.SigningRequired) > 0;
                    SMB2Dialect smb2Dialect     = SMBServer.ToSMB2Dialect(state.Dialect);
                    byte[]      signingKey      = SMB2Cryptography.GenerateSigningKey(sessionKey, smb2Dialect, null);
                    state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken, signingRequired, signingKey);
                }
                else
                {
                    state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), logged in as guest.", userName, domainName, machineName, osVersion);
                    state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken, false, null);
                    response.SessionFlags = SessionFlags.IsGuest;
                }
            }
            return(response);
        }