ソースを参照

Improved SMB_COM_SESSION_SETUP_ANDX request and response implementations

Tal Aloni 8 年 前
コミット
8997f4e0dc

+ 12 - 1
SMBLibrary/SMB1/Commands/SMB1Command.cs

@@ -258,7 +258,18 @@ namespace SMBLibrary.SMB1
                         }
                     }
                 case CommandName.SMB_COM_SESSION_SETUP_ANDX:
-                    return new SessionSetupAndXResponse(buffer, offset, isUnicode);
+                    if (wordCount * 2 == SessionSetupAndXResponse.ParametersLength)
+                    {
+                        return new SessionSetupAndXResponse(buffer, offset, isUnicode);
+                    }
+                    else if (wordCount * 2 == SessionSetupAndXResponseExtended.ParametersLength)
+                    {
+                        return new SessionSetupAndXResponseExtended(buffer, offset, isUnicode);
+                    }
+                    else
+                    {
+                        throw new InvalidRequestException(); ;
+                    }
                 case CommandName.SMB_COM_LOGOFF_ANDX:
                     return new LogoffAndXResponse(buffer, offset);
                 case CommandName.SMB_COM_TREE_CONNECT_ANDX:

+ 49 - 6
SMBLibrary/SMB1/Commands/SessionSetupAndXRequest.cs

@@ -22,8 +22,8 @@ namespace SMBLibrary.SMB1
         public ushort MaxMpxCount;
         public ushort VcNumber;
         public uint SessionKey;
-        //ushort OEMPasswordLength;
-        //ushort UnicodePasswordLength;
+        private ushort OEMPasswordLength;
+        private ushort UnicodePasswordLength;
         public uint Reserved;
         public ServerCapabilities Capabilities;
         // Data:
@@ -35,14 +35,18 @@ namespace SMBLibrary.SMB1
         public string NativeOS;      // SMB_STRING (this field WILL be aligned to start on a 2-byte boundary from the start of the SMB header)
         public string NativeLanMan;  // SMB_STRING (this field WILL be aligned to start on a 2-byte boundary from the start of the SMB header)
 
+        public SessionSetupAndXRequest(): base()
+        {
+        }
+
         public SessionSetupAndXRequest(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
         {
             MaxBufferSize = LittleEndianConverter.ToUInt16(this.SMBParameters, 4);
             MaxMpxCount = LittleEndianConverter.ToUInt16(this.SMBParameters, 6);
             VcNumber = LittleEndianConverter.ToUInt16(this.SMBParameters, 8);
             SessionKey = LittleEndianConverter.ToUInt32(this.SMBParameters, 10);
-            ushort OEMPasswordLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 14);
-            ushort UnicodePasswordLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 16);
+            OEMPasswordLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 14);
+            UnicodePasswordLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 16);
             Reserved = LittleEndianConverter.ToUInt32(this.SMBParameters, 18);
             Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(this.SMBParameters, 22);
 
@@ -52,8 +56,9 @@ namespace SMBLibrary.SMB1
             int dataOffset = OEMPasswordLength + UnicodePasswordLength;
             if (isUnicode)
             {
-                // wordCount is 1 byte
-                int padding = (1 + OEMPasswordLength + UnicodePasswordLength) % 2;
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                int padding = (OEMPasswordLength + UnicodePasswordLength + 1) % 2;
                 dataOffset += padding;
             }
             AccountName = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
@@ -62,6 +67,44 @@ namespace SMBLibrary.SMB1
             NativeLanMan = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
         }
 
+        public override byte[] GetBytes(bool isUnicode)
+        {
+            OEMPasswordLength = (ushort)OEMPassword.Length;
+            UnicodePasswordLength = (ushort)UnicodePassword.Length;
+            
+            this.SMBParameters = new byte[ParametersLength];
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 4, MaxBufferSize);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 6, MaxMpxCount);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 8, VcNumber);
+            LittleEndianWriter.WriteUInt32(this.SMBParameters, 10, SessionKey);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 14, OEMPasswordLength);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 16, UnicodePasswordLength);
+            LittleEndianWriter.WriteUInt32(this.SMBParameters, 18, Reserved);
+
+            int padding = 0;
+            if (isUnicode)
+            {
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                padding = (OEMPasswordLength + UnicodePasswordLength + 1) % 2;
+                this.SMBData = new byte[OEMPassword.Length + UnicodePassword.Length + padding + (AccountName.Length + 1) * 2 + (PrimaryDomain.Length + 1) * 2 + (NativeOS.Length + 1) * 2 + (NativeLanMan.Length + 1) * 2];
+            }
+            else
+            {
+                this.SMBData = new byte[OEMPassword.Length + UnicodePassword.Length + AccountName.Length + 1 + PrimaryDomain.Length + 1 + NativeOS.Length + 1 + NativeLanMan.Length + 1];
+            }
+            int offset = 0;
+            ByteWriter.WriteBytes(this.SMBData, ref offset, OEMPassword);
+            ByteWriter.WriteBytes(this.SMBData, ref offset, UnicodePassword);
+            offset += padding;
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, AccountName);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, PrimaryDomain);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, NativeOS);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, NativeLanMan);
+
+            return base.GetBytes(isUnicode);
+        }
+
         public override CommandName CommandName
         {
             get

+ 43 - 6
SMBLibrary/SMB1/Commands/SessionSetupAndXRequestExtended.cs

@@ -22,7 +22,7 @@ namespace SMBLibrary.SMB1
         public ushort MaxMpxCount;
         public ushort VcNumber;
         public uint SessionKey;
-        //ushort SecurityBlobLength;
+        private ushort SecurityBlobLength;
         public uint Reserved;
         public ServerCapabilities Capabilities;
         // Data:
@@ -30,30 +30,67 @@ namespace SMBLibrary.SMB1
         public string NativeOS;     // SMB_STRING (If Unicode, this field MUST be aligned to start on a 2-byte boundary from the start of the SMB header)
         public string NativeLanMan; // SMB_STRING (this field WILL be aligned to start on a 2-byte boundary from the start of the SMB header)
 
+        public SessionSetupAndXRequestExtended(): base()
+        {
+        }
+
         public SessionSetupAndXRequestExtended(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
         {
             MaxBufferSize = LittleEndianConverter.ToUInt16(this.SMBParameters, 4);
             MaxMpxCount = LittleEndianConverter.ToUInt16(this.SMBParameters, 6);
             VcNumber = LittleEndianConverter.ToUInt16(this.SMBParameters, 8);
             SessionKey = LittleEndianConverter.ToUInt32(this.SMBParameters, 10);
-            ushort securityBlobLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 14);
+            SecurityBlobLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 14);
             Reserved = LittleEndianConverter.ToUInt32(this.SMBParameters, 16);
             Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(this.SMBParameters, 20);
 
-            SecurityBlob = ByteReader.ReadBytes(this.SMBData, 0, securityBlobLength);
+            SecurityBlob = ByteReader.ReadBytes(this.SMBData, 0, SecurityBlobLength);
 
             int dataOffset = SecurityBlob.Length;
             if (isUnicode)
             {
-                // when a Unicode string is passed it MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
-                // Note: SMBData starts at an odd offset
-                int padding = (securityBlobLength + 1) % 2;
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                int padding = (SecurityBlobLength + 1) % 2;
                 dataOffset += padding;
             }
             NativeOS = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
             NativeLanMan = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
         }
 
