From 966085c841aa3cfea0fa6f6148115ea0b3df83f4 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Sat, 30 Sep 2017 22:12:14 +0300 Subject: [PATCH] SMB1: Transaction2 subcommands: Added support for pass-through Information Levels --- SMBLibrary/Client/SMB1FileStore.cs | 4 +- .../Transaction2QueryFSInformationRequest.cs | 44 +++++++++++-- .../Transaction2QueryFSInformationResponse.cs | 29 ++++++-- ...Transaction2QueryFileInformationRequest.cs | 43 ++++++++++-- ...ransaction2QueryFileInformationResponse.cs | 29 ++++++-- ...Transaction2QueryPathInformationRequest.cs | 46 +++++++++++-- ...ransaction2QueryPathInformationResponse.cs | 30 ++++++--- .../Transaction2SetFSInformationRequest.cs | 30 +++++++++ .../Transaction2SetFileInformationRequest.cs | 51 ++++++++++++-- .../Transaction2SetPathInformationRequest.cs | 66 ++++++++++++++++--- .../SMB1/Transaction2SubcommandHelper.cs | 28 ++++---- 11 files changed, 332 insertions(+), 68 deletions(-) diff --git a/SMBLibrary/Client/SMB1FileStore.cs b/SMBLibrary/Client/SMB1FileStore.cs index b2bf869..9c52016 100644 --- a/SMBLibrary/Client/SMB1FileStore.cs +++ b/SMBLibrary/Client/SMB1FileStore.cs @@ -211,7 +211,7 @@ namespace SMBLibrary.Client int maxOutputLength = 4096; Transaction2QueryFileInformationRequest subcommand = new Transaction2QueryFileInformationRequest(); subcommand.FID = (ushort)handle; - subcommand.InformationLevel = informationLevel; + subcommand.QueryInformationLevel = informationLevel; Transaction2Request request = new Transaction2Request(); request.Setup = subcommand.GetSetup(); @@ -282,7 +282,7 @@ namespace SMBLibrary.Client result = null; int maxOutputLength = 4096; Transaction2QueryFSInformationRequest subcommand = new Transaction2QueryFSInformationRequest(); - subcommand.InformationLevel = informationLevel; + subcommand.QueryFSInformationLevel = informationLevel; Transaction2Request request = new Transaction2Request(); request.Setup = subcommand.GetSetup(); diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationRequest.cs index 598f4c9..5c58c21 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationRequest.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* 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, @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -16,9 +15,10 @@ namespace SMBLibrary.SMB1 /// public class Transaction2QueryFSInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; public const int ParametersLength = 2; - - public QueryFSInformationLevel InformationLevel; + // Parameters: + public ushort InformationLevel; public Transaction2QueryFSInformationRequest() : base() { @@ -27,7 +27,7 @@ namespace SMBLibrary.SMB1 public Transaction2QueryFSInformationRequest(byte[] parameters, byte[] data, bool isUnicode) : base() { - InformationLevel = (QueryFSInformationLevel)LittleEndianConverter.ToUInt16(parameters, 0); + InformationLevel = LittleEndianConverter.ToUInt16(parameters, 0); } public override byte[] GetSetup() @@ -38,10 +38,42 @@ namespace SMBLibrary.SMB1 public override byte[] GetParameters(bool isUnicode) { byte[] parameters = new byte[ParametersLength]; - LittleEndianWriter.WriteUInt16(parameters, 0, (ushort)InformationLevel); + LittleEndianWriter.WriteUInt16(parameters, 0, InformationLevel); return parameters; } + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public QueryFSInformationLevel QueryFSInformationLevel + { + get + { + return (QueryFSInformationLevel)InformationLevel; + } + set + { + InformationLevel = (ushort)value; + } + } + + public FileSystemInformationClass FileSystemInformationClass + { + get + { + return (FileSystemInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + public override Transaction2SubcommandName SubcommandName { get diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationResponse.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationResponse.cs index 1b199ef..509c2ee 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationResponse.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFSInformationResponse.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* 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, @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -18,7 +17,7 @@ namespace SMBLibrary.SMB1 { public const int ParametersLength = 0; // Data: - private byte[] QueryFSInformationBytes; + public byte[] InformationBytes; public Transaction2QueryFSInformationResponse() : base() { @@ -26,22 +25,38 @@ namespace SMBLibrary.SMB1 public Transaction2QueryFSInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base() { - QueryFSInformationBytes = data; + InformationBytes = data; } public override byte[] GetData(bool isUnicode) { - return QueryFSInformationBytes; + return InformationBytes; } public QueryFSInformation GetQueryFSInformation(QueryFSInformationLevel informationLevel, bool isUnicode) { - return QueryFSInformation.GetQueryFSInformation(QueryFSInformationBytes, informationLevel, isUnicode); + return QueryFSInformation.GetQueryFSInformation(InformationBytes, informationLevel, isUnicode); } public void SetQueryFSInformation(QueryFSInformation queryFSInformation, bool isUnicode) { - QueryFSInformationBytes = queryFSInformation.GetBytes(isUnicode); + InformationBytes = queryFSInformation.GetBytes(isUnicode); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public FileSystemInformation GetFileSystemInformation(FileSystemInformationClass informationClass) + { + return FileSystemInformation.GetFileSystemInformation(InformationBytes, 0, informationClass); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetFileSystemInformation(FileSystemInformation information) + { + InformationBytes = information.GetBytes(); } public override Transaction2SubcommandName SubcommandName diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationRequest.cs index 7e47d86..5cb3ec1 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationRequest.cs @@ -15,10 +15,11 @@ namespace SMBLibrary.SMB1 /// public class Transaction2QueryFileInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; public const int ParametersLength = 4; // Parameters: public ushort FID; - public QueryInformationLevel InformationLevel; + public ushort InformationLevel; // Data: public FullExtendedAttributeList GetExtendedAttributeList; // Used with QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST @@ -30,9 +31,9 @@ namespace SMBLibrary.SMB1 public Transaction2QueryFileInformationRequest(byte[] parameters, byte[] data, bool isUnicode) : base() { FID = LittleEndianConverter.ToUInt16(parameters, 0); - InformationLevel = (QueryInformationLevel)LittleEndianConverter.ToUInt16(parameters, 2); + InformationLevel = LittleEndianConverter.ToUInt16(parameters, 2); - if (InformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) + if (!IsPassthroughInformationLevel && QueryInformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) { GetExtendedAttributeList = new FullExtendedAttributeList(data, 0); } @@ -47,13 +48,13 @@ namespace SMBLibrary.SMB1 { byte[] parameters = new byte[ParametersLength]; LittleEndianWriter.WriteUInt16(parameters, 0, FID); - LittleEndianWriter.WriteUInt16(parameters, 2, (ushort)InformationLevel); + LittleEndianWriter.WriteUInt16(parameters, 2, InformationLevel); return parameters; } public override byte[] GetData(bool isUnicode) { - if (InformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) + if (!IsPassthroughInformationLevel && QueryInformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) { return GetExtendedAttributeList.GetBytes(); } @@ -63,6 +64,38 @@ namespace SMBLibrary.SMB1 } } + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public QueryInformationLevel QueryInformationLevel + { + get + { + return (QueryInformationLevel)InformationLevel; + } + set + { + InformationLevel = (ushort)value; + } + } + + public FileInformationClass FileInformationClass + { + get + { + return (FileInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + public override Transaction2SubcommandName SubcommandName { get diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationResponse.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationResponse.cs index 5578221..75b156b 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationResponse.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryFileInformationResponse.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* 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, @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -20,7 +19,7 @@ namespace SMBLibrary.SMB1 // Parameters: public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST // Data: - private byte[] QueryInformationBytes = new byte[0]; + public byte[] InformationBytes = new byte[0]; public Transaction2QueryFileInformationResponse() : base() { @@ -29,7 +28,7 @@ namespace SMBLibrary.SMB1 public Transaction2QueryFileInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base() { EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0); - QueryInformationBytes = data; + InformationBytes = data; } public override byte[] GetParameters(bool isUnicode) @@ -39,17 +38,33 @@ namespace SMBLibrary.SMB1 public override byte[] GetData(bool isUnicode) { - return QueryInformationBytes; + return InformationBytes; } public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel) { - return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel); + return QueryInformation.GetQueryInformation(InformationBytes, queryInformationLevel); } public void SetQueryInformation(QueryInformation queryInformation) { - QueryInformationBytes = queryInformation.GetBytes(); + InformationBytes = queryInformation.GetBytes(); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public FileInformation GetFileInformation(FileInformationClass informationClass) + { + return FileInformation.GetFileInformation(InformationBytes, 0, informationClass); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetFileInformation(FileInformation information) + { + InformationBytes = information.GetBytes(); } public override Transaction2SubcommandName SubcommandName diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationRequest.cs index a8c53f1..0eeb63d 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationRequest.cs @@ -15,8 +15,10 @@ namespace SMBLibrary.SMB1 /// public class Transaction2QueryPathInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; + public const int ParametersFixedLength = 6; // Parameters: - public QueryInformationLevel InformationLevel; + public ushort InformationLevel; public uint Reserved; public string FileName; // SMB_STRING // Data: @@ -29,11 +31,11 @@ namespace SMBLibrary.SMB1 public Transaction2QueryPathInformationRequest(byte[] parameters, byte[] data, bool isUnicode) : base() { - InformationLevel = (QueryInformationLevel)LittleEndianConverter.ToUInt16(parameters, 0); + InformationLevel = LittleEndianConverter.ToUInt16(parameters, 0); Reserved = LittleEndianConverter.ToUInt32(parameters, 4); FileName = SMB1Helper.ReadSMBString(parameters, 6, isUnicode); - if (InformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) + if (!IsPassthroughInformationLevel && QueryInformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) { GetExtendedAttributeList = new FullExtendedAttributeList(data, 0); } @@ -46,7 +48,7 @@ namespace SMBLibrary.SMB1 public override byte[] GetParameters(bool isUnicode) { - int length = 6; + int length = ParametersFixedLength; if (isUnicode) { length += FileName.Length * 2 + 2; @@ -56,7 +58,7 @@ namespace SMBLibrary.SMB1 length += FileName.Length + 1; } byte[] parameters = new byte[length]; - LittleEndianWriter.WriteUInt16(parameters, 0, (ushort)InformationLevel); + LittleEndianWriter.WriteUInt16(parameters, 0, InformationLevel); LittleEndianWriter.WriteUInt32(parameters, 2, Reserved); SMB1Helper.WriteSMBString(parameters, 6, isUnicode, FileName); return parameters; @@ -64,7 +66,7 @@ namespace SMBLibrary.SMB1 public override byte[] GetData(bool isUnicode) { - if (InformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) + if (!IsPassthroughInformationLevel && QueryInformationLevel == QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST) { return GetExtendedAttributeList.GetBytes(); } @@ -74,6 +76,38 @@ namespace SMBLibrary.SMB1 } } + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public QueryInformationLevel QueryInformationLevel + { + get + { + return (QueryInformationLevel)InformationLevel; + } + set + { + InformationLevel = (ushort)value; + } + } + + public FileInformationClass FileInformationClass + { + get + { + return (FileInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + public override Transaction2SubcommandName SubcommandName { get diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationResponse.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationResponse.cs index bd217c7..d87dfe2 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationResponse.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2QueryPathInformationResponse.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* 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, @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -19,17 +18,16 @@ namespace SMBLibrary.SMB1 // Parameters: public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST // Data: - private byte[] QueryInformationBytes; + public byte[] InformationBytes; public Transaction2QueryPathInformationResponse() : base() { - } public Transaction2QueryPathInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base() { EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0); - QueryInformationBytes = data; + InformationBytes = data; } public override byte[] GetParameters(bool isUnicode) @@ -39,17 +37,33 @@ namespace SMBLibrary.SMB1 public override byte[] GetData(bool isUnicode) { - return QueryInformationBytes; + return InformationBytes; } public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel) { - return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel); + return QueryInformation.GetQueryInformation(InformationBytes, queryInformationLevel); } public void SetQueryInformation(QueryInformation queryInformation) { - QueryInformationBytes = queryInformation.GetBytes(); + InformationBytes = queryInformation.GetBytes(); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public FileInformation GetFileInformation(FileInformationClass informationClass) + { + return FileInformation.GetFileInformation(InformationBytes, 0, informationClass); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetFileInformation(FileInformation information) + { + InformationBytes = information.GetBytes(); } public override Transaction2SubcommandName SubcommandName diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFSInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFSInformationRequest.cs index 60b4f5a..18d0552 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFSInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFSInformationRequest.cs @@ -15,6 +15,7 @@ namespace SMBLibrary.SMB1 /// public class Transaction2SetFSInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; public const int ParametersLength = 4; // Parameters: public ushort FID; @@ -52,6 +53,35 @@ namespace SMBLibrary.SMB1 return InformationBytes; } + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public FileSystemInformationClass FileSystemInformationClass + { + get + { + return (FileSystemInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetFileSystemInformation(FileSystemInformation information) + { + FileSystemInformationClass = information.FileSystemInformationClass; + InformationBytes = information.GetBytes(); + } + public override Transaction2SubcommandName SubcommandName { get diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFileInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFileInformationRequest.cs index 23f1c75..98e1e66 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFileInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetFileInformationRequest.cs @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -16,10 +15,11 @@ namespace SMBLibrary.SMB1 /// public class Transaction2SetFileInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; public const int ParametersLength = 6; // Parameters: public ushort FID; - public SetInformationLevel InformationLevel; + public ushort InformationLevel; public ushort Reserved; // Data: public byte[] InformationBytes; @@ -31,7 +31,7 @@ namespace SMBLibrary.SMB1 public Transaction2SetFileInformationRequest(byte[] parameters, byte[] data, bool isUnicode) : base() { FID = LittleEndianConverter.ToUInt16(parameters, 0); - InformationLevel = (SetInformationLevel)LittleEndianConverter.ToUInt16(parameters, 2); + InformationLevel = LittleEndianConverter.ToUInt16(parameters, 2); Reserved = LittleEndianConverter.ToUInt16(parameters, 4); InformationBytes = data; @@ -46,7 +46,7 @@ namespace SMBLibrary.SMB1 { byte[] parameters = new byte[ParametersLength]; LittleEndianWriter.WriteUInt16(parameters, 0, FID); - LittleEndianWriter.WriteUInt16(parameters, 2, (ushort)InformationLevel); + LittleEndianWriter.WriteUInt16(parameters, 2, InformationLevel); LittleEndianWriter.WriteUInt16(parameters, 4, Reserved); return parameters; } @@ -56,9 +56,50 @@ namespace SMBLibrary.SMB1 return InformationBytes; } + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public SetInformationLevel SetInformationLevel + { + get + { + return (SetInformationLevel)InformationLevel; + } + set + { + InformationLevel = (ushort)value; + } + } + + public FileInformationClass FileInformationClass + { + get + { + return (FileInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + public void SetInformation(SetInformation information) { - InformationLevel = information.InformationLevel; + SetInformationLevel = information.InformationLevel; + InformationBytes = information.GetBytes(); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetInformation(FileInformation information) + { + FileInformationClass = information.FileInformationClass; InformationBytes = information.GetBytes(); } diff --git a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetPathInformationRequest.cs b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetPathInformationRequest.cs index 85f8011..1fbae8a 100644 --- a/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetPathInformationRequest.cs +++ b/SMBLibrary/SMB1/Transaction2Subcommands/Transaction2SetPathInformationRequest.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* 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, @@ -6,7 +6,6 @@ */ using System; using System.Collections.Generic; -using System.Text; using Utilities; namespace SMBLibrary.SMB1 @@ -16,22 +15,26 @@ namespace SMBLibrary.SMB1 /// public class Transaction2SetPathInformationRequest : Transaction2Subcommand { + private const ushort SMB_INFO_PASSTHROUGH = 0x03E8; public const int ParametersFixedLength = 6; // Parameters: - public SetInformationLevel InformationLevel; + public ushort InformationLevel; public uint Reserved; public string FileName; // SMB_STRING // Data: - public SetInformation SetInfo; + public byte[] InformationBytes; public Transaction2SetPathInformationRequest() : base() - {} + { + } public Transaction2SetPathInformationRequest(byte[] parameters, byte[] data, bool isUnicode) : base() { - InformationLevel = (SetInformationLevel)LittleEndianConverter.ToUInt16(parameters, 0); + InformationLevel = LittleEndianConverter.ToUInt16(parameters, 0); Reserved = LittleEndianConverter.ToUInt32(parameters, 2); FileName = SMB1Helper.ReadSMBString(parameters, 6, isUnicode); + + InformationBytes = data; } public override byte[] GetSetup() @@ -52,7 +55,7 @@ namespace SMBLibrary.SMB1 } byte[] parameters = new byte[length]; - LittleEndianWriter.WriteUInt16(parameters, 0, (ushort)InformationLevel); + LittleEndianWriter.WriteUInt16(parameters, 0, InformationLevel); LittleEndianWriter.WriteUInt32(parameters, 2, Reserved); SMB1Helper.WriteSMBString(parameters, 6, isUnicode, FileName); return parameters; @@ -60,7 +63,54 @@ namespace SMBLibrary.SMB1 public override byte[] GetData(bool isUnicode) { - return SetInfo.GetBytes(); + return InformationBytes; + } + + public bool IsPassthroughInformationLevel + { + get + { + return (InformationLevel >= SMB_INFO_PASSTHROUGH); + } + } + + public SetInformationLevel SetInformationLevel + { + get + { + return (SetInformationLevel)InformationLevel; + } + set + { + InformationLevel = (ushort)value; + } + } + + public FileInformationClass FileInformationClass + { + get + { + return (FileInformationClass)(InformationLevel - SMB_INFO_PASSTHROUGH); + } + set + { + InformationLevel = (ushort)((ushort)value + SMB_INFO_PASSTHROUGH); + } + } + + public void SetInformation(SetInformation information) + { + SetInformationLevel = information.InformationLevel; + InformationBytes = information.GetBytes(); + } + + /// + /// Support for pass-through Information Levels must be enabled. + /// + public void SetInformation(FileInformation information) + { + FileInformationClass = information.FileInformationClass; + InformationBytes = information.GetBytes(); } public override Transaction2SubcommandName SubcommandName diff --git a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs index ea1d319..20d45a7 100644 --- a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs +++ b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs @@ -146,14 +146,14 @@ namespace SMBLibrary.Server.SMB1 Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse(); QueryFSInformation queryFSInformation; - NTStatus queryStatus = SMB1FileStoreHelper.GetFileSystemInformation(out queryFSInformation, share.FileStore, subcommand.InformationLevel); + NTStatus queryStatus = SMB1FileStoreHelper.GetFileSystemInformation(out queryFSInformation, share.FileStore, subcommand.QueryFSInformationLevel); if (queryStatus != NTStatus.STATUS_SUCCESS) { - state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information level: {1}, NTStatus: {2}", share.Name, subcommand.InformationLevel, queryStatus); + state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information level: {1}, NTStatus: {2}", share.Name, subcommand.QueryFSInformationLevel, queryStatus); header.Status = queryStatus; return null; } - state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information level: {1}", share.Name, subcommand.InformationLevel); + state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information level: {1}", share.Name, subcommand.QueryFSInformationLevel); response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag); return response; } @@ -179,14 +179,14 @@ namespace SMBLibrary.Server.SMB1 Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse(); QueryInformation queryInformation; - NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, path, subcommand.InformationLevel, session.SecurityContext); + NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, path, subcommand.QueryInformationLevel, session.SecurityContext); if (queryStatus != NTStatus.STATUS_SUCCESS) { - state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}", share.Name, path, subcommand.InformationLevel, queryStatus); + state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}", share.Name, path, subcommand.QueryInformationLevel, queryStatus); header.Status = queryStatus; return null; } - state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}", share.Name, path, subcommand.InformationLevel); + state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}", share.Name, path, subcommand.QueryInformationLevel); response.SetQueryInformation(queryInformation); return response; } @@ -214,14 +214,14 @@ namespace SMBLibrary.Server.SMB1 Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse(); QueryInformation queryInformation; - NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, openFile.Handle, subcommand.InformationLevel); + NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, openFile.Handle, subcommand.QueryInformationLevel); if (queryStatus != NTStatus.STATUS_SUCCESS) { - state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.InformationLevel, queryStatus, subcommand.FID); + state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.QueryInformationLevel, queryStatus, subcommand.FID); header.Status = queryStatus; return null; } - state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.InformationLevel, subcommand.FID); + state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.QueryInformationLevel, subcommand.FID); response.SetQueryInformation(queryInformation); return response; } @@ -250,17 +250,17 @@ namespace SMBLibrary.Server.SMB1 SetInformation information; try { - information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.InformationLevel); + information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.SetInformationLevel); } catch(UnsupportedInformationLevelException) { - state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.InformationLevel); + state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.SetInformationLevel); header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return null; } catch(Exception) { - state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.InformationLevel); + state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.SetInformationLevel); header.Status = NTStatus.STATUS_INVALID_PARAMETER; return null; } @@ -268,11 +268,11 @@ namespace SMBLibrary.Server.SMB1 NTStatus status = SMB1FileStoreHelper.SetFileInformation(share.FileStore, openFile.Handle, information); if (status != NTStatus.STATUS_SUCCESS) { - state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.InformationLevel, status, subcommand.FID); + state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.SetInformationLevel, status, subcommand.FID); header.Status = status; return null; } - state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.InformationLevel, subcommand.FID); + state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.SetInformationLevel, subcommand.FID); Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse(); return response; }