public void GetFileInformation(out FileInformation result, NtHandle handle, FileInformationClass informationClass) { if (m_client.InfoLevelPassthrough) { int maxOutputLength = 4096; Transaction2QueryFileInformationRequest subcommand = new Transaction2QueryFileInformationRequest { FID = ((Smb1Handle)handle).FID, FileInformationClass = informationClass }; Transaction2Request request = new Transaction2Request { Setup = subcommand.GetSetup(), TransParameters = subcommand.GetParameters(m_client.Unicode), TransData = subcommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2QueryFileInformationResponse.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); reply.IsSuccessElseThrow(); if (!(reply.Commands[0] is Transaction2Response transaction2Response)) { throw new NtStatusException(reply.Header.Status); } Transaction2QueryFileInformationResponse subcommandResponse = new Transaction2QueryFileInformationResponse(transaction2Response.TransParameters, transaction2Response.TransData); if (informationClass == FileInformationClass.FileAllInformation) { // Windows implementations return SMB_QUERY_FILE_ALL_INFO when a client specifies native NT passthrough level "FileAllInformation". QueryInformation queryFileAllInfo = subcommandResponse.GetQueryInformation(QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO); result = QueryInformationHelper.ToFileInformation(queryFileAllInfo); } else { result = subcommandResponse.GetFileInformation(informationClass); } reply.IsSuccessElseThrow(); return; } QueryInformationLevel informationLevel = QueryInformationHelper.ToFileInformationLevel(informationClass); GetFileInformation(out QueryInformation? queryInformation, handle, informationLevel); result = QueryInformationHelper.ToFileInformation(queryInformation); }
public void SetFileInformation(NtHandle handle, SetInformation information) { int maxOutputLength = 4096; Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest { FID = ((Smb1Handle)handle).FID, }; subcommand.SetInformation(information); Transaction2Request request = new Transaction2Request { Setup = subcommand.GetSetup(), TransParameters = subcommand.GetParameters(m_client.Unicode), TransData = subcommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2SetFileInformationResponse.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); reply.IsSuccessElseThrow(); }
public void Disconnect() { TreeDisconnectRequest request = new TreeDisconnectRequest(); TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TREE_DISCONNECT); reply.IsSuccessElseThrow(); }
public void CloseFile(NtHandle handle) { CloseRequest request = new CloseRequest { FID = ((Smb1Handle)handle).FID }; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_CLOSE); reply.IsSuccessElseThrow(); }
public void CreateFile(out NtHandle handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext?securityContext) { handle = null; fileStatus = FileStatus.FILE_DOES_NOT_EXIST; NTCreateAndXRequest request = new NTCreateAndXRequest { FileName = path, DesiredAccess = desiredAccess, ExtFileAttributes = ToExtendedFileAttributes(fileAttributes), ShareAccess = shareAccess, CreateDisposition = createDisposition, CreateOptions = createOptions, ImpersonationLevel = ImpersonationLevel.Impersonation }; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_NT_CREATE_ANDX); switch (reply.Commands[0]) { case NTCreateAndXResponse response: { handle = new Smb1Handle(response.FID); fileStatus = ToFileStatus(response.CreateDisposition); reply.IsSuccessElseThrow(); break; } case ErrorResponse _: reply.IsSuccessElseThrow(); break; default: throw new NtStatusException(NTStatus.STATUS_INVALID_SMB); } }
public void GetFileInformation(out QueryInformation result, NtHandle handle, QueryInformationLevel informationLevel) { int maxOutputLength = 4096; Transaction2QueryFileInformationRequest subcommand = new Transaction2QueryFileInformationRequest { FID = ((Smb1Handle)handle).FID, QueryInformationLevel = informationLevel }; Transaction2Request request = new Transaction2Request { Setup = subcommand.GetSetup(), TransParameters = subcommand.GetParameters(m_client.Unicode), TransData = subcommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2QueryFileInformationResponse.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); reply.IsSuccessElseThrow(); if (!(reply.Commands[0] is Transaction2Response)) { throw new NtStatusException(reply.Header.Status); } Transaction2Response response = (Transaction2Response)reply.Commands[0]; Transaction2QueryFileInformationResponse subcommandResponse = new Transaction2QueryFileInformationResponse(response.TransParameters, response.TransData); result = subcommandResponse.GetQueryInformation(informationLevel); reply.IsSuccessElseThrow(); }
private SMB1FileStore TreeConnect(string shareName, ServiceName serviceName) { if (!IsConnected || !m_isLoggedIn) { throw new InvalidOperationException("A login session must be successfully established before connecting to a share"); } TreeConnectAndXRequest request = new TreeConnectAndXRequest { Path = shareName, Service = serviceName }; SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_TREE_CONNECT_ANDX); reply.IsSuccessElseThrow(); return(new SMB1FileStore(this, reply.Header.TID)); }
public void SetFileInformation(NtHandle handle, FileInformation information) { if (!m_client.InfoLevelPassthrough) { throw new NotSupportedException("Server does not support InfoLevelPassthrough"); } if (information is FileRenameInformationType2 fileRenameInformationType2) { FileRenameInformationType1 informationType1 = new FileRenameInformationType1 { FileName = fileRenameInformationType2.FileName, ReplaceIfExists = fileRenameInformationType2.ReplaceIfExists, RootDirectory = (uint)fileRenameInformationType2.RootDirectory }; information = informationType1; } int maxOutputLength = 4096; Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest { FID = ((Smb1Handle)handle).FID, }; subcommand.SetInformation(information); Transaction2Request request = new Transaction2Request { Setup = subcommand.GetSetup(), TransParameters = subcommand.GetParameters(m_client.Unicode), TransData = subcommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2SetFileInformationResponse.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); reply.IsSuccessElseThrow(); }
public void WriteFile(out int numberOfBytesWritten, NtHandle handle, long offset, byte[] data) { numberOfBytesWritten = 0; WriteAndXRequest request = new WriteAndXRequest { FID = ((Smb1Handle)handle).FID, Offset = (ulong)offset, Data = data }; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_WRITE_ANDX); reply.IsSuccessElseThrow(); if (reply.Commands[0] is WriteAndXResponse response) { numberOfBytesWritten = (int)response.Count; } }
public void ReadFile(out byte[]?data, NtHandle handle, long offset, int maxCount) { data = null; ReadAndXRequest request = new ReadAndXRequest { FID = ((Smb1Handle)handle).FID, Offset = (ulong)offset, MaxCountLarge = (uint)maxCount }; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_READ_ANDX); reply.IsSuccessElseThrow(); if (reply.Commands[0] is ReadAndXResponse response) { data = response.Data; } }
public void Logoff() { if (!IsConnected) { throw new InvalidOperationException("A session must be successfully established before attempting logoff"); } if (!m_isLoggedIn) { throw new InvalidOperationException("A login session must be successfully established before attempting logoff"); } LogoffAndXRequest request = new LogoffAndXRequest(); SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_LOGOFF_ANDX); if (reply.Header.Status == NTStatus.STATUS_SUCCESS) { m_isLoggedIn = false; } reply.IsSuccessElseThrow(); }
public void Login(string domainName, string userName, string password, AuthenticationMethod authenticationMethod) { if (!IsConnected) { throw new InvalidOperationException("A connection must be successfully established before attempting login"); } Capabilities clientCapabilities = Capabilities.NTSMB | Capabilities.RpcRemoteApi | Capabilities.NTStatusCode | Capabilities.NTFind; if (m_unicode) { clientCapabilities |= Capabilities.Unicode; } if (m_largeFiles) { clientCapabilities |= Capabilities.LargeFiles; } if (m_largeRead) { clientCapabilities |= Capabilities.LargeRead; } if (m_serverChallenge != null) { SessionSetupAndXRequest request = new SessionSetupAndXRequest { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, AccountName = userName, PrimaryDomain = domainName }; byte[] clientChallenge = new byte[8]; new Random().NextBytes(clientChallenge); if (authenticationMethod == AuthenticationMethod.NtlmV1) { request.OEMPassword = NtlmCryptography.ComputeLMv1Response(m_serverChallenge, password); request.UnicodePassword = NtlmCryptography.ComputeNTLMv1Response(m_serverChallenge, password); } else if (authenticationMethod == AuthenticationMethod.NtlmV1ExtendedSessionSecurity) { // [MS-CIFS] CIFS does not support Extended Session Security because there is no mechanism in CIFS to negotiate Extended Session Security throw new ArgumentException("SMB Extended Security must be negotiated in order for NtlmV1 Extended Session Security to be used"); } else // NtlmV2 { // Note: NtlmV2 over non-extended security session setup is not supported under Windows Vista and later which will return STATUS_INVALID_PARAMETER. // https://msdn.microsoft.com/en-us/library/ee441701.aspx // https://msdn.microsoft.com/en-us/library/cc236700.aspx request.OEMPassword = NtlmCryptography.ComputeLMv2Response(m_serverChallenge, clientChallenge, password, userName, domainName); NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(DateTime.UtcNow, clientChallenge, AVPairUtils.GetAVPairSequence(domainName, Environment.MachineName)); byte[] temp = clientChallengeStructure.GetBytesPadded(); byte[] proofStr = NtlmCryptography.ComputeNTLMv2Proof(m_serverChallenge, temp, password, userName, domainName); request.UnicodePassword = ByteUtils.Concatenate(proofStr, temp); } SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); m_isLoggedIn = (reply.Header.Status == NTStatus.STATUS_SUCCESS); reply.IsSuccessElseThrow(); } else // m_securityBlob != null { byte[] negotiateMessage = NtlmAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod); SessionSetupAndXRequestExtended request = new SessionSetupAndXRequestExtended { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, SecurityBlob = negotiateMessage }; SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); if (reply.Header.Status != NTStatus.STATUS_MORE_PROCESSING_REQUIRED || !(reply.Commands[0] is SessionSetupAndXResponseExtended)) { throw new NtStatusException(reply.Header.Status); } SessionSetupAndXResponseExtended response = (SessionSetupAndXResponseExtended)reply.Commands[0]; byte[]? authenticateMessage = NtlmAuthenticationHelper.GetAuthenticateMessage(response.SecurityBlob, domainName, userName, password, authenticationMethod, out m_sessionKey); if (authenticateMessage == null) { throw new NtStatusException(NTStatus.SEC_E_INVALID_TOKEN); } m_userID = reply.Header.UID; request = new SessionSetupAndXRequestExtended { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, SecurityBlob = authenticateMessage }; SendMessage(request); reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); m_isLoggedIn = (reply.Header.Status == NTStatus.STATUS_SUCCESS); reply.IsSuccessElseThrow(); } }
public void QueryDirectory(out List <FindInformation>?result, string fileName, FindInformationLevel informationLevel) { result = null; int maxOutputLength = 4096; Transaction2FindFirst2Request subCommand = new Transaction2FindFirst2Request { SearchAttributes = SMBFileAttributes.Hidden | SMBFileAttributes.System | SMBFileAttributes.Directory, SearchCount = ushort.MaxValue, Flags = FindFlags.SMB_FIND_CLOSE_AT_EOS, InformationLevel = informationLevel, FileName = fileName }; Transaction2Request request = new Transaction2Request { Setup = subCommand.GetSetup(), TransParameters = subCommand.GetParameters(m_client.Unicode), TransData = subCommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2FindFirst2Response.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); reply.IsSuccessElseThrow(); if (!(reply.Commands[0] is Transaction2Response)) { throw new NtStatusException(reply.Header.Status); } result = new List <FindInformation>(); Transaction2Response response = (Transaction2Response)reply.Commands[0]; Transaction2FindFirst2Response subcommandResponse = new Transaction2FindFirst2Response(response.TransParameters, response.TransData); FindInformationList findInformationList = subcommandResponse.GetFindInformationList(subCommand.InformationLevel, reply.Header.UnicodeFlag); result.AddRange(findInformationList); bool endOfSearch = subcommandResponse.EndOfSearch; while (!endOfSearch) { Transaction2FindNext2Request nextSubCommand = new Transaction2FindNext2Request { SID = subcommandResponse.SID, SearchCount = ushort.MaxValue, Flags = FindFlags.SMB_FIND_CLOSE_AT_EOS | FindFlags.SMB_FIND_CONTINUE_FROM_LAST, InformationLevel = informationLevel, FileName = fileName }; request = new Transaction2Request { Setup = nextSubCommand.GetSetup(), TransParameters = nextSubCommand.GetParameters(m_client.Unicode), TransData = nextSubCommand.GetData(m_client.Unicode) }; request.TotalDataCount = (ushort)request.TransData.Length; request.TotalParameterCount = (ushort)request.TransParameters.Length; request.MaxParameterCount = Transaction2FindNext2Response.ParametersLength; request.MaxDataCount = (ushort)maxOutputLength; TrySendMessage(request); reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2); if (reply.Header.Status == NTStatus.STATUS_SUCCESS && reply.Commands[0] is Transaction2Response transaction2Response) { Transaction2FindNext2Response nextSubCommandResponse = new Transaction2FindNext2Response(transaction2Response.TransParameters, transaction2Response.TransData); findInformationList = nextSubCommandResponse.GetFindInformationList(subCommand.InformationLevel, reply.Header.UnicodeFlag); result.AddRange(findInformationList); endOfSearch = nextSubCommandResponse.EndOfSearch; } else { endOfSearch = true; } } reply.IsSuccessElseThrow(); }