+        public override byte[] GetBytes(bool isUnicode)
+        {
+            SecurityBlobLength = (ushort)SecurityBlob.Length;
+
+            this.SMBParameters = new byte[ParametersLength];
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 4, MaxBufferSize);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 6, MaxMpxCount);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 8, VcNumber);
+            LittleEndianWriter.WriteUInt32(this.SMBParameters, 10, SessionKey);
+            LittleEndianWriter.WriteUInt16(this.SMBParameters, 14, SecurityBlobLength);
+            LittleEndianWriter.WriteUInt32(this.SMBParameters, 16, Reserved);
+
+            int padding = 0;
+            if (isUnicode)
+            {
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                padding = (SecurityBlobLength + 1) % 2;
+                this.SMBData = new byte[SecurityBlob.Length + (NativeOS.Length + 1) * 2 + (NativeLanMan.Length  + 1) * 2];
+            }
+            else
+            {
+                this.SMBData = new byte[SecurityBlob.Length + NativeOS.Length + 1 + NativeLanMan.Length  + 1];
+            }
+            int offset = 0;
+            ByteWriter.WriteBytes(this.SMBData, ref offset, SecurityBlob);
+            offset += padding;
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, NativeOS);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, NativeLanMan);
+
+            return base.GetBytes(isUnicode);
+        }
+
         public override CommandName CommandName
         {
             get

+ 5 - 1
SMBLibrary/SMB1/Commands/SessionSetupAndXResponse.cs

@@ -35,6 +35,8 @@ namespace SMBLibrary.SMB1
             int dataOffset = 0;
             if (isUnicode)
             {
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
                 dataOffset++;
             }
             NativeOS = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
@@ -50,7 +52,9 @@ namespace SMBLibrary.SMB1
             int offset = 0;
             if (isUnicode)
             {
-                int padding = 1; // 1 byte padding for 2 byte alignment
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                int padding = 1;
                 this.SMBData = new byte[padding + NativeOS.Length * 2 + NativeLanMan.Length * 2 + PrimaryDomain.Length * 2 + 6];
                 offset = padding;
             }

+ 22 - 2
SMBLibrary/SMB1/Commands/SessionSetupAndXResponseExtended.cs

@@ -19,7 +19,7 @@ namespace SMBLibrary.SMB1
         //byte AndXReserved;
         //ushort AndXOffset;
         public SessionSetupAction Action;
-        //ushort SecurityBlobLength;
+        private ushort SecurityBlobLength;
         // Data:
         public byte[] SecurityBlob;
         public string NativeOS;     // SMB_STRING (If Unicode, this field MUST be aligned to start on a 2-byte boundary from the start of the SMB header)
@@ -32,6 +32,25 @@ namespace SMBLibrary.SMB1
             NativeLanMan = String.Empty;
         }
 
+        public SessionSetupAndXResponseExtended(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
+        {
+            Action = (SessionSetupAction)LittleEndianConverter.ToUInt16(this.SMBParameters, 4);
+            SecurityBlobLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 6);
+
+            SecurityBlob = ByteReader.ReadBytes(this.SMBData, 0, SecurityBlobLength);
+
+            int dataOffset = SecurityBlob.Length;
+            if (isUnicode)
+            {
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
+                int padding = (SecurityBlobLength + 1) % 2;
+                dataOffset += padding;
+            }
+            NativeOS = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
+            NativeLanMan = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, isUnicode);
+        }
+
         public override byte[] GetBytes(bool isUnicode)
         {
             ushort securityBlobLength = (ushort)SecurityBlob.Length;
@@ -43,7 +62,8 @@ namespace SMBLibrary.SMB1
             int padding = 0;
             if (isUnicode)
             {
-                // wordCount is 1 byte
+                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
+                // Note: SMBData starts at an odd offset.
                 padding = (1 + securityBlobLength) % 2;
                 this.SMBData = new byte[SecurityBlob.Length + padding + NativeOS.Length * 2 + NativeLanMan.Length * 2 + 4];
             }