Example #1
0
        private static byte[] MakeTicketIntoBinaryBlob(FormsAuthenticationTicket ticket)
        {
            if (((ticket.Name == null) || (ticket.UserData == null)) || (ticket.CookiePath == null))
            {
                return(null);
            }
            if (!AppSettings.UseLegacyFormsAuthenticationTicketCompatibility)
            {
                return(FormsAuthenticationTicketSerializer.Serialize(ticket));
            }
            byte[] dst    = new byte[0x1000];
            byte[] pBytes = new byte[4];
            long[] pDates = new long[2];
            if (((_Protection != FormsProtectionEnum.All) && (_Protection != FormsProtectionEnum.Encryption)) || (MachineKeySection.CompatMode == MachineKeyCompatibilityMode.Framework20SP1))
            {
                byte[] data = new byte[8];
                new RNGCryptoServiceProvider().GetBytes(data);
                Buffer.BlockCopy(data, 0, dst, 0, 8);
            }
            pBytes[0] = (byte)ticket.Version;
            pBytes[1] = ticket.IsPersistent ? ((byte)1) : ((byte)0);
            pDates[0] = ticket.IssueDate.ToFileTime();
            pDates[1] = ticket.Expiration.ToFileTime();
            int count = System.Web.UnsafeNativeMethods.CookieAuthConstructTicket(dst, dst.Length, ticket.Name, ticket.UserData, ticket.CookiePath, pBytes, pDates);

            if (count < 0)
            {
                return(null);
            }
            byte[] buffer4 = new byte[count];
            Buffer.BlockCopy(dst, 0, buffer4, 0, count);
            return(buffer4);
        }
Example #2
0
        /////////////////////////////////////////////////////////////////////////////
        private static byte[] MakeTicketIntoBinaryBlob(FormsAuthenticationTicket ticket)
        {
            // None of the modes (Framework20 / Framework40 / beyond) support null values for these fields;
            // they always eventually just returned a null value.
            if (ticket.Name == null || ticket.UserData == null || ticket.CookiePath == null)
            {
                return(null);
            }

            // ** MSRC 11838 **
            // Framework20 / Framework40 ticket generation modes are insecure. We should use a
            // secure serialization mode by default.
            if (!AppSettings.UseLegacyFormsAuthenticationTicketCompatibility)
            {
                return(FormsAuthenticationTicketSerializer.Serialize(ticket));
            }

            // ** MSRC 11838 **
            // If we have reached this point of execution, the developer has explicitly elected
            // to continue using the insecure code path instead of the secure one. We removed
            // the Framework40 serialization mode, so everybody using the legacy code path is
            // forced to Framework20.

            byte [] bData  = new byte[4096];
            byte [] pBin   = new byte[4];
            long [] pDates = new long[2];
            byte [] pNull  = { 0, 0, 0 };

            // DevDiv Bugs 137864: 8 bytes may not be enough random bits as the length should be equal to the
            // key size. In CompatMode > Framework20SP1, use the IVType.Random feature instead of these 8 bytes,
            // but still include empty 8 bytes for compat with webengine.dll, where CookieAuthConstructTicket is.
            // Note that even in CompatMode = Framework20SP2 we fill 8 bytes with random data if the ticket
            // is not going to be encrypted.

            bool willEncrypt   = (_Protection == FormsProtectionEnum.All || _Protection == FormsProtectionEnum.Encryption);
            bool legacyPadding = !willEncrypt || (MachineKeySection.CompatMode == MachineKeyCompatibilityMode.Framework20SP1);

            if (legacyPadding)
            {
                // Fill the first 8 bytes of the blob with random bits
                byte[] bRandom = new byte[8];
                RNGCryptoServiceProvider randgen = new RNGCryptoServiceProvider();
                randgen.GetBytes(bRandom);
                Buffer.BlockCopy(bRandom, 0, bData, 0, 8);
            }
            else
            {
                // use blank 8 bytes for compatibility with CookieAuthConstructTicket (do nothing)
            }

            pBin[0] = (byte)ticket.Version;
            pBin[1] = (byte)(ticket.IsPersistent ? 1 : 0);

            pDates[0] = ticket.IssueDate.ToFileTime();
            pDates[1] = ticket.Expiration.ToFileTime();

            int iRet = UnsafeNativeMethods.CookieAuthConstructTicket(
                bData, bData.Length,
                ticket.Name, ticket.UserData, ticket.CookiePath,
                pBin, pDates);

            if (iRet < 0)
            {
                return(null);
            }

            byte[] ciphertext = new byte[iRet];
            Buffer.BlockCopy(bData, 0, ciphertext, 0, iRet);
            return(ciphertext);
        }
Example #3
0
        /////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////
        // Decrypt and get the auth ticket

        /// <devdoc>
        ///    <para>Given an encrypted authenitcation ticket as
        ///       obtained from an HTTP cookie, this method returns an instance of a
        ///       FormsAuthenticationTicket class.</para>
        /// </devdoc>
        public static FormsAuthenticationTicket Decrypt(string encryptedTicket)
        {
            if (String.IsNullOrEmpty(encryptedTicket) || encryptedTicket.Length > MAX_TICKET_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "encryptedTicket"));
            }

            Initialize();
            byte[] bBlob = null;
            if ((encryptedTicket.Length % 2) == 0)   // Could be a hex string
            {
                try {
                    bBlob = CryptoUtil.HexToBinary(encryptedTicket);
                } catch { }
            }
            if (bBlob == null)
            {
                bBlob = HttpServerUtility.UrlTokenDecode(encryptedTicket);
            }
            if (bBlob == null || bBlob.Length < 1)
            {
                throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "encryptedTicket"));
            }

            int ticketLength;

            if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider)
            {
                // If new crypto routines are enabled, call them instead.
                ICryptoService cryptoService   = AspNetCryptoServiceProvider.Instance.GetCryptoService(Purpose.FormsAuthentication_Ticket);
                byte[]         unprotectedData = cryptoService.Unprotect(bBlob);
                ticketLength = unprotectedData.Length;
                bBlob        = unprotectedData;
            }
            else
            {
#pragma warning disable 618 // calling obsolete methods
                // Otherwise call into MachineKeySection routines.

                if (_Protection == FormsProtectionEnum.All || _Protection == FormsProtectionEnum.Encryption)
                {
                    // DevDiv Bugs 137864: Include a random IV if under the right compat mode
                    // for improved encryption semantics
                    bBlob = MachineKeySection.EncryptOrDecryptData(false, bBlob, null, 0, bBlob.Length, false, false, IVType.Random);
                    if (bBlob == null)
                    {
                        return(null);
                    }
                }

                ticketLength = bBlob.Length;

                if (_Protection == FormsProtectionEnum.All || _Protection == FormsProtectionEnum.Validation)
                {
                    if (!MachineKeySection.VerifyHashedData(bBlob))
                    {
                        return(null);
                    }
                    ticketLength -= MachineKeySection.HashSize;
                }
#pragma warning restore 618 // calling obsolete methods
            }

            //////////////////////////////////////////////////////////////////////
            // Step 4: Change binary ticket to managed struct

            // ** MSRC 11838 **
            // Framework20 / Framework40 ticket generation modes are insecure. We should use a
            // secure serialization mode by default.
            if (!AppSettings.UseLegacyFormsAuthenticationTicketCompatibility)
            {
                return(FormsAuthenticationTicketSerializer.Deserialize(bBlob, ticketLength));
            }

            // ** MSRC 11838 **
            // If we have reached this point of execution, the developer has explicitly elected
            // to continue using the insecure code path instead of the secure one. We removed
            // the Framework40 serialization mode, so everybody using the legacy code path is
            // forced to Framework20.

            int           iSize  = ((ticketLength > MAX_TICKET_LENGTH) ? MAX_TICKET_LENGTH : ticketLength);
            StringBuilder name   = new StringBuilder(iSize);
            StringBuilder data   = new StringBuilder(iSize);
            StringBuilder path   = new StringBuilder(iSize);
            byte []       pBin   = new byte[4];
            long []       pDates = new long[2];

            int iRet = UnsafeNativeMethods.CookieAuthParseTicket(bBlob, ticketLength,
                                                                 name, iSize,
                                                                 data, iSize,
                                                                 path, iSize,
                                                                 pBin, pDates);

            if (iRet != 0)
            {
                return(null);
            }

            DateTime dt1 = DateTime.FromFileTime(pDates[0]);
            DateTime dt2 = DateTime.FromFileTime(pDates[1]);

            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket((int)pBin[0],
                                                                             name.ToString(),
                                                                             dt1,
                                                                             dt2,
                                                                             (bool)(pBin[1] != 0),
                                                                             data.ToString(),
                                                                             path.ToString());
            return(ticket);
        }
Example #4
0
        public static FormsAuthenticationTicket Decrypt(string encryptedTicket)
        {
            if (string.IsNullOrEmpty(encryptedTicket) || (encryptedTicket.Length > 0x1000))
            {
                throw new ArgumentException(System.Web.SR.GetString("InvalidArgumentValue", new object[] { "encryptedTicket" }));
            }
            Initialize();
            byte[] buf = null;
            if ((encryptedTicket.Length % 2) == 0)
            {
                try
                {
                    buf = MachineKeySection.HexStringToByteArray(encryptedTicket);
                }
                catch
                {
                }
            }
            if (buf == null)
            {
                buf = HttpServerUtility.UrlTokenDecode(encryptedTicket);
            }
            if ((buf == null) || (buf.Length < 1))
            {
                throw new ArgumentException(System.Web.SR.GetString("InvalidArgumentValue", new object[] { "encryptedTicket" }));
            }
            if ((_Protection == FormsProtectionEnum.All) || (_Protection == FormsProtectionEnum.Encryption))
            {
                buf = MachineKeySection.EncryptOrDecryptData(false, buf, null, 0, buf.Length, false, false, IVType.Random);
                if (buf == null)
                {
                    return(null);
                }
            }
            int length = buf.Length;

            if ((_Protection == FormsProtectionEnum.All) || (_Protection == FormsProtectionEnum.Validation))
            {
                if (!MachineKeySection.VerifyHashedData(buf))
                {
                    return(null);
                }
                length -= MachineKeySection.HashSize;
            }
            if (!AppSettings.UseLegacyFormsAuthenticationTicketCompatibility)
            {
                return(FormsAuthenticationTicketSerializer.Deserialize(buf, length));
            }
            int           capacity = (length > 0x1000) ? 0x1000 : length;
            StringBuilder szName   = new StringBuilder(capacity);
            StringBuilder szData   = new StringBuilder(capacity);
            StringBuilder szPath   = new StringBuilder(capacity);

            byte[] pBytes = new byte[4];
            long[] pDates = new long[2];
            if (System.Web.UnsafeNativeMethods.CookieAuthParseTicket(buf, length, szName, capacity, szData, capacity, szPath, capacity, pBytes, pDates) != 0)
            {
                return(null);
            }
            DateTime issueDate = DateTime.FromFileTime(pDates[0]);

            return(new FormsAuthenticationTicket(pBytes[0], szName.ToString(), issueDate, DateTime.FromFileTime(pDates[1]), pBytes[1] != 0, szData.ToString(), szPath.ToString()));
        }