net.jradius.freeradius.RadiusDictionary Maven / Gradle / Ivy
/**
* RadiusDictionary (for FreeRADIUS)
* Copyright (C) 2004-2006 PicoPoint, B.V.
* Copyright (c) 2006-2007 David Bird
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package net.jradius.freeradius;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import net.jradius.log.RadiusLog;
/**
* JRadius Dictionary builder for FreeRADIUS
*
* See the comments for the main method for how to build a dictionary
* library.
*
* @author David Bird
*/
@SuppressWarnings("unchecked")
public class RadiusDictionary
{
private static final String ppkg = "net.jradius.packet.attribute";
private boolean haveSeenJRadius = false;
private final String bpkg;
private final String sdir;
private final String ddir;
// private static String defaultJRadiusDictionary = // trying to make it look nice p;)
// "VENDOR\t" + "JRadius\t" + "19211\n" +
// "ATTRIBUTE\t" + "JRadius-Request-Id\t" + "1\t" + "string\t" + "JRadius\n" +
// "ATTRIBUTE\t" + "JRadius-Session-Id\t" + "2\t" + "string\t" + "JRadius\n" +
// "ATTRIBUTE\t" + "JRadius-Proxy-Client\t" + "3\t" + "octets\t" + "JRadius\n";
private static String fileHeader =
"// DO NOT EDIT THIS FILE DIRECTLY! - AUTOMATICALLY GENERATED\n" +
"// Generated by: " + RadiusDictionary.class.toString() + "\n" +
"// Generated on: " + new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").format(Calendar.getInstance().getTime()) + "\n";
private LinkedHashMap attrMap = new LinkedHashMap();
private LinkedHashMap vendorMap = new LinkedHashMap();
private LinkedHashMap seenNames = new LinkedHashMap();
private LinkedHashMap classNames = new LinkedHashMap();
private String cVendor = null;
private String cTLV = null;
class AttrDesc
{
public String name;
public String num;
public String type;
public String extra;
public String vendor;
public LinkedHashMap values = null;
public LinkedHashMap subAttributes = null;
public AttrDesc(String n, String m, String t, String e, String v)
{
name = n; num = m; type = t; extra = e; vendor = v;
}
}
class AttrValueDesc
{
public LinkedList names = new LinkedList();
public String num;
public AttrValueDesc(String n, String m)
{
num = m;
names.add(n);
}
public void addName(String n)
{
for (Iterator i=names.iterator(); i.hasNext(); )
if (i.next().equals(n))
return;
names.add(n);
}
}
class VendorDesc
{
public String name;
public String num;
public String pkg;
public String extra;
public LinkedHashMap attrMap = new LinkedHashMap();
public VendorDesc(String n, String m, String p, String e)
{
name = n; num = m; pkg = p; extra = e;
}
public String getFormat()
{
if (extra != null && extra.startsWith("format="))
{
return extra.substring(7);
}
return null; /* not custom */
}
}
public RadiusDictionary(Reader in, String pkgName, String dictDir, String srcDir) throws IOException
{
bpkg = pkgName;
ddir = dictDir;
sdir = srcDir;
readFile(new BufferedReader(in));
if (!haveSeenJRadius)
{
try
{
readFile(new BufferedReader(new FileReader(dictDir + "/" + "dictionary.jradius")));
}
catch(Exception e)
{
RadiusLog.error("WARNING!! You have not included the JRadius Dictionary (dictionary.jradius)");
}
}
}
public RadiusDictionary(String fileName, String pkgName, String dictDir, String srcDir) throws IOException
{
this(new FileReader(dictDir + "/" + fileName), pkgName, dictDir, srcDir);
}
public void readFile(BufferedReader in) throws IOException
{
String line;
while ((line = in.readLine()) != null)
{
line = line.trim();
String upperLine = line.toUpperCase();
if (upperLine.startsWith("#")) continue;
if (upperLine.startsWith("$INCLUDE"))
{
String parts[] = line.split("[\t ]+");
String file = parts[1];
if ("dictionary.jradius".equals(file)) haveSeenJRadius = true;
RadiusLog.info("Including file: " + file);
readFile(new BufferedReader(new FileReader(ddir + "/" + file)));
}
else if (upperLine.startsWith("BEGIN-TLV"))
{
String parts[] = line.split("[\t ]+");
cTLV = parts[1];
}
else if (upperLine.startsWith("END-TLV"))
{
cTLV = null;
}
else if (upperLine.startsWith("BEGIN-VENDOR"))
{
String parts[] = line.split("[\t ]+");
cVendor = parts[1];
}
else if (upperLine.startsWith("END-VENDOR"))
{
cVendor = null;
}
else if (upperLine.startsWith("ATTRIBUTE"))
{
String parts[] = line.split("[\t ]+");
String attrName = null;
String attrNum = null;
String attrType = null;
String attrExtra = null;
String attrVendor = null;
VendorDesc vdesc = null;
for (int i = 1; i < parts.length; i++)
{
String p = parts[i].trim();
if (p.length() == 0) continue;
if (attrName == null) attrName = p;
else if (attrNum == null) attrNum = p;
else if (attrType == null) attrType = p;
else
{
if ((vdesc = (VendorDesc)vendorMap.get(p)) != null)
attrVendor = p;
else
attrExtra = p;
}
}
if (attrName != null
&& attrNum != null
&& attrType != null
&& !seenNames.containsKey(attrName.toLowerCase()))
{
Map map = attrMap;
if (attrVendor == null && cVendor != null)
{
attrVendor = cVendor;
vdesc = (VendorDesc)vendorMap.get(cVendor);
}
if (vdesc != null)
{
if (cTLV != null)
{
AttrDesc attrDesc = (AttrDesc)vdesc.attrMap.get(cTLV);
if (attrDesc.subAttributes == null) attrDesc.subAttributes = new LinkedHashMap();
map = attrDesc.subAttributes;
}
else
{
map = vdesc.attrMap;
}
}
map.put(attrName, new AttrDesc(attrName, attrNum, attrType, attrExtra, attrVendor));
//RadiusLog.error(line);
System.out.println("Seen = " + attrName);
seenNames.put(attrName.toLowerCase(), attrNum);
}
}
else if (upperLine.startsWith("VALUE"))
{
String parts[] = line.split("[\t ]+");
String attrName = null;
String attrValueName = null;
String attrValueNum = null;
for (int i = 1; i < parts.length; i++)
{
String p = parts[i].trim();
if (p.length() == 0) continue;
if (attrName == null) attrName = p;
else if (attrValueName == null) attrValueName = p;
else if (attrValueNum == null) attrValueNum = p;
}
if (attrName != null && attrValueNum != null && attrValueName != null)
{
AttrDesc desc = (AttrDesc)attrMap.get(attrName);
if (desc == null && cVendor != null)
{
VendorDesc vendorDesc = (VendorDesc)vendorMap.get(cVendor);
desc = (AttrDesc)vendorDesc.attrMap.get(attrName);
}
if (desc != null)
{
AttrValueDesc avd;
if (desc.values == null) desc.values = new LinkedHashMap();
if ((avd = (AttrValueDesc)desc.values.get(attrValueNum)) == null)
desc.values.put(attrValueNum, new AttrValueDesc(attrValueName, attrValueNum));
else
avd.addName(attrValueName);
}
}
}
else if (upperLine.startsWith("VENDOR"))
{
String parts[] = line.split("[\t ]+");
String vendorName = null;
String vendorNum = null;
String vendorExtra = null;
String vendorPkg = null;
for (int i = 1; i < parts.length; i++)
{
String p = parts[i].trim();
if (p.length() == 0) continue;
if (vendorName == null) vendorName = p;
else if (vendorNum == null) vendorNum = p;
else if (vendorExtra == null) vendorExtra = p;
}
if (vendorName != null && vendorNum != null)
{
String vendor = "vsa_" + vendorName.toLowerCase().replaceAll("-",".");
vendorPkg = bpkg + "." + vendor;
if (vendorExtra != null)
{
}
vendorMap.put(vendorName, new VendorDesc(vendorName, vendorNum, vendorPkg, vendorExtra));
//RadiusLog.error(line);
}
}
}
return;
}
public void writeAttrMap(Map map, String pkg, String vName, String cName, String pName, boolean withVendors)
{
String dir = sdir + "/" + pkg.replaceAll("\\.","/");
Iterator iter = map.values().iterator();
String dictFile = dir + "/" + cName + ".java";
PrintWriter dict = null;
StringBuffer loadAttributes = new StringBuffer();
StringBuffer loadAttributesNames = new StringBuffer();
(new File(dir)).mkdirs();
if (cName != null)
{
try
{
dict = new PrintWriter(new FileWriter(dictFile));
dict.println(fileHeader);
dict.println("package " + pkg + ";");
dict.println("");
dict.println("import java.util.Map;");
dict.println("");
if (withVendors)
{
dict.println("import net.jradius.packet.attribute.AttributeDictionary;");
}
else
{
dict.println("import net.jradius.packet.attribute.VSADictionary;");
}
dict.println("");
dict.println("/**");
dict.println(" * Dictionary for package " + pkg);
dict.println(" * @author " + RadiusDictionary.class.toString());
dict.println(" */");
dict.print("public class " + cName);
if (withVendors)
{
dict.print(" implements AttributeDictionary");
}
else
{
dict.print(" implements VSADictionary");
}
dict.println("\n{");
if (withVendors)
{
dict.println(" public void loadVendorCodes(Map> map)");
dict.println(" {");
Iterator iter2 = vendorMap.values().iterator();
while (iter2.hasNext())
{
VendorDesc vdesc = (VendorDesc)iter2.next();
dict.println(" map.put(new Long(" + vdesc.num + "L), " + vdesc.pkg + ".VSADictionaryImpl.class);");
}
dict.println(" }");
dict.println("");
}
else
{
dict.println(" public String getVendorName() { return \"" + vName + "\"; }\n");
}
}
catch (Exception e)
{
e.printStackTrace();
}
loadAttributes.append(" public void loadAttributes(Map> map)\n");
loadAttributes.append(" {\n");
loadAttributesNames.append(" public void loadAttributesNames(Map> map)\n");
loadAttributesNames.append(" {\n");
}
while (iter.hasNext())
{
AttrDesc desc = (AttrDesc)iter.next();
VendorDesc vdesc = null;
StringBuffer fileSB = new StringBuffer(dir);
String pkgPath = pkg;
if (withVendors && desc.vendor != null)
{
String vendor = "vsa_" + desc.vendor.toLowerCase().replaceAll("-",".");
fileSB.append("/").append(vendor.replaceAll("\\.", "/"));
pkgPath += "." + vendor;
}
if (desc.vendor != null)
{
vdesc = (VendorDesc)vendorMap.get(desc.vendor);
}
String implementsInterface = null;
String className = "Attr_" + clean(desc.name);
String parentName = "RadiusAttribute";
if (!withVendors) parentName = "VSAttribute";
String parentImport = parentName;
if (desc.subAttributes != null)
{
parentName = "VSAWithSubAttributes";
parentImport = "VSAWithSubAttributes";
}
if (pName != null)
{
parentName = "SubAttribute";
parentImport = "SubAttribute";
}
String valueClass = "OctetsValue";
String valueArgs = "";
String extraImport = null;
String extraUtils = null;
int integerLength = 4;
(new File(fileSB.toString())).mkdirs();
fileSB.append("/").append(className).append(".java");
String file = fileSB.toString();
if (desc.type.startsWith("string"))
{
if (desc.extra != null && "encrypt=1".equals(desc.extra))
{
valueClass = "EncryptedStringValue";
}
else
{
valueClass = "StringValue";
}
}
if (desc.type.startsWith("integer"))
{
valueClass = "IntegerValue";
}
if (desc.type.startsWith("singed"))
{
valueClass = "IntegerValue";
}
if (desc.type.startsWith("date"))
{
valueClass = "DateValue";
extraUtils = "import java.util.Date;\n";
}
if (desc.type.startsWith("ipaddr"))
{
valueClass = "IPAddrValue";
extraUtils = "import java.net.InetAddress;\n";
}
if (desc.type.startsWith("ipv6addr"))
{
valueClass = "IPv6AddrValue";
extraUtils = "import java.net.InetAddress;\n";
}
if (desc.type.startsWith("byte"))
{
valueClass = "IntegerValue";
integerLength = 1;
}
if (desc.type.startsWith("short"))
{
valueClass = "IntegerValue";
integerLength = 2;
}
// WiMAX: signed
if (desc.type.startsWith("signed"))
{
valueClass = "SignedValue";
}
// WiMAX: combo-ip
if (desc.type.startsWith("combo-ip"))
{
valueClass = "ComboIPAddrValue";
}
if (desc.values != null)
{
valueClass = "NamedValue";
valueArgs = "map != null ? map : (map = new NamedValueMap())";
}
/*
if (withVendors && desc.vendor != null)
{
extraImport = valueClass;
valueArgs = "new " + valueClass + "(" + valueArgs + ")";
valueClass = "VSAValue";
}
*/
if (desc.subAttributes != null)
{
valueClass = "TLVValue";
valueArgs = "VENDOR_ID, VSA_TYPE, getSubAttributes()";
}
try
{
PrintWriter writer = new PrintWriter(new FileWriter(file));
writer.println(fileHeader);
writer.println("package " + pkgPath + ";");
writer.println("");
writer.println("import java.io.Serializable;");
if (desc.values != null)
{
writer.println("import java.util.LinkedHashMap;");
writer.println("import java.util.Map;");
writer.println("");
}
if (extraUtils != null)
{
writer.println(extraUtils);
writer.println("");
}
writer.println("import " + ppkg + "." + parentImport + ";");
if (implementsInterface != null)
{
writer.println("import " + ppkg + "." + implementsInterface + ";");
}
writer.println("import " + ppkg + ".value." + valueClass + ";");
if (desc.values != null && integerLength < 4)
writer.println("import " + ppkg + ".value.IntegerValue;");
if (extraImport != null)
{
writer.println("import net.jradius.packet.attribute.value." + extraImport + ";");
}
writer.println("");
writer.println("/**");
writer.println(" * Attribute Name: " + desc.name + "
");
if (withVendors)
{
writer.print(" * Attribute Type: " + desc.num);
if (parseInt(desc.num) > 255)
{
writer.print(" (FreeRADIUS Internal Attribute)
");
}
writer.println("
");
}
else
{
writer.println(" * Attribute Type: 26
");
writer.println(" * Vendor Id: " + vdesc.num + "
");
writer.println(" * VSA Type: " + desc.num + "
");
}
writer.println(" * Value Type: " + valueClass + "
");
if (desc.values != null)
{
writer.println(" * Possible Values:
");
writer.println(" * ");
Iterator iter2 = desc.values.values().iterator();
while (iter2.hasNext())
{
AttrValueDesc avdesc = (AttrValueDesc)iter2.next();
for (Iterator i = avdesc.names.iterator(); i.hasNext(); )
writer.println(" * - " + i.next() + " (" + avdesc.num + ")");
}
writer.println(" *
");
}
classNames.put(className, desc.num);
writer.println(" *");
writer.println(" * @author " + RadiusDictionary.class.toString());
writer.println(" */");
writer.println("public final class " + className + " extends " + parentName + (implementsInterface != null ? " implements "+implementsInterface : ""));
writer.println("{");
writer.println(" public static final String NAME = \"" + desc.name + "\";");
String attributeType = desc.num;
if (pName != null)
{
writer.println(" public static final int VENDOR_ID = " + ((VendorDesc)vendorMap.get(desc.vendor)).num + ";");
writer.println(" public static final int PARENT_TYPE = "+classNames.get(pName)+";");
writer.println(" public static final int VSA_TYPE = (" + desc.num + " << 8) | PARENT_TYPE;");
writer.println(" public static final long TYPE = ((VENDOR_ID & 0xFFFF) << 16) | VSA_TYPE;");
}
else if (withVendors)
{
writer.println(" public static final long TYPE = " + desc.num + ";");
}
else
{
attributeType = "26";
writer.println(" public static final int VENDOR_ID = " + ((VendorDesc)vendorMap.get(desc.vendor)).num + ";");
writer.println(" public static final int VSA_TYPE = " + desc.num + ";");
writer.println(" public static final long TYPE = ((VENDOR_ID & 0xFFFF) << 16) | VSA_TYPE;");
}
writer.println("");
writer.println(" public static final long serialVersionUID = TYPE;");
writer.println("");
if (desc.values != null)
{
Iterator iter2 = desc.values.values().iterator();
Map names = new LinkedHashMap();
while (iter2.hasNext())
{
AttrValueDesc avdesc = (AttrValueDesc)iter2.next();
for (Iterator i = avdesc.names.iterator(); i.hasNext(); )
{
String name = clean((String)i.next());
if (names.get(name) == null)
{
names.put(name, name);
String pubName = name;
if ("true".equals(pubName) || "false".equals(pubName))
pubName = pubName.toUpperCase();
writer.println(" public static final Long " + pubName + " = new Long(" + avdesc.num + "L);");
}
}
}
writer.println("");
writer.println(" @SuppressWarnings(\"serial\")");
writer.println(" protected class NamedValueMap implements NamedValue.NamedValueMap, Serializable");
writer.println(" {");
iter2 = desc.values.values().iterator();
String pvalues=" ";
while (iter2.hasNext())
{
AttrValueDesc avdesc = (AttrValueDesc)iter2.next();
pvalues+="new Long("+avdesc.num+"L),";
}
writer.println(" public Long[] knownValues = {"+pvalues.substring(0, pvalues.length()-1)+"};");
writer.println("");
writer.println(" public Long[] getKnownValues() { return knownValues; }");
writer.println("");
writer.println(" public Long getNamedValue(String name)");
writer.println(" {");
iter2 = desc.values.values().iterator();
while (iter2.hasNext())
{
AttrValueDesc avdesc = (AttrValueDesc)iter2.next();
for (Iterator i = avdesc.names.iterator(); i.hasNext(); )
{
String name = (String)i.next();
writer.println(" if (\""+name+"\".equals(name)) return new Long("+avdesc.num+"L);");
}
}
writer.println(" return null;");
writer.println(" }");
writer.println("");
writer.println(" public String getNamedValue(Long value)");
writer.println(" {");
iter2 = desc.values.values().iterator();
while (iter2.hasNext())
{
AttrValueDesc avdesc = (AttrValueDesc)iter2.next();
Iterator i = avdesc.names.iterator();
if (i != null && i.hasNext())
{
// The last one defined is the one used for number to String lookups!
String name = (String)i.next();
writer.println(" if (new Long(" + avdesc.num + "L).equals(value)) return \""+name+"\";");
}
}
writer.println(" return null;");
writer.println(" }");
writer.println(" };");
writer.println("");
writer.println(" public static transient NamedValueMap map = null;");
}
writer.println(" public void setup()");
writer.println(" {");
writer.println(" attributeName = NAME;");
writer.println(" attributeType = " + attributeType + ";");
if (pName != null)
{
writer.println(" setParentClass("+pName+".class);");
}
if (pName != null || !withVendors)
{
writer.println(" vendorId = VENDOR_ID;");
writer.println(" vsaAttributeType = VSA_TYPE;");
}
if (vdesc != null && vdesc.getFormat() != null)
{
writer.println(" setFormat(\""+vdesc.getFormat()+"\");");
}
writer.println(" attributeValue = new " + valueClass + "(" + valueArgs + ");");
if (valueClass.equals("IntegerValue") && integerLength < 4)
{
writer.println(" ((IntegerValue)attributeValue).setLength("+integerLength+");");
}
writer.println(" }");
writer.println("");
writer.println(" public " + className + "()");
writer.println(" {");
writer.println(" setup();");
writer.println(" }");
writer.println("");
writer.println(" public " + className + "(Serializable o)");
writer.println(" {");
writer.println(" setup(o);");
writer.println(" }");
/*if (desc.values != null)
{
writer.println("");
writer.println(" public static Map getValueMap()");
writer.println(" {");
writer.println(" return valueMap;");
writer.println(" }");
}*/
writer.println("}");
writer.close();
if (cName != null && !withVendors || desc.vendor == null)
{
loadAttributes.append(" map.put(new Long(" + desc.num + "L), " + className + ".class);\n");
loadAttributesNames.append(" map.put(" + className + ".NAME, " + className + ".class);\n");
if (desc.subAttributes != null)
{
for (Object obj : desc.subAttributes.values())
{
AttrDesc at = (AttrDesc) obj;
String cn = "Attr_" + clean(at.name);
long value = ((Integer.parseInt(at.num)) << 8) | (Integer.parseInt(desc.num) & 0xFF);
loadAttributes.append(" map.put(new Long(" + value + "L), " + cn + ".class);\n");
loadAttributesNames.append(" map.put(" + cn + ".NAME, " + cn + ".class);\n");
}
}
}
}
catch (Exception e)
{
RadiusLog.error(e.getMessage(), e);
}
if (desc.subAttributes != null)
{
writeAttrMap(desc.subAttributes, pkg, vName, null, className, false);
}
RadiusLog.info(desc.name);
}
loadAttributes.append(" }\n");
loadAttributesNames.append(" }\n");
if (dict != null)
{
dict.println(loadAttributes.toString());
dict.print(loadAttributesNames.toString());
try
{
dict.println("}");
dict.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
if (withVendors)
{
Iterator iter2 = vendorMap.values().iterator();
while (iter2.hasNext())
{
VendorDesc vdesc = (VendorDesc)iter2.next();
writeAttrMap(vdesc.attrMap, vdesc.pkg, vdesc.name, "VSADictionaryImpl", null, false);
}
}
}
public int parseInt(String s)
{
if (s.startsWith("0x"))
return Integer.parseInt(s.substring(2), 16);
return Integer.parseInt(s);
}
public void writeJavaClasses()
{
writeAttrMap(attrMap, bpkg, null, "AttributeDictionaryImpl", null, true);
}
private String clean(String s)
{
s = s.replaceAll("-", "_");
s = s.replaceAll("[^a-zA-Z0-9]+", "");
if (Character.isDigit(s.charAt(0)))
s = "_" + s;
return s;
}
/**
* Main method of the dictionary builder. Requires 3 command line
* arguments: package name, dictionary directory, and java source
* directory. For example (on one line):
*
* java net.jradius.freeradius.RadiusDictionary net.jradius.dictionary /path-to-freeradius-dictionary /path-to-java-source-directory
*
*
* @param args
*/
public static void main(String[] args)
{
if (args.length != 3)
{
System.err.println("Requires 3 arguments: [package-name] [dictionary-dir] [java-src-dir]");
System.err.println("\tpackage-name: Name of the Java package to be built (e.g. net.jradius.dictionary)");
System.err.println("\tdictionary-dir: Directory where the FreeRADIUS 'dictionary' file is");
System.err.println("\tjava-src--dir: Directory where to write Java classes");
return;
}
String file = "dictionary";
String pkg = args[0];
String dDir = args[1];
String jDir = args[2];
try
{
RadiusDictionary d = new RadiusDictionary(file, pkg, dDir, jDir);
d.writeJavaClasses();
}
catch (Exception e)
{
RadiusLog.error(e.getMessage(), e);
}
}
}