/// <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); }
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); }
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; }
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); }
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); }
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); }