summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2016-03-10 13:44:13 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2016-03-10 13:44:13 +0700
commit605ef991b309a87a2ec590625ba449081c806274 (patch)
tree1a71adb56fdc734a0837b3d52aea53712004fb78
parentBMA-147 Support ECDH_anon key exchange in (D)TLS (diff)
downloadBouncyCastle.NET-ed25519-605ef991b309a87a2ec590625ba449081c806274.tar.xz
Implement unique name_type restriction from RFC 6066
-rw-r--r--crypto/src/crypto/tls/NameType.cs5
-rw-r--r--crypto/src/crypto/tls/ServerNameList.cs27
2 files changed, 30 insertions, 2 deletions
diff --git a/crypto/src/crypto/tls/NameType.cs b/crypto/src/crypto/tls/NameType.cs
index 25f6046fc..782164215 100644
--- a/crypto/src/crypto/tls/NameType.cs
+++ b/crypto/src/crypto/tls/NameType.cs
@@ -8,5 +8,10 @@ namespace Org.BouncyCastle.Crypto.Tls
          * RFC 3546 3.1.
          */
         public const byte host_name = 0;
+
+        public static bool IsValid(byte nameType)
+        {
+            return nameType == host_name;
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/ServerNameList.cs b/crypto/src/crypto/tls/ServerNameList.cs
index 13da79bf6..5b5b90e58 100644
--- a/crypto/src/crypto/tls/ServerNameList.cs
+++ b/crypto/src/crypto/tls/ServerNameList.cs
@@ -15,8 +15,8 @@ namespace Org.BouncyCastle.Crypto.Tls
          */
         public ServerNameList(IList serverNameList)
         {
-            if (serverNameList == null || serverNameList.Count < 1)
-                throw new ArgumentException("must not be null or empty", "serverNameList");
+            if (serverNameList == null)
+                throw new ArgumentNullException("serverNameList");
 
             this.mServerNameList = serverNameList;
         }
@@ -40,8 +40,13 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             MemoryStream buf = new MemoryStream();
 
+            byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
             foreach (ServerName entry in ServerNames)
             {
+                nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
+                if (nameTypesSeen == null)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+
                 entry.Encode(buf);
             }
 
@@ -68,14 +73,32 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             MemoryStream buf = new MemoryStream(data, false);
 
+            byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
             IList server_name_list = Platform.CreateArrayList();
             while (buf.Position < buf.Length)
             {
                 ServerName entry = ServerName.Parse(buf);
+
+                nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
+                if (nameTypesSeen == null)
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
                 server_name_list.Add(entry);
             }
 
             return new ServerNameList(server_name_list);
         }
+
+        private static byte[] CheckNameType(byte[] nameTypesSeen, byte nameType)
+        {
+            /*
+             * RFC 6066 3. The ServerNameList MUST NOT contain more than one name of the same
+             * name_type.
+             */
+            if (!NameType.IsValid(nameType) || Arrays.Contains(nameTypesSeen, nameType))
+                return null;
+
+            return Arrays.Append(nameTypesSeen, nameType);
+        }
     }
 }