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