/// <summary> /// Parses a VALUE line containing an enumeration value. /// </summary> private static void ParseValueLine(IWritableDictionary dictionary, string[] tok, int lineNum) { try { if (tok.Length != 4) { throw new IOException("expect 4 columns but actual is " + tok.Length); } String typeName = tok[1].Trim(); String enumName = tok[2].Trim(); String valStr = tok[3].Trim(); AttributeType at = dictionary.GetAttributeTypeByName(typeName); if (at == null) { throw new IOException("unknown attribute type: " + typeName + ", line: " + lineNum); } at.AddEnumerationValue(Convert.ToInt32(valStr), enumName); } catch (Exception ex) { throw new IOException("syntax error on line" + lineNum, ex); } }
/// <summary> /// Reads a Radius response packet from the given input stream and /// creates an appropiate RadiusPacket descendant object. /// Reads in all attributes and returns the object. /// Checks the packet authenticator. /// @param dictionary dictionary to use for attributes /// @param in InputStream to read packet from /// @param sharedSecret shared secret to be used to decode this packet /// @param request Radius request packet /// @return new RadiusPacket object /// @exception IOException IO error /// @exception RadiusException malformed packet /// </summary> public RadiusPacket DecodeResponsePacket(IWritableDictionary dictionary, Stream @in, String sharedSecret, RadiusPacket request) { if (request == null) { throw new ArgumentNullException("request", "request may not be null"); } return(DecodePacket(dictionary, @in, sharedSecret, request)); }
/// <summary> /// Parses a line containing a vendor declaration. /// </summary> private static void ParseVendorLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 3) { throw new IOException("syntax error on line " + lineNum); } int vendorId = Convert.ToInt32(tok[1].Trim()); String vendorName = tok[2].Trim(); dictionary.AddVendor(vendorId, vendorName); }
/// <summary> /// Returns a new dictionary filled with the contents /// from the given input stream. /// @param source input stream /// @return dictionary object /// @throws IOException /// </summary> //public static IDictionary ParseDictionary(Stream source) //{ // IWritableDictionary d = new MemoryDictionary(); // ParseDictionary(source, d); // return d; //} /// <summary> /// Parses the dictionary from the specified InputStream. /// @param source input stream /// @param dictionary dictionary data is written to /// @throws IOException syntax errors /// @throws NotImplementedException syntax errors /// </summary> public static void ParseDictionary(Stream source, IWritableDictionary dictionary) { // read each line separately var @in = new StreamReader(source); String line; int lineNum = -1; while ((line = @in.ReadLine()) != null) { // ignore comments lineNum++; line = line.Trim(); if (line.StartsWith("#") || line.Length == 0) { continue; } // tokenize line by whitespace string[] tok = Regex.Split(line, "[\\t ]+"); String lineType = tok[0].ToUpper(); switch (lineType) { case ("ATTRIBUTE"): parseAttributeLine(dictionary, tok, lineNum); break; case ("VALUE"): ParseValueLine(dictionary, tok, lineNum); break; case ("$INCLUDE"): IncludeDictionaryFile(dictionary, tok, lineNum); break; case ("VENDORATTR"): ParseVendorAttributeLine(dictionary, tok, lineNum); break; case ("VENDOR"): ParseVendorLine(dictionary, tok, lineNum); break; default: throw new IOException("unknown line type: " + lineType + " line: " + lineNum); } } }
/// <summary> /// Parses a line that declares a Vendor-Specific attribute. /// </summary> private static void ParseVendorAttributeLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 5) { throw new IOException("syntax error on line " + lineNum); } String vendor = tok[1].Trim(); String name = tok[2].Trim(); int code = Convert.ToInt32(tok[3].Trim()); String typeStr = tok[4].Trim(); Type type = GetAttributeTypeClass(code, typeStr); var at = new AttributeType(Convert.ToInt32(vendor), code, name, type); dictionary.AddAttributeType(at); }
/// <summary> /// Parse a line that declares an attribute. /// </summary> private static void parseAttributeLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 4) { throw new IOException("syntax error on line " + lineNum); } // read name, code, type String name = tok[1]; int code = Convert.ToInt32(tok[2]); String typeStr = tok[3]; // translate type to class Type type = code == VendorSpecificAttribute.VENDOR_SPECIFIC ? typeof(VendorSpecificAttribute) : GetAttributeTypeClass(code, typeStr); // create and cache object dictionary.AddAttributeType(new AttributeType(code, name, type)); }
/// <summary> /// Parse a line that declares an attribute. /// </summary> private static void parseAttributeLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 4) { throw new IOException("syntax error on line " + lineNum); } // read name, code, type String name = tok[1]; int code = Convert.ToInt32(tok[2]); String typeStr = tok[3]; // translate type to class Type type = code == VendorSpecificAttribute.VENDOR_SPECIFIC ? typeof (VendorSpecificAttribute) : GetAttributeTypeClass(code, typeStr); // create and cache object dictionary.AddAttributeType(new AttributeType(code, name, type)); }
/// <summary> /// Returns a new dictionary filled with the contents /// from the given input stream. /// @param source input stream /// @return dictionary object /// @throws IOException /// </summary> //public static IDictionary ParseDictionary(Stream source) //{ // IWritableDictionary d = new MemoryDictionary(); // ParseDictionary(source, d); // return d; //} /// <summary> /// Parses the dictionary from the specified InputStream. /// @param source input stream /// @param dictionary dictionary data is written to /// @throws IOException syntax errors /// @throws NotImplementedException syntax errors /// </summary> public static void ParseDictionary(Stream source, IWritableDictionary dictionary) { // read each line separately var @in = new StreamReader(source); String line; int lineNum = -1; while ((line = @in.ReadLine()) != null) { // ignore comments lineNum++; line = line.Trim(); if (line.StartsWith("#") || line.Length == 0) continue; // tokenize line by whitespace string[] tok = Regex.Split(line, "[\\t ]+"); String lineType = tok[0].ToUpper(); switch (lineType) { case ("ATTRIBUTE"): parseAttributeLine(dictionary, tok, lineNum); break; case ("VALUE"): ParseValueLine(dictionary, tok, lineNum); break; case ("$INCLUDE"): IncludeDictionaryFile(dictionary, tok, lineNum); break; case ("VENDORATTR"): ParseVendorAttributeLine(dictionary, tok, lineNum); break; case ("VENDOR"): ParseVendorLine(dictionary, tok, lineNum); break; default: throw new IOException("unknown line type: " + lineType + " line: " + lineNum); } } }
/// <summary> /// Includes a dictionary file. /// </summary> private static void IncludeDictionaryFile(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 2) { throw new IOException("syntax error on line " + lineNum); } String includeFile = tok[1]; var incf = new FileInfo(includeFile); if (!incf.Exists) { throw new IOException("inclueded file '" + includeFile + "' not found, line " + lineNum); } FileStream fs = incf.OpenRead(); ParseDictionary(fs, dictionary); // line numbers begin with 0 again, but file name is // not mentioned in exceptions // furthermore, this method does not allow to include // classpath resources }
/// <summary> /// Creates a RadiusAttribute object of the appropriate type. /// @param dictionary Hashtable to use /// @param vendorId vendor ID or -1 /// @param attributeType attribute type /// @return RadiusAttribute object /// </summary> public static RadiusAttribute CreateRadiusAttribute(IWritableDictionary dictionary, int vendorId, int attributeType) { var attribute = new RadiusAttribute(); AttributeType at = dictionary.GetAttributeTypeByCode(vendorId, attributeType); if (at != null && at.Class != null) { try { attribute = (RadiusAttribute)Activator.CreateInstance(at.Class); } catch (Exception e) { // error instantiating class - should not occur } } attribute.Type = attributeType; attribute.Dictionary = dictionary; attribute.VendorId = vendorId; return(attribute); }
/// <summary> /// Reads a Radius request 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. /// @param dictionary dictionary to use for attributes /// @param in InputStream to read packet from /// @param sharedSecret shared secret to be used to decode this packet /// @return new RadiusPacket object /// @exception IOException IO error /// @exception RadiusException malformed packet /// </summary> public RadiusPacket DecodeRequestPacket(IWritableDictionary dictionary, Stream @in, String sharedSecret) { return(DecodePacket(dictionary, @in, sharedSecret, null)); }
/// <summary> /// Creates a RadiusAttribute object of the appropriate type. /// @param dictionary Hashtable to use /// @param vendorId vendor ID or -1 /// @param attributeType attribute type /// @return RadiusAttribute object /// </summary> public static RadiusAttribute CreateRadiusAttribute(IWritableDictionary dictionary, int vendorId, int attributeType) { var attribute = new RadiusAttribute(); AttributeType at = dictionary.GetAttributeTypeByCode(vendorId, attributeType); if (at != null && at.Class != null) { try { attribute = (RadiusAttribute) Activator.CreateInstance(at.Class); } catch (Exception e) { // error instantiating class - should not occur } } attribute.Type = attributeType; attribute.Dictionary = dictionary; attribute.VendorId = vendorId; return attribute; }
/// <summary> /// Parses a line containing a vendor declaration. /// </summary> private static void ParseVendorLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 3) throw new IOException("syntax error on line " + lineNum); int vendorId = Convert.ToInt32(tok[1].Trim()); String vendorName = tok[2].Trim(); dictionary.AddVendor(vendorId, vendorName); }
/// <summary> /// Includes a dictionary file. /// </summary> private static void IncludeDictionaryFile(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 2) throw new IOException("syntax error on line " + lineNum); String includeFile = tok[1]; var incf = new FileInfo(includeFile); if (!incf.Exists) throw new IOException("inclueded file '" + includeFile + "' not found, line " + lineNum); FileStream fs = incf.OpenRead(); ParseDictionary(fs, dictionary); // line numbers begin with 0 again, but file name is // not mentioned in exceptions // furthermore, this method does not allow to include // classpath resources }
/// <summary> /// Parses a VALUE line containing an enumeration value. /// </summary> private static void ParseValueLine(IWritableDictionary dictionary, string[] tok, int lineNum) { try { if (tok.Length != 4) throw new IOException("expect 4 columns but actual is " + tok.Length); String typeName = tok[1].Trim(); String enumName = tok[2].Trim(); String valStr = tok[3].Trim(); AttributeType at = dictionary.GetAttributeTypeByName(typeName); if (at == null) throw new IOException("unknown attribute type: " + typeName + ", line: " + lineNum); at.AddEnumerationValue(Convert.ToInt32(valStr), enumName); } catch (Exception ex) { throw new IOException("syntax error on line" + lineNum, ex); } }
/// <summary> /// Parses a line that declares a Vendor-Specific attribute. /// </summary> private static void ParseVendorAttributeLine(IWritableDictionary dictionary, string[] tok, int lineNum) { if (tok.Length != 5) throw new IOException("syntax error on line " + lineNum); String vendor = tok[1].Trim(); String name = tok[2].Trim(); int code = Convert.ToInt32(tok[3].Trim()); String typeStr = tok[4].Trim(); Type type = GetAttributeTypeClass(code, typeStr); var at = new AttributeType(Convert.ToInt32(vendor), code, name, type); dictionary.AddAttributeType(at); }
/// <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; }
/// <summary> /// Reads a Radius response packet from the given input stream and /// creates an appropiate RadiusPacket descendant object. /// Reads in all attributes and returns the object. /// Checks the packet authenticator. /// @param dictionary dictionary to use for attributes /// @param in InputStream to read packet from /// @param sharedSecret shared secret to be used to decode this packet /// @param request Radius request packet /// @return new RadiusPacket object /// @exception IOException IO error /// @exception RadiusException malformed packet /// </summary> public RadiusPacket DecodeResponsePacket(IWritableDictionary dictionary, Stream @in, String sharedSecret, RadiusPacket request) { if (request == null) throw new ArgumentNullException("request", "request may not be null"); return DecodePacket(dictionary, @in, sharedSecret, request); }
/// <summary> /// Reads a Radius request 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. /// @param dictionary dictionary to use for attributes /// @param in InputStream to read packet from /// @param sharedSecret shared secret to be used to decode this packet /// @return new RadiusPacket object /// @exception IOException IO error /// @exception RadiusException malformed packet /// </summary> public RadiusPacket DecodeRequestPacket(IWritableDictionary dictionary, Stream @in, String sharedSecret) { return DecodePacket(dictionary, @in, sharedSecret, null); }
/// <summary> /// Creates a Radius attribute. The default dictionary is /// used. /// @param attributeType attribute type /// @return RadiusAttribute instance /// </summary> public static RadiusAttribute CreateRadiusAttribute(int attributeType) { IWritableDictionary dictionary = DefaultDictionary.GetDefaultDictionary(); return(CreateRadiusAttribute(dictionary, -1, attributeType)); }
/// <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); }