Example #1
0
        /// <summary>
        ///  Reads a Radius packet from the given input stream and
        ///  creates an appropiate RadiusPacket descendant object.
        ///  Reads in all attributes and returns the object.
        ///  Decodes the encrypted fields and attributes of the packet.
        ///  @exception IOException if an IO error occurred
        ///  @exception RadiusException if the Radius packet is malformed
        /// </summary>
        /// <param name="dictionary">dictionary to use for attributes</param>
        /// <param name="inputStream"></param>
        /// <param name="request">Radius request packet if this is a response packet to be
        ///  decoded, null if this is a request packet to be decoded</param>
        /// <param name="sharedSecret">shared secret to be used to decode this packet</param>
        /// <returns>RadiusPacket object</returns>
        protected static RadiusPacket DecodePacket(IWritableDictionary dictionary, Stream inputStream,
                                                   String sharedSecret,
                                                   RadiusPacket request)
        {
            // check shared secret
            if (string.IsNullOrEmpty(sharedSecret))
            {
                throw new ArgumentNullException("sharedSecret", "no shared secret has been set");
            }

            // check request authenticator
            if (request != null && request.Authenticator == null)
            {
                throw new ArgumentNullException("request", "request authenticator not set");
            }

            // read and check header
            int type       = inputStream.ReadByte() & 0x0ff;
            int identifier = inputStream.ReadByte() & 0x0ff;
            int length     = (inputStream.ReadByte() & 0x0ff) << 8 | (inputStream.ReadByte() & 0x0ff);

            if (request != null && request.Identifier != identifier)
            {
                throw new RadiusException("bad packet: invalid packet identifier (request: " +
                                          request.Identifier + ", response: " + identifier);
            }
            if (length < RadiusHeaderLength)
            {
                throw new RadiusException("bad packet: packet too short (" + length + " bytes)");
            }
            if (length > MaxPacketLength)
            {
                throw new RadiusException("bad packet: packet too long (" + length + " bytes)");
            }

            // read rest of packet
            var authenticator = new byte[16];
            var attributeData = new byte[length - RadiusHeaderLength];

            inputStream.Read(authenticator, 0, 16);
            inputStream.Read(attributeData, 0, attributeData.Length);

            // check and count attributes
            int pos = 0;

            while (pos < attributeData.Length)
            {
                if (pos + 1 >= attributeData.Length)
                {
                    throw new RadiusException("bad packet: attribute Length mismatch");
                }
                int attributeLength = attributeData[pos + 1] & 0x0ff;
                if (attributeLength < 2)
                {
                    throw new RadiusException("bad packet: invalid attribute Length");
                }
                pos += attributeLength;
            }
            if (pos != attributeData.Length)
            {
                throw new RadiusException("bad packet: attribute Length mismatch");
            }

            // create RadiusPacket object; set properties
            RadiusPacket rp = CreateRadiusPacket(type);

            rp.Type          = type;
            rp.Identifier    = identifier;
            rp.Authenticator = authenticator;

            // load attributes
            pos = 0;
            while (pos < attributeData.Length)
            {
                int             attributeType   = attributeData[pos] & 0x0ff;
                int             attributeLength = attributeData[pos + 1] & 0x0ff;
                RadiusAttribute a = RadiusAttribute.CreateRadiusAttribute(dictionary, -1, attributeType);
                a.ReadAttribute(attributeData, pos, attributeLength);
                rp.AddAttribute(a);
                pos += attributeLength;
            }

            // request packet?
            if (request == null)
            {
                // decode attributes
                rp.DecodeRequestAttributes(sharedSecret);
                rp.CheckRequestAuthenticator(sharedSecret, length, attributeData);
            }
            else
            {
                // response packet: check authenticator
                rp.CheckResponseAuthenticator(sharedSecret, length, attributeData, request.Authenticator);
            }

            return(rp);
        }