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); }
///////////////////////////////////////////////////////////////////////////// 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); }