2005-07-25 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Mon, 25 Jul 2005 08:42:40 +0000 (08:42 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Mon, 25 Jul 2005 08:42:40 +0000 (08:42 -0000)
* FormsAuthentication.cs: my previous patch missed a "small" detail: it
didn't include the verification key when computing/checking the
validation hash. Now this is really a MAC or HMAC or...

svn path=/trunk/mcs/; revision=47632

mcs/class/System.Web/System.Web.Security/ChangeLog
mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs

index a7badb0c12e8415d8a042a0f7445e67da22733dd..998dcdcc696e7d963182bf32c598589b2073d25f 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-25 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * FormsAuthentication.cs: my previous patch missed a "small" detail: it
+       didn't include the verification key when computing/checking the
+       validation hash. Now this is really a MAC or HMAC or...
+
 2005-07-25 Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * FormsAuthentication.cs:
index 60558c30e97887a5fdd76ef17984ccf4cca1a572..9bbe172d35b5efe1f8afa72cbb64264c9c9bb10e 100644 (file)
@@ -104,44 +104,50 @@ namespace System.Web.Security
                        MachineKeyConfig config = HttpContext.GetAppConfig ("system.web/machineKey") as MachineKeyConfig;
                        bool all = (protection == FormsProtectionEnum.All);
 
-                       byte [] unencrypted = bytes;
+                       byte [] result = bytes;
                        if (all || protection == FormsProtectionEnum.Encryption) {
                                ICryptoTransform decryptor;
                                decryptor = new TripleDESCryptoServiceProvider().CreateDecryptor (config.DecryptionKey192Bits, init_vector);
-                               unencrypted = decryptor.TransformFinalBlock (bytes, 0, bytes.Length);
+                               result = decryptor.TransformFinalBlock (bytes, 0, bytes.Length);
                                bytes = null;
                        }
 
                        if (all || protection == FormsProtectionEnum.Validation) {
-                               byte [] hash = null;
-                               int offset = 0, count = 0;
+                               int count;
+
+                               if (config.ValidationType == MachineKeyValidation.MD5)
+                                       count = MD5_hash_size;
+                               else
+                                       count = SHA1_hash_size; // 3DES and SHA1
+
+                               byte [] vk = config.ValidationKey;
+                               byte [] mix = new byte [result.Length - count + vk.Length];
+                               Buffer.BlockCopy (result, 0, mix, 0, result.Length - count);
+                               Buffer.BlockCopy (vk, 0, mix, result.Length - count, vk.Length);
 
+                               byte [] hash = null;
                                switch (config.ValidationType) {
                                case MachineKeyValidation.MD5:
-                                       count = MD5_hash_size;
-                                       offset = unencrypted.Length - count;
-                                       hash = MD5.Create ().ComputeHash (unencrypted, 0, unencrypted.Length - count);
+                                       hash = MD5.Create ().ComputeHash (mix);
                                        break;
                                // From MS docs: "When 3DES is specified, forms authentication defaults to SHA1"
                                case MachineKeyValidation.TripleDES:
                                case MachineKeyValidation.SHA1:
-                                       count = SHA1_hash_size;
-                                       offset = unencrypted.Length - count;
-                                       hash = SHA1.Create ().ComputeHash (unencrypted, 0, unencrypted.Length - count);
+                                       hash = SHA1.Create ().ComputeHash (mix);
                                        break;
                                }
 
-                               if (unencrypted.Length < count)
+                               if (result.Length < count)
                                        throw new ArgumentException ("Error validating ticket (length).", "encryptedTicket");
 
                                int i, k;
-                               for (i = offset, k = 0; k < count; i++, k++) {
-                                       if (unencrypted [i] != hash [k])
+                               for (i = result.Length - count, k = 0; k < count; i++, k++) {
+                                       if (result [i] != hash [k])
                                                throw new ArgumentException ("Error validating ticket.", "encryptedTicket");
                                }
                        }
 
-                       return FormsAuthenticationTicket.FromByteArray (unencrypted);
+                       return FormsAuthenticationTicket.FromByteArray (result);
                }
 
                public static FormsAuthenticationTicket Decrypt (string encryptedTicket)
@@ -172,36 +178,41 @@ namespace System.Web.Security
                        if (protection == FormsProtectionEnum.None)
                                return GetHexString (ticket_bytes);
 
-                       byte [] all_bytes = ticket_bytes;
+                       byte [] result = ticket_bytes;
                        MachineKeyConfig config = HttpContext.GetAppConfig ("system.web/machineKey") as MachineKeyConfig;
                        bool all = (protection == FormsProtectionEnum.All);
                        if (all || protection == FormsProtectionEnum.Validation) {
                                byte [] valid_bytes = null;
+                               byte [] vk = config.ValidationKey;
+                               byte [] mix = new byte [ticket_bytes.Length + vk.Length];
+                               Buffer.BlockCopy (ticket_bytes, 0, mix, 0, ticket_bytes.Length);
+                               Buffer.BlockCopy (vk, 0, mix, result.Length, vk.Length);
+
                                switch (config.ValidationType) {
                                case MachineKeyValidation.MD5:
-                                       valid_bytes = MD5.Create ().ComputeHash (ticket_bytes);
+                                       valid_bytes = MD5.Create ().ComputeHash (mix);
                                        break;
                                // From MS docs: "When 3DES is specified, forms authentication defaults to SHA1"
                                case MachineKeyValidation.TripleDES:
                                case MachineKeyValidation.SHA1:
-                                       valid_bytes = SHA1.Create ().ComputeHash (ticket_bytes);
+                                       valid_bytes = SHA1.Create ().ComputeHash (mix);
                                        break;
                                }
 
                                int tlen = ticket_bytes.Length;
                                int vlen = valid_bytes.Length;
-                               all_bytes = new byte [tlen + vlen];
-                               Buffer.BlockCopy (ticket_bytes, 0, all_bytes, 0, tlen);
-                               Buffer.BlockCopy (valid_bytes, 0, all_bytes, tlen, vlen);
+                               result = new byte [tlen + vlen];
+                               Buffer.BlockCopy (ticket_bytes, 0, result, 0, tlen);
+                               Buffer.BlockCopy (valid_bytes, 0, result, tlen, vlen);
                        }
 
                        if (all || protection == FormsProtectionEnum.Encryption) {
                                ICryptoTransform encryptor;
                                encryptor = new TripleDESCryptoServiceProvider().CreateEncryptor (config.DecryptionKey192Bits, init_vector);
-                               all_bytes = encryptor.TransformFinalBlock (all_bytes, 0, all_bytes.Length);
+                               result = encryptor.TransformFinalBlock (result, 0, result.Length);
                        }
 
-                       return GetHexString (all_bytes);
+                       return GetHexString (result);
                }
 
                public static HttpCookie GetAuthCookie (string userName, bool createPersistentCookie)