コード例 #1
0
        /// <summary>
        /// Parses the content and returns an object of proper type
        /// </summary>
        /// <param name="contentBytes"></param>
        /// <param name="type"></param>
        /// <param name="code"></param>
        /// <param name="authenticator"></param>
        /// <param name="sharedSecret"></param>
        /// <returns></returns>
        private static Object ParseContentBytes(Byte[] contentBytes, String type, UInt32 code, Byte[] authenticator, Byte[] sharedSecret)
        {
            switch (type)
            {
            case "string":
                return(Encoding.UTF8.GetString(contentBytes));

            case "tagged-string":
                return(Encoding.UTF8.GetString(contentBytes));

            case "octet":
                // If this is a password attribute it must be decrypted
                if (code == 2)
                {
                    return(RadiusPassword.Decrypt(sharedSecret, authenticator, contentBytes));
                }
                return(contentBytes);

            case "integer":
                return(BitConverter.ToUInt32(contentBytes.Reverse().ToArray(), 0));

            case "tagged-integer":
                return(BitConverter.ToUInt32(contentBytes.Reverse().ToArray(), 0));

            case "ipaddr":
                return(new IPAddress(contentBytes));

            default:
                return(null);
            }
        }
コード例 #2
0
        /// <summary>
        /// Parses the content and returns an object of proper type
        /// </summary>
        /// <param name="contentBytes"></param>
        /// <param name="type"></param>
        /// <param name="code"></param>
        /// <param name="authenticator"></param>
        /// <param name="sharedSecret"></param>
        /// <returns></returns>
        private static Object ParseContentBytes(Byte[] contentBytes, String type, UInt32 code, Byte[] authenticator, Byte[] sharedSecret)
        {
            switch (type)
            {
            case "string":
            case "String":
            case "tagged-string":
                return(Encoding.UTF8.GetString(contentBytes));

            case "octet":
            case "octets":
                // If this is a password attribute it must be decrypted
                if (code == 2)
                {
                    return(RadiusPassword.Decrypt(sharedSecret, authenticator, contentBytes));
                }

                return(contentBytes);

            case "ipaddr":
            case "ipv6addr":
                return(new IPAddress(contentBytes));

            case "date":
                return(DateTimeOffset.FromUnixTimeSeconds(BitConverter.ToUInt32(contentBytes.Reverse().ToArray(), 0)));

            case "short":
                return(BitConverter.ToUInt16(contentBytes.Reverse().ToArray(), 0));

            case "integer":
            case "signed":
            case "tagged-integer":
                return(BitConverter.ToUInt32(contentBytes.Reverse().ToArray(), 0));

            case "integer64":
                return(BitConverter.ToUInt64(contentBytes.Reverse().ToArray(), 0));

            case "abinary":                  // Ascend binary filter format.
            case "byte":                     // 8-bit unsigned integer.
            case "bytes":
            case "combo-ip":
            case "ether":                   // Ethernet MAC address.
            case "extended":
            case "ifid":                    // Interface Id (hex:hex:hex).
            case "ipv4prefix":              // IPv4 Prefix as given in RFC 6572.
            case "ipv6prefix":              // IPv6 prefix, with mask. 2001:db8:a000:ff::/64
            case "long-extended":
            case "struct":                  // Fixed size structures.
            case "tlv":                     // Type-Length-Value (allows nested attributes).
            default:
                _log.Warn($"No content parser for type '{type}'.");
                return(null);
            }
        }
コード例 #3
0
        /// <summary>
        /// Get the raw packet bytes
        /// </summary>
        /// <returns></returns>
        public Byte[] GetBytes(RadiusDictionary dictionary)
        {
            var packetBytes = new List <Byte>
            {
                (Byte)Code,
                Identifier
            };

            packetBytes.AddRange(new Byte[18]); // Placeholder for length and authenticator

            var messageAuthenticatorPosition = 0;

            foreach (var attribute in Attributes)
            {
                // todo add logic to check attribute object type matches type in dictionary?
                foreach (var value in attribute.Value)
                {
                    var contentBytes = GetAttributeValueBytes(value);
                    var headerBytes  = new Byte[2];

                    dictionary.AttributeNames.TryGetValue(attribute.Key, out var attributeType);
                    switch (attributeType)
                    {
                    case DictionaryVendorAttribute _attributeType:
                        headerBytes    = new Byte[8];
                        headerBytes[0] = 26;     // VSA type

                        var vendorId = BitConverter.GetBytes(_attributeType.VendorId);
                        Array.Reverse(vendorId);
                        Buffer.BlockCopy(vendorId, 0, headerBytes, 2, 4);
                        headerBytes[6] = (Byte)_attributeType.VendorCode;
                        headerBytes[7] = (Byte)(2 + contentBytes.Length);      // length of the vsa part
                        break;

                    case DictionaryAttribute _attributeType:
                        headerBytes[0] = attributeType.Code;

                        // Encrypt password if this is a User-Password attribute
                        if (_attributeType.Code == 2)
                        {
                            contentBytes = RadiusPassword.Encrypt(SharedSecret, Authenticator, contentBytes);
                        }
                        else if (_attributeType.Code == 80)        // Remember the position of the message authenticator, because it has to be added after everything else
                        {
                            messageAuthenticatorPosition = packetBytes.Count;
                        }
                        break;

                    default:
                        throw new InvalidOperationException($"Unknown attribute {attribute.Key}, check spelling or dictionary");
                    }

                    headerBytes[1] = (Byte)(headerBytes.Length + contentBytes.Length);
                    packetBytes.AddRange(headerBytes);
                    packetBytes.AddRange(contentBytes);
                }
            }

            // Note the order of the bytes...
            var packetLengthBytes = BitConverter.GetBytes(packetBytes.Count);

            packetBytes[2] = packetLengthBytes[1];
            packetBytes[3] = packetLengthBytes[0];

            var packetBytesArray = packetBytes.ToArray();

            if (Code == PacketCode.AccountingRequest || Code == PacketCode.DisconnectRequest)
            {
                var authenticator = CalculateRequestAuthenticator(SharedSecret, packetBytesArray);
                Buffer.BlockCopy(authenticator, 0, packetBytesArray, 4, 16);
            }
            else
            {
                var authenticator = _requestAuthenticator != null?CalculateResponseAuthenticator(SharedSecret, _requestAuthenticator, packetBytesArray) : Authenticator;

                Buffer.BlockCopy(authenticator, 0, packetBytesArray, 4, 16);
            }

            if (messageAuthenticatorPosition != 0)
            {
                var temp = new Byte[16];
                Buffer.BlockCopy(temp, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16);
                var messageAuthenticatorBytes = CalculateMessageAuthenticator(packetBytesArray, SharedSecret);
                Buffer.BlockCopy(messageAuthenticatorBytes, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16);
            }


            return(packetBytesArray);
        }