Ver Fonte

Add XOR-MAPPED-ADDRESS attribute

Bruce Wayne há 5 anos atrás
pai
commit
24c788df2b

+ 25 - 0
STUN/Message/Attributes/Attribute.cs

@@ -30,6 +30,22 @@ namespace STUN.Message.Attributes
 
         public IAttribute Value { get; set; }
 
+
+        private byte[] _magicCookie;
+        private byte[] _transactionId;
+
+        public Attribute(byte[] magicCookie, byte[] transactionID)
+        {
+            if (magicCookie.Length != 4 || transactionID.Length != 12)
+            {
+                throw new ArgumentException(@"Wrong length");
+            }
+
+            _magicCookie = magicCookie;
+
+            _transactionId = transactionID;
+        }
+
         public IEnumerable<byte> ToBytes()
         {
             var res = new List<byte>();
@@ -71,6 +87,15 @@ namespace STUN.Message.Attributes
                     }
                     break;
                 }
+                case AttributeType.XorMappedAddress:
+                {
+                    var t = new XorMappedAddressAttribute(_magicCookie, _transactionId);
+                    if (t.TryParse(value))
+                    {
+                        Value = t;
+                    }
+                    break;
+                }
                 //TODO:Parse
                 default:
                     return 0;

+ 7 - 2
STUN/Message/Attributes/MappedAddressAttribute.cs

@@ -1,5 +1,6 @@
 using STUN.Message.Enums;
 using STUN.Utils;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
@@ -11,10 +12,14 @@ namespace STUN.Message.Attributes
     /// </summary>
     public class MappedAddressAttribute : IAttribute
     {
-        public IEnumerable<byte> Bytes
+        public virtual IEnumerable<byte> Bytes
         {
             get
             {
+                if (Address == null)
+                {
+                    return Array.Empty<byte>();
+                }
                 var res = new List<byte> { 0, (byte)Family };
                 res.AddRange(Port.ToBe());
                 res.AddRange(Address.GetAddressBytes());
@@ -28,7 +33,7 @@ namespace STUN.Message.Attributes
 
         public IPAddress Address { get; set; }
 
-        public bool TryParse(byte[] bytes)
+        public virtual bool TryParse(byte[] bytes)
         {
             var length = 4;
 

+ 68 - 0
STUN/Message/Attributes/XorMappedAddressAttribute.cs

@@ -0,0 +1,68 @@
+using STUN.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc5389#section-15.2
+    /// </summary>
+    public class XorMappedAddressAttribute : MappedAddressAttribute
+    {
+        private readonly byte[] _magicCookie;
+        private readonly byte[] _transactionId;
+
+        public XorMappedAddressAttribute(byte[] magicCookie, byte[] transactionID)
+        {
+            _magicCookie = magicCookie;
+            _transactionId = transactionID;
+        }
+
+        public override IEnumerable<byte> Bytes
+        {
+            get
+            {
+                if (Address == null)
+                {
+                    return Array.Empty<byte>();
+                }
+
+                var res = new List<byte> { 0, (byte)Family };
+                res.AddRange(Xor(Port).ToBe());
+                res.AddRange(Xor(Address).GetAddressBytes());
+                return res;
+            }
+        }
+
+        public override bool TryParse(byte[] bytes)
+        {
+            if (!base.TryParse(bytes)) return false;
+
+            Port = Xor(Port);
+
+            Address = Xor(Address);
+
+            return true;
+        }
+
+        private ushort Xor(ushort port)
+        {
+            var b = port.ToBe().ToArray();
+            var xPort = BitUtils.FromBe((byte)(_magicCookie[0] ^ b[0]), (byte)(_magicCookie[1] ^ b[1]));
+            return xPort;
+        }
+
+        private IPAddress Xor(IPAddress address)
+        {
+            var b = address.GetAddressBytes();
+            var xor = _magicCookie.Concat(_transactionId).ToArray();
+            for (var i = 0; i < b.Length; ++i)
+            {
+                b[i] ^= xor[i];
+            }
+            return new IPAddress(b);
+        }
+    }
+}