ServerNameList.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using Org.BouncyCastle.Utilities;
  6. namespace Org.BouncyCastle.Crypto.Tls
  7. {
  8. public class ServerNameList
  9. {
  10. protected readonly IList mServerNameList;
  11. /**
  12. * @param serverNameList an {@link IList} of {@link ServerName}.
  13. */
  14. public ServerNameList(IList serverNameList)
  15. {
  16. if (serverNameList == null)
  17. throw new ArgumentNullException("serverNameList");
  18. this.mServerNameList = serverNameList;
  19. }
  20. /**
  21. * @return an {@link IList} of {@link ServerName}.
  22. */
  23. public virtual IList ServerNames
  24. {
  25. get { return mServerNameList; }
  26. }
  27. /**
  28. * Encode this {@link ServerNameList} to a {@link Stream}.
  29. *
  30. * @param output
  31. * the {@link Stream} to encode to.
  32. * @throws IOException
  33. */
  34. public virtual void Encode(Stream output)
  35. {
  36. MemoryStream buf = new MemoryStream();
  37. byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
  38. foreach (ServerName entry in ServerNames)
  39. {
  40. nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
  41. if (nameTypesSeen == null)
  42. throw new TlsFatalAlert(AlertDescription.internal_error);
  43. entry.Encode(buf);
  44. }
  45. TlsUtilities.CheckUint16(buf.Length);
  46. TlsUtilities.WriteUint16((int)buf.Length, output);
  47. buf.WriteTo(output);
  48. }
  49. /**
  50. * Parse a {@link ServerNameList} from a {@link Stream}.
  51. *
  52. * @param input
  53. * the {@link Stream} to parse from.
  54. * @return a {@link ServerNameList} object.
  55. * @throws IOException
  56. */
  57. public static ServerNameList Parse(Stream input)
  58. {
  59. int length = TlsUtilities.ReadUint16(input);
  60. if (length < 1)
  61. throw new TlsFatalAlert(AlertDescription.decode_error);
  62. byte[] data = TlsUtilities.ReadFully(length, input);
  63. MemoryStream buf = new MemoryStream(data, false);
  64. byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
  65. IList server_name_list = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  66. while (buf.Position < buf.Length)
  67. {
  68. ServerName entry = ServerName.Parse(buf);
  69. nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
  70. if (nameTypesSeen == null)
  71. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  72. server_name_list.Add(entry);
  73. }
  74. return new ServerNameList(server_name_list);
  75. }
  76. private static byte[] CheckNameType(byte[] nameTypesSeen, byte nameType)
  77. {
  78. /*
  79. * RFC 6066 3. The ServerNameList MUST NOT contain more than one name of the same
  80. * name_type.
  81. */
  82. if (!NameType.IsValid(nameType) || Arrays.Contains(nameTypesSeen, nameType))
  83. return null;
  84. return Arrays.Append(nameTypesSeen, nameType);
  85. }
  86. }
  87. }
  88. #endif