diff --git a/SMBLibrary/SMBLibrary.csproj b/SMBLibrary/SMBLibrary.csproj index 96b852f..287cf4c 100644 --- a/SMBLibrary/SMBLibrary.csproj +++ b/SMBLibrary/SMBLibrary.csproj @@ -127,6 +127,7 @@ + diff --git a/SMBLibrary/Server/SMB1/NegotiateHelper.cs b/SMBLibrary/Server/SMB1/NegotiateHelper.cs index 7f0e65a..869a802 100644 --- a/SMBLibrary/Server/SMB1/NegotiateHelper.cs +++ b/SMBLibrary/Server/SMB1/NegotiateHelper.cs @@ -14,7 +14,7 @@ using Utilities; namespace SMBLibrary.Server.SMB1 { /// - /// Negotiate and Session Setup helper + /// Negotiate helper /// public class NegotiateHelper { @@ -67,119 +67,5 @@ namespace SMBLibrary.Server.SMB1 return response; } - - internal static SMB1Command GetSessionSetupResponse(SMB1Header header, SessionSetupAndXRequest request, INTLMAuthenticationProvider users, SMB1ConnectionState state) - { - SessionSetupAndXResponse response = new SessionSetupAndXResponse(); - // The PrimaryDomain field in the request is used to determine with domain controller should authenticate the user credentials, - // However, the domain controller itself does not use this field. - // See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749%28v=vs.85%29.aspx - User user; - try - { - user = users.Authenticate(request.AccountName, request.OEMPassword, request.UnicodePassword); - } - catch(EmptyPasswordNotAllowedException) - { - header.Status = NTStatus.STATUS_ACCOUNT_RESTRICTION; - return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); - } - - if (user != null) - { - response.PrimaryDomain = request.PrimaryDomain; - header.UID = state.AddConnectedUser(user.AccountName); - } - else if (users.EnableGuestLogin) - { - response.Action = SessionSetupAction.SetupGuest; - response.PrimaryDomain = request.PrimaryDomain; - header.UID = state.AddConnectedUser("Guest"); - } - else - { - header.Status = NTStatus.STATUS_LOGON_FAILURE; - return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); - } - if ((request.Capabilities & ServerCapabilities.LargeRead) > 0) - { - state.LargeRead = true; - } - if ((request.Capabilities & ServerCapabilities.LargeWrite) > 0) - { - state.LargeWrite = true; - } - response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" - response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" - - return response; - } - - internal static SMB1Command GetSessionSetupResponseExtended(SMB1Header header, SessionSetupAndXRequestExtended request, INTLMAuthenticationProvider users, SMB1ConnectionState state) - { - SessionSetupAndXResponseExtended response = new SessionSetupAndXResponseExtended(); - - // [MS-SMB] The Windows GSS implementation supports raw Kerberos / NTLM messages in the SecurityBlob - byte[] messageBytes = request.SecurityBlob; - bool isRawMessage = true; - if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes)) - { - messageBytes = GSSAPIHelper.GetNTLMSSPMessage(request.SecurityBlob); - isRawMessage = false; - } - if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes)) - { - header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; - return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); - } - - MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(messageBytes); - if (messageType == MessageTypeName.Negotiate) - { - byte[] challengeMessageBytes = users.GetChallengeMessageBytes(messageBytes); - if (isRawMessage) - { - response.SecurityBlob = challengeMessageBytes; - } - else - { - response.SecurityBlob = GSSAPIHelper.GetGSSTokenResponseBytesFromNTLMSSPMessage(challengeMessageBytes); - } - header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED; - } - else // MessageTypeName.Authenticate - { - User user; - try - { - user = users.Authenticate(messageBytes); - } - catch(EmptyPasswordNotAllowedException) - { - header.Status = NTStatus.STATUS_ACCOUNT_RESTRICTION; - return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); - } - - - if (user != null) - { - header.UID = state.AddConnectedUser(user.AccountName); - } - else if (users.EnableGuestLogin) - { - response.Action = SessionSetupAction.SetupGuest; - header.UID = state.AddConnectedUser("Guest"); - } - else - { - header.Status = NTStatus.STATUS_LOGON_FAILURE; - return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); - } - } - response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" - response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" - - return response; - } } } diff --git a/SMBLibrary/Server/SMB1/SessionSetupHelper.cs b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs new file mode 100644 index 0000000..4881642 --- /dev/null +++ b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs @@ -0,0 +1,135 @@ +/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. + * + * You can redistribute this program and/or modify it under the terms of + * the GNU Lesser Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + */ +using System; +using System.Collections.Generic; +using System.Text; +using SMBLibrary.Authentication; +using SMBLibrary.SMB1; +using Utilities; + +namespace SMBLibrary.Server.SMB1 +{ + /// + /// Session Setup helper + /// + public class SessionSetupHelper + { + internal static SMB1Command GetSessionSetupResponse(SMB1Header header, SessionSetupAndXRequest request, INTLMAuthenticationProvider users, SMB1ConnectionState state) + { + SessionSetupAndXResponse response = new SessionSetupAndXResponse(); + // The PrimaryDomain field in the request is used to determine with domain controller should authenticate the user credentials, + // However, the domain controller itself does not use this field. + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749%28v=vs.85%29.aspx + User user; + try + { + user = users.Authenticate(request.AccountName, request.OEMPassword, request.UnicodePassword); + } + catch (EmptyPasswordNotAllowedException) + { + header.Status = NTStatus.STATUS_ACCOUNT_RESTRICTION; + return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); + } + + if (user != null) + { + response.PrimaryDomain = request.PrimaryDomain; + header.UID = state.AddConnectedUser(user.AccountName); + } + else if (users.EnableGuestLogin) + { + response.Action = SessionSetupAction.SetupGuest; + response.PrimaryDomain = request.PrimaryDomain; + header.UID = state.AddConnectedUser("Guest"); + } + else + { + header.Status = NTStatus.STATUS_LOGON_FAILURE; + return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); + } + if ((request.Capabilities & ServerCapabilities.LargeRead) > 0) + { + state.LargeRead = true; + } + if ((request.Capabilities & ServerCapabilities.LargeWrite) > 0) + { + state.LargeWrite = true; + } + response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" + response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" + + return response; + } + + internal static SMB1Command GetSessionSetupResponseExtended(SMB1Header header, SessionSetupAndXRequestExtended request, INTLMAuthenticationProvider users, SMB1ConnectionState state) + { + SessionSetupAndXResponseExtended response = new SessionSetupAndXResponseExtended(); + + // [MS-SMB] The Windows GSS implementation supports raw Kerberos / NTLM messages in the SecurityBlob + byte[] messageBytes = request.SecurityBlob; + bool isRawMessage = true; + if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes)) + { + messageBytes = GSSAPIHelper.GetNTLMSSPMessage(request.SecurityBlob); + isRawMessage = false; + } + if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes)) + { + header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; + return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); + } + + MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(messageBytes); + if (messageType == MessageTypeName.Negotiate) + { + byte[] challengeMessageBytes = users.GetChallengeMessageBytes(messageBytes); + if (isRawMessage) + { + response.SecurityBlob = challengeMessageBytes; + } + else + { + response.SecurityBlob = GSSAPIHelper.GetGSSTokenResponseBytesFromNTLMSSPMessage(challengeMessageBytes); + } + header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED; + } + else // MessageTypeName.Authenticate + { + User user; + try + { + user = users.Authenticate(messageBytes); + } + catch (EmptyPasswordNotAllowedException) + { + header.Status = NTStatus.STATUS_ACCOUNT_RESTRICTION; + return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); + } + + + if (user != null) + { + header.UID = state.AddConnectedUser(user.AccountName); + } + else if (users.EnableGuestLogin) + { + response.Action = SessionSetupAction.SetupGuest; + header.UID = state.AddConnectedUser("Guest"); + } + else + { + header.Status = NTStatus.STATUS_LOGON_FAILURE; + return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX); + } + } + response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" + response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" + + return response; + } + } +} diff --git a/SMBLibrary/Server/SMBServer.SMB1.cs b/SMBLibrary/Server/SMBServer.SMB1.cs index 9eb3add..8bb21c0 100644 --- a/SMBLibrary/Server/SMBServer.SMB1.cs +++ b/SMBLibrary/Server/SMBServer.SMB1.cs @@ -77,13 +77,13 @@ namespace SMBLibrary.Server { SessionSetupAndXRequest request = (SessionSetupAndXRequest)command; state.MaxBufferSize = request.MaxBufferSize; - return NegotiateHelper.GetSessionSetupResponse(header, request, m_users, state); + return SessionSetupHelper.GetSessionSetupResponse(header, request, m_users, state); } else if (command is SessionSetupAndXRequestExtended) { SessionSetupAndXRequestExtended request = (SessionSetupAndXRequestExtended)command; state.MaxBufferSize = request.MaxBufferSize; - return NegotiateHelper.GetSessionSetupResponseExtended(header, request, m_users, state); + return SessionSetupHelper.GetSessionSetupResponseExtended(header, request, m_users, state); } else if (command is EchoRequest) {