/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package fedora.server.security; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import org.apache.log4j.Logger; import fedora.common.PID; /** * @author Bill Niebel */ public class BackendPolicies { /** Logger for this class. */ private static final Logger LOG = Logger.getLogger(BackendPolicies.class.getName()); public static final String FEDORA_INTERNAL_CALL = "fedoraInternalCall-1"; public static final String BACKEND_SERVICE_CALL_UNSECURE = "fedoraInternalCall-2"; private String inFilePath = null; private String outFilePath = null; private BackendSecuritySpec backendSecuritySpec = null; public BackendPolicies(String inFilePath, String outFilePath) { this.inFilePath = inFilePath; this.outFilePath = outFilePath; } public BackendPolicies(String inFilePath) { this(inFilePath, null); } public Hashtable generateBackendPolicies() throws Exception { LOG.debug("in BackendPolicies.generateBackendPolicies() 1"); Hashtable tempfiles = null; if (inFilePath.endsWith(".xml")) { // replacing code for .properties LOG.debug("in BackendPolicies.generateBackendPolicies() .xml 1"); BackendSecurityDeserializer bds = new BackendSecurityDeserializer("UTF-8", false); LOG.debug("in BackendPolicies.generateBackendPolicies() .xml 2"); backendSecuritySpec = bds.deserialize(inFilePath); LOG.debug("in BackendPolicies.generateBackendPolicies() .xml 3"); tempfiles = writePolicies(); LOG.debug("in BackendPolicies.generateBackendPolicies() .xml 4"); } return tempfiles; } private static final String[] parseForSlash(String key) throws Exception { int lastSlash = key.lastIndexOf("/"); if (lastSlash + 1 == key.length()) { throw new Exception("BackendPolicies.newWritePolicies() " + "can't handle key ending with '/'"); } if (lastSlash != key.indexOf("/")) { throw new Exception("BackendPolicies.newWritePolicies() " + "can't handle key containing multiple instances of '/'"); } String[] parts = null; if (-1 < lastSlash && lastSlash < key.length()) { parts = key.split("/"); } else { parts = new String[] {key}; } return parts; } private static final String getExcludedRolesText(String key, Set roles) { StringBuffer excludedRolesText = new StringBuffer(); if ("default".equals(key) && roles.size() > 1) { excludedRolesText.append("\t\t<ExcludedRoles>\n"); Iterator excludedRoleIterator = roles.iterator(); while (excludedRoleIterator.hasNext()) { LOG .debug("in BackendPolicies.newWritePolicies() another inner it"); String excludedRole = (String) excludedRoleIterator.next(); if ("default".equals(excludedRole)) { continue; } LOG.debug("in BackendPolicies.newWritePolicies() excludedRole=" + excludedRole); excludedRolesText.append("\t\t\t<ExcludedRole>"); excludedRolesText.append(excludedRole); excludedRolesText.append("</ExcludedRole>\n"); } excludedRolesText.append("\t\t</ExcludedRoles>\n"); } return excludedRolesText.toString(); } private static final String writeRules(String callbackBasicAuth, String callbackSsl, String iplist, String role, Set roles) throws Exception { StringBuffer temp = new StringBuffer(); temp.append("\t<Rule RuleId=\"1\" Effect=\"Permit\">\n"); temp.append(getExcludedRolesText(role, roles)); if ("true".equals(callbackBasicAuth)) { temp.append("\t\t<AuthnRequired/>\n"); } if ("true".equals(callbackSsl)) { temp.append("\t\t<SslRequired/>\n"); } LOG.debug("DEBUGGING IPREGEX0 [" + iplist + "]"); String[] ipRegexes = new String[0]; if (iplist != null && !"".equals(iplist.trim())) { ipRegexes = iplist.trim().split("\\s"); } /* * if (ipRegexes.length == 1) { //fixup ipRegexes[0] = * ipRegexes[0].trim(); } */ LOG.debug("DEBUGGING IPREGEX1 [" + iplist.trim() + "]"); if (ipRegexes.length != 0) { temp.append("\t\t<IpRegexes>\n"); for (String element : ipRegexes) { LOG.debug("DEBUGGING IPREGEX2 " + element); temp.append("\t\t\t<IpRegex>"); temp.append(element); temp.append("</IpRegex>\n"); } temp.append("\t\t</IpRegexes>\n"); } temp.append("\t</Rule>\n"); if ("true".equals(callbackBasicAuth) || "true".equals(callbackSsl) || ipRegexes.length != 0) { temp.append("\t<Rule RuleId=\"2\" Effect=\"Deny\">\n"); temp.append(getExcludedRolesText(role, roles)); temp.append("\t</Rule>\n"); } return temp.toString(); } private Hashtable writePolicies() throws Exception { LOG.debug("in BackendPolicies.newWritePolicies() 1"); StringBuffer sb = null; Hashtable<String, String> tempfiles = new Hashtable<String, String>(); Iterator coarseIterator = backendSecuritySpec.listRoleKeys().iterator(); while (coarseIterator.hasNext()) { String key = (String) coarseIterator.next(); String[] parts = parseForSlash(key); String filename1 = ""; String filename2 = ""; switch (parts.length) { case 2: filename2 = "-method-" + parts[1]; //break purposely absent: fall through case 1: if (-1 == parts[0].indexOf(":")) { filename1 = "callback-by:" + parts[0]; } else { filename1 = "callback-by-sdep-" + parts[0]; } if ("".equals(filename2)) { if (!"default".equals(parts[0])) { filename2 = "-other-methods"; } } break; default: //bad value throw new Exception("BackendPolicies.newWritePolicies() " + "didn't correctly parse key " + key); } sb = new StringBuffer(); LOG .debug("in BackendPolicies.newWritePolicies() another outer it, key=" + key); Hashtable properties = backendSecuritySpec.getSecuritySpec(key); LOG .debug("in BackendPolicies.newWritePolicies() properties.size()=" + properties.size()); LOG .debug("in BackendPolicies.newWritePolicies() properties.get(BackendSecurityDeserializer.ROLE)=" + properties.get(BackendSecurityDeserializer.ROLE)); String callbackBasicAuth = (String) properties .get(BackendSecurityDeserializer.CALLBACK_BASIC_AUTH); if (callbackBasicAuth == null) { callbackBasicAuth = "false"; } LOG .debug("in BackendPolicies.newWritePolicies() CallbackBasicAuth=" + callbackBasicAuth); String callbackSsl = (String) properties .get(BackendSecurityDeserializer.CALLBACK_SSL); if (callbackSsl == null) { callbackSsl = "false"; } String iplist = (String) properties.get(BackendSecurityDeserializer.IPLIST); if (iplist == null) { iplist = ""; } LOG.debug("in BackendPolicies.newWritePolicies() coarseIplist=" + iplist); String id = "generated_for_" + key.replace(':', '-'); LOG.debug("in BackendPolicies.newWritePolicies() id=" + id); LOG.debug("in BackendPolicies.newWritePolicies() " + filename1 + " " + filename2); String filename = filename1 + filename2; //was id.replace(':','-'); LOG.debug("in BackendPolicies.newWritePolicies() " + filename); PID tempPid = new PID(filename); LOG.debug("in BackendPolicies.newWritePolicies() got PID " + tempPid); filename = tempPid.toFilename(); LOG.debug("in BackendPolicies.newWritePolicies() filename=" + filename); sb .append("<Policy xmlns=\"urn:oasis:names:tc:xacml:1.0:policy\" PolicyId=\"" + id + "\">\n"); sb .append("\t<Description>this policy is machine-generated at each Fedora server startup. edit beSecurity.xml to change this policy.</Description>\n"); sb.append("\t<Target>\n"); sb.append("\t\t<Subjects>\n"); if ("default".equals(key)) { sb.append("\t\t\t<AnySubject/>\n"); } else { sb.append("\t\t\t<Subject>\n"); sb.append("\t\t\t\t<SubjectMatch>\n"); sb.append("\t\t\t\t\t<AttributeValue>" + key + "</AttributeValue>\n"); sb.append("\t\t\t\t</SubjectMatch>\n"); sb.append("\t\t\t</Subject>\n"); } sb.append("\t\t</Subjects>\n"); sb.append("\t</Target>\n"); String temp = writeRules(callbackBasicAuth, callbackSsl, iplist, key, backendSecuritySpec.listRoleKeys()); sb.append(temp); sb.append("</Policy>\n"); LOG.debug("\ndumping policy\n" + sb + "\n"); File outfile = null; if (outFilePath == null) { outfile = File.createTempFile(filename, ".xml"); } else { outfile = new File(outFilePath + File.separator + filename + ".xml"); } tempfiles.put(filename + ".xml", outfile.getAbsolutePath()); PrintStream pos = new PrintStream(new FileOutputStream(outfile)); pos.println(sb); pos.close(); } LOG.debug("finished writing temp files"); return tempfiles; } public static void main(String[] args) throws Exception { BackendPolicies backendPolicies = new BackendPolicies(args[0], args[1]); backendPolicies.generateBackendPolicies(); } }