瀏覽代碼

SPNEGO: Added MechanismListMIC to negTokenInit and negTokenResp structures

Tal Aloni 8 年之前
父節點
當前提交
3b4c50c190

+ 39 - 5
SMBLibrary/Authentication/GSSAPI/SimpleProtectedNegotiationTokenInit.cs

@@ -14,9 +14,9 @@ namespace SMBLibrary.Authentication
     public class TokenInitEntry
     {
         public List<byte[]> MechanismTypeList = new List<byte[]>(); // Optional
-        // reqFlags - Optional, Unused
+        // reqFlags - Optional, RECOMMENDED to be left out
         public byte[] MechanismToken = new byte[0]; // Optional
-        // mechListMIC - Optional, Unused
+        public byte[] MechanismListMIC; // Optional
     }
 
     /// <summary>
@@ -58,13 +58,21 @@ namespace SMBLibrary.Authentication
                     {
                         entry.MechanismTypeList = ReadMechanismTypeList(buffer, ref offset);
                     }
+                    else if (tag == RequiredFlagsTag)
+                    {
+                        throw new NotImplementedException("negTokenInit.ReqFlags is not implemented");
+                    }
                     else if (tag == MechanismTokenTag)
                     {
                         entry.MechanismToken = ReadMechanismToken(buffer, ref offset);
                     }
+                    else if (tag == MechanismListMICTag)
+                    {
+                        entry.MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
+                    }
                     else
                     {
-                        throw new InvalidDataException();
+                        throw new InvalidDataException("Invalid negTokenInit structure");
                     }
                 }
                 Tokens.Add(entry);
@@ -96,7 +104,11 @@ namespace SMBLibrary.Authentication
                 }
                 if (token.MechanismToken != null)
                 {
-                    WriteMechanismToken(buffer, ref offset, token.MechanismToken);   
+                    WriteMechanismToken(buffer, ref offset, token.MechanismToken);
+                }
+                if (token.MechanismListMIC != null)
+                {
+                    WriteMechanismListMIC(buffer, ref offset, token.MechanismListMIC);
                 }
             }
             return buffer;
@@ -161,6 +173,18 @@ namespace SMBLibrary.Authentication
             return token;
         }
 
+        private static byte[] ReadMechanismListMIC(byte[] buffer, ref int offset)
+        {
+            int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
+            byte tag = ByteReader.ReadByte(buffer, ref offset);
+            if (tag != (byte)DerEncodingTag.ByteArray)
+            {
+                throw new InvalidDataException();
+            }
+            int length = DerEncodingHelper.ReadLength(buffer, ref offset);
+            return ByteReader.ReadBytes(buffer, ref offset, length);
+        }
+
         private static int GetSequenceLength(List<byte[]> mechanismTypeList)
         {
             int sequenceLength = 0;
@@ -199,6 +223,16 @@ namespace SMBLibrary.Authentication
             ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
             DerEncodingHelper.WriteLength(buffer, ref offset, mechanismToken.Length);
             ByteWriter.WriteBytes(buffer, ref offset, mechanismToken);
-        }   
+        }
+
+        private static void WriteMechanismListMIC(byte[] buffer, ref int offset, byte[] mechanismListMIC)
+        {
+            int mechanismListMICLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismListMIC.Length);
+            ByteWriter.WriteByte(buffer, ref offset, MechanismListMICTag);
+            DerEncodingHelper.WriteLength(buffer, ref offset, 1 + mechanismListMICLengthFieldSize + mechanismListMIC.Length);
+            ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
+            DerEncodingHelper.WriteLength(buffer, ref offset, mechanismListMIC.Length);
+            ByteWriter.WriteBytes(buffer, ref offset, mechanismListMIC);
+        }
     }
 }

+ 33 - 3
SMBLibrary/Authentication/GSSAPI/SimpleProtectedNegotiationTokenResponse.cs

@@ -24,11 +24,11 @@ namespace SMBLibrary.Authentication
         public NegState? NegState; // Optional
         public byte[] SupportedMechanism; // Optional
         public byte[] ResponseToken; // Optional
-        // mechListMIC - Optional, Unused
+        public byte[] MechanismListMIC; // Optional
     }
 
     /// <summary>
-    /// RFC 4178 - negTokenInit
+    /// RFC 4178 - negTokenResp
     /// </summary>
     public class SimpleProtectedNegotiationTokenResponse : SimpleProtectedNegotiationToken
     {
@@ -78,9 +78,13 @@ namespace SMBLibrary.Authentication
                     {
                         entry.ResponseToken = ReadResponseToken(buffer, ref offset);
                     }
+                    else if (tag == MechanismListMICTag)
+                    {
+                        entry.MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
+                    }
                     else
                     {
-                        throw new InvalidDataException();
+                        throw new InvalidDataException("Invalid negTokenResp structure");
                     }
                 }
                 Tokens.Add(entry);
@@ -118,6 +122,10 @@ namespace SMBLibrary.Authentication
                 {
                     WriteResponseToken(buffer, ref offset, token.ResponseToken);
                 }
+                if (token.MechanismListMIC != null)
+                {
+                    WriteMechanismListMIC(buffer, ref offset, token.MechanismListMIC);
+                }
             }
             return buffer;
         }
@@ -158,6 +166,18 @@ namespace SMBLibrary.Authentication
             return ByteReader.ReadBytes(buffer, ref offset, length);
         }
 
+        private static byte[] ReadMechanismListMIC(byte[] buffer, ref int offset)
+        {
+            int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
+            byte tag = ByteReader.ReadByte(buffer, ref offset);
+            if (tag != (byte)DerEncodingTag.ByteArray)
+            {
+                throw new InvalidDataException();
+            }
+            int length = DerEncodingHelper.ReadLength(buffer, ref offset);
+            return ByteReader.ReadBytes(buffer, ref offset, length);
+        }
+
         private static int GetEntryLength(TokenResponseEntry token)
         {
             int result = 0;
@@ -211,5 +231,15 @@ namespace SMBLibrary.Authentication
             DerEncodingHelper.WriteLength(buffer, ref offset, responseToken.Length);
             ByteWriter.WriteBytes(buffer, ref offset, responseToken);
         }
+
+        private static void WriteMechanismListMIC(byte[] buffer, ref int offset, byte[] mechanismListMIC)
+        {
+            int mechanismListMICLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismListMIC.Length);
+            ByteWriter.WriteByte(buffer, ref offset, MechanismListMICTag);
+            DerEncodingHelper.WriteLength(buffer, ref offset, 1 + mechanismListMICLengthFieldSize + mechanismListMIC.Length);
+            ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
+            DerEncodingHelper.WriteLength(buffer, ref offset, mechanismListMIC.Length);
+            ByteWriter.WriteBytes(buffer, ref offset, mechanismListMIC);
+        }
     }
 }