diff options
Diffstat (limited to 'bkucommon/src')
7 files changed, 361 insertions, 16 deletions
| diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java index 9b3e563d..3b75a5f2 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java @@ -1,10 +1,38 @@  package at.gv.egiz.bku.accesscontroller;
 +import java.io.InputStream;
  import java.util.Hashtable;
 +import java.util.List;
 +
 +import javax.xml.bind.JAXBContext;
 +import javax.xml.bind.JAXBException;
 +import javax.xml.bind.Unmarshaller;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.bku.accesscontrol.config.AccessControl;
 +import at.gv.egiz.bku.accesscontrol.config.Chain;
 +import at.gv.egiz.bku.accesscontrol.config.Command;
 +import at.gv.egiz.bku.accesscontrol.config.ObjectFactory;
 +import at.gv.egiz.bku.accesscontrol.config.Rule;
 +import at.gv.egiz.bku.slcommands.impl.InfoboxReadCommandImpl;
 +import at.gv.egiz.bku.slexceptions.SLRuntimeException;
  public class AccessControllerFactory {
 -	private static AccessControllerFactory instance;
 +	private static AccessControllerFactory instance = new AccessControllerFactory();
 +	private static Log log = LogFactory.getLog(AccessControllerFactory.class);
 +	private static JAXBContext jaxbContext;
 +
 +	static {
 +		try {
 +			jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage()
 +					.getName());
 +		} catch (JAXBException e) {
 +			log.fatal("Cannot init jaxbContext", e);
 +		}
 +	}
  	private Hashtable<String, ChainChecker> chainTable = new Hashtable<String, ChainChecker>();
 @@ -35,5 +63,43 @@ public class AccessControllerFactory {  	public void registerChainChecker(ChainChecker cc) {
  		chainTable.put(cc.getId(), cc);
  	}
 +	
 +	public RuleChecker createRuleChecker(Rule rule) {
 +		RuleChecker rc;
 +		Command cmd = rule.getCommand();
 +		if (cmd != null) {
 +			if ((cmd.getParam() != null) && (cmd.getParam().size()>0)) {
 +				if (cmd.getName().startsWith("Infobox")) {
 +					rc = new InfoboxRuleChecker(rule.getId());
 +				} else {
 +					throw new SLRuntimeException("Cannot handle parameters for command "+cmd.getName());
 +				}
 +			} else {
 +				rc = new RuleChecker(rule.getId());
 +			}
 +		} else {
 +			rc = new RuleChecker(rule.getId());
 +		}
 +		// FIXME TODO cont. here
 +		
 +		
 +	return  rc;	
 +	}
 +	
 +	
 +	public void init(InputStream is) throws JAXBException {
 +		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
 +		AccessControl ac = (AccessControl) unmarshaller.unmarshal(is);
 +		List<Chain> chainList = ac.getChains().getChain();
 +		log.debug("Found "+chainList.size()+" chains in config");
 +		for (Chain chain : chainList) {
 +			List<Rule> ruleList = chain.getRules().getRule();
 +			log.debug("Found "+ruleList.size()+" rules in chain "+chain.getId());
 +			for (Rule rule : ruleList) {
 +				//rule.g
 +			}
 +		}
 +		
 +	}
  }
 diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainResult.java index a534f4e5..a8fb789e 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainResult.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainResult.java @@ -12,6 +12,7 @@ public class ChainResult {  	public ChainResult(Action action, UserAction userAction, boolean matchFound) {
  		this.action = action;
  		this.userAction = userAction;
 +		this.matchFound = matchFound;
  	}
  	public Action getAction() {
 diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java new file mode 100644 index 00000000..2981d24e --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java @@ -0,0 +1,14 @@ +package at.gv.egiz.bku.accesscontroller;
 +
 +/**
 + * Adds infobox parameter checks
 + * @author wbauer
 + *
 + */
 +public class InfoboxRuleChecker extends RuleChecker {
 +
 +	public InfoboxRuleChecker(String id) {
 +		super(id);
 +	}
 +
 +}
 diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java index bf46034d..c59f5b70 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java @@ -1,23 +1,36 @@  package at.gv.egiz.bku.accesscontroller;
 +import java.net.InetAddress;
 +import java.net.MalformedURLException;
 +import java.net.URL;
 +import java.net.UnknownHostException;
 +import java.util.regex.Matcher;
 +import java.util.regex.Pattern;
 +
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
 +import at.gv.egiz.bku.slcommands.SLCommand;
  import at.gv.egiz.bku.slexceptions.SLRuntimeException;
  public class RuleChecker implements AccessChecker {
 -	
 +
  	private static Log log = LogFactory.getLog(RuleChecker.class);
 -	
 -	public static enum PEER_TYPE {HOST, IP, URL};
 +
 +	public static enum PEER_TYPE {
 +		HOST, IP, URL
 +	};
  	protected String id;
  	protected AuthenticationClass authenticationClass;
  	protected String commandName;
 +	protected Pattern commandNamePattern;
  	protected String peerId;
 +	protected Pattern peerIdPattern;
  	protected PEER_TYPE peerType;
  	protected Action action;
  	protected UserAction userAction;
 +	protected String chainId;
  	public RuleChecker(String id) {
  		if (id == null) {
 @@ -27,43 +40,112 @@ public class RuleChecker implements AccessChecker {  	}
  	public void setAuthenticationClass(String ac) {
 -		AuthenticationClass tmp = AuthenticationClass.fromString(ac); 
 +		AuthenticationClass tmp = AuthenticationClass.fromString(ac);
  		if (tmp == null) {
 -			throw new SLRuntimeException("Unknown authentication class "+ac);
 +			throw new SLRuntimeException("Unknown authentication class " + ac);
  		}
  		authenticationClass = tmp;
  	}
 -	
 +
  	public void setAction(String ac) {
  		Action tmp = Action.fromString(ac);
  		if (tmp == null) {
 -			throw new SLRuntimeException("Unknown action "+ac);
 +			throw new SLRuntimeException("Unknown action " + ac);
  		}
  		action = tmp;
  	}
 -	
 +
  	public void setUserAction(String uac) {
 -		 UserAction tmp = UserAction.fromString(uac);
 +		UserAction tmp = UserAction.fromString(uac);
  		if (tmp == null) {
 -			throw new SLRuntimeException("Unknown user action "+uac);
 +			throw new SLRuntimeException("Unknown user action " + uac);
  		}
  		userAction = tmp;
  	}
 -	
 +
 +	public void setChainId(String chainId) {
 +		this.chainId = chainId;
 +	}
 +
  	public void setPeerId(String peerId, PEER_TYPE type) {
  		this.peerType = type;
  		this.peerId = peerId;
 +		peerIdPattern = Pattern.compile(peerId);
  	}
 -	
 +
 +	public void setCommandName(String commandName) {
 +		this.commandName = commandName;
 +		commandNamePattern = Pattern.compile(commandName);
 +	}
 +
  	public String getId() {
  		return id;
  	}
 +	protected boolean matchAuthenticationClass(AuthenticationClass cls) {
 +		if (this.authenticationClass == null) {
 +			return true;
 +		}
 +		return this.authenticationClass.compareTo(cls) <= 0;
 +	}
 +
 +	protected boolean matchCommandName(SLCommand cmd) {
 +		if (commandName == null) {
 +			return true;
 +		}
 +		Matcher matcher = commandNamePattern.matcher(cmd.getName());
 +		return matcher.matches();
 +	}
 +
 +	protected boolean matchPeerId(String peerUrl) {
 +		if (peerId == null) {
 +			return true;
 +		}
 +		if (peerType == PEER_TYPE.URL) {
 +			Matcher matcher = peerIdPattern.matcher(peerUrl);
 +			return matcher.matches();
 +		} else {
 +			try {
 +				URL url = new URL(peerUrl);
 +				if (peerType == PEER_TYPE.HOST) {
 +					try {
 +						String host = url.getHost();
 +						String hostName = InetAddress.getByName(host).getCanonicalHostName();
 +						Matcher matcher = peerIdPattern.matcher(hostName);
 +						return matcher.matches();
 +					} catch (UnknownHostException e) {
 +						log.error("Cannot resolve hostname", e);
 +						return false;
 +					}
 +				} else {
 +					try {
 +						String hostAddr = InetAddress.getByName(url.getHost())
 +								.getHostAddress();
 +						Matcher matcher = peerIdPattern.matcher(hostAddr);
 +						return matcher.matches();
 +					} catch (UnknownHostException e) {
 +						log.error("Cannot resolve host address", e);
 +						return false;
 +					}
 +				}
 +			} catch (MalformedURLException e) {
 +				log.error("Cannot parse url", e);
 +				return false;
 +			}
 +		}
 +	}
 +
  	@Override
  	public RuleResult check(AccessCheckerContext checkCtx) {
 -		log.debug("Processing rule: "+id);
 -		// TODO Auto-generated method stub
 -		return null;
 +		log.debug("Processing rule: " + id);
 +		if (matchAuthenticationClass(checkCtx.getAuthenticationClass())
 +				&& matchCommandName(checkCtx.getCommand())
 +				&& matchPeerId(checkCtx.getPeerUrl())) {
 +			log.debug("Match found for rule: " + id);
 +			return new RuleResult(action, userAction, true, chainId);
 +		} 
 +		log.debug("No match found for rule: " + id);
 +		return new RuleResult(action, userAction, false, chainId);
  	}
  }
 diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/ConfigTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/ConfigTest.java new file mode 100644 index 00000000..b53db264 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/ConfigTest.java @@ -0,0 +1,17 @@ +package at.gv.egiz.bku.accesscontroller;
 +
 +import javax.xml.bind.JAXBException;
 +
 +import org.junit.Test;
 +
 +public class ConfigTest {
 +
 +	public final static String RESOURCE = "at/gv/egiz/bku/accesscontroller/AccessControlConfig.xml";
 +
 +	@Test
 +	public void testUnmarshall() throws JAXBException {
 +		AccessControllerFactory.getInstance().init(
 +				getClass().getClassLoader().getResourceAsStream(RESOURCE));
 +	}
 +
 +}
 diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/RuleCheckerTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/RuleCheckerTest.java new file mode 100644 index 00000000..88f1490c --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/accesscontroller/RuleCheckerTest.java @@ -0,0 +1,87 @@ +package at.gv.egiz.bku.accesscontroller;
 +
 +import org.junit.Before;
 +import org.junit.Test;
 +
 +import at.gv.egiz.bku.accesscontroller.RuleChecker.PEER_TYPE;
 +import at.gv.egiz.bku.slcommands.impl.InfoboxReadCommandImpl;
 +import at.gv.egiz.bku.slcommands.impl.NullOperationCommandImpl;
 +import static org.junit.Assert.*;
 +
 +public class RuleCheckerTest {
 +
 +	protected RuleChecker onlyAuthChecker;
 +	protected RuleChecker onlyCmdChecker;
 +	protected RuleChecker onlyPeerChecker;
 +
 +	@Before
 +	public void setUp() {
 +		onlyAuthChecker = new RuleChecker("OnlyAuthChecker");
 +		onlyAuthChecker.setAction("allow");
 +		onlyAuthChecker.setUserAction("none");
 +		onlyAuthChecker.setAuthenticationClass("pseudoanonymous");
 +		onlyCmdChecker = new RuleChecker("OnlyCmdChecker");
 +		onlyCmdChecker.setAction("allow");
 +		onlyCmdChecker.setCommandName("InfoboxReadRequest");
 +		onlyPeerChecker = new RuleChecker("OnlyPeerChecker");
 +		onlyPeerChecker.setAction("allow");
 +		onlyPeerChecker.setPeerId("https://129.27.142..*", PEER_TYPE.URL);
 +	}
 +
 +	@Test
 +	public void testAuthClass() {
 +		AccessCheckerContext ctx = new AccessCheckerContext(null,
 +				AuthenticationClass.ANONYMOUS, null);
 +		RuleResult rr = onlyAuthChecker.check(ctx);
 +		assertFalse(rr.matchFound());
 +		ctx = new AccessCheckerContext(null, AuthenticationClass.PSEUDO_ANONYMOUS,
 +				null);
 +		rr = onlyAuthChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +		ctx = new AccessCheckerContext(null, AuthenticationClass.CERTIFIED, null);
 +		rr = onlyAuthChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +	}
 +
 +	@Test
 +	public void testCmd() {
 +		AccessCheckerContext ctx = new AccessCheckerContext(
 +				new InfoboxReadCommandImpl(), null, null);
 +		RuleResult rr = onlyCmdChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +		onlyCmdChecker.setCommandName("Info.*");
 +		rr = onlyCmdChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +		ctx = new AccessCheckerContext(new NullOperationCommandImpl(), null, null);
 +		rr = onlyCmdChecker.check(ctx);
 +		assertFalse(rr.matchFound());
 +		onlyCmdChecker.setCommandName(".*");
 +		rr = onlyCmdChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +	}
 +
 +	@Test
 +	public void testPeerId() {
 +		AccessCheckerContext ctx = new AccessCheckerContext(null, null,
 +				"https://129.27.142.20:80/index.html");
 +		RuleResult rr = onlyPeerChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +
 +		ctx = new AccessCheckerContext(null, null,
 +				"https://129.27.14.20:80/index.html");
 +		rr = onlyPeerChecker.check(ctx);
 +		assertFalse(rr.matchFound());
 +		
 +		onlyPeerChecker.setPeerId(".*.iaik..*", PEER_TYPE.HOST);
 +		ctx = new AccessCheckerContext(null, null,
 +		"https://129.27.142.20:80/index.html");
 +		rr = onlyPeerChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +		
 +		onlyPeerChecker.setPeerId("129.27.142..*", PEER_TYPE.IP);
 +		ctx = new AccessCheckerContext(null, null, "https://www.iaik.tugraz.at:80/");
 +		rr = onlyPeerChecker.check(ctx);
 +		assertTrue(rr.matchFound());
 +	}
 +
 +}
 diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/accesscontroller/AccessControlConfig.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/accesscontroller/AccessControlConfig.xml new file mode 100644 index 00000000..2455d68d --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/accesscontroller/AccessControlConfig.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?>
 +<AccessControl>
 +	<Chains>
 +		<Chain Id="Identification">
 +			<Rules>
 +				<Rule Id="rule-1">
 +					<AuthClass>certifiedGovAgency</AuthClass>
 +					<AnyPeer />
 +					<Action>
 +						<RuleAction>allow</RuleAction>
 +					</Action>
 +					<UserInteraction>confirm</UserInteraction>
 +				</Rule>
 +				<Rule Id="rule-2">
 +					<AuthClass>pseudoanonymous</AuthClass>
 +					<AnyPeer />
 +					<Action>
 +						<ChainRef>Command</ChainRef>
 +					</Action>
 +					<UserInteraction>none</UserInteraction>
 +				</Rule>
 +				<Rule Id="rule-3">
 +					<AuthClass>anonymous</AuthClass>
 +					<IPv4Address>127.0.0.1</IPv4Address>
 +					<Action>
 +						<ChainRef>Command</ChainRef>
 +					</Action>
 +					<UserInteraction>none</UserInteraction>
 +				</Rule>
 +				<Rule Id="rule-4">
 +					<AuthClass>anonymous</AuthClass>
 +					<DomainName>*.gv.at</DomainName>
 +					<Action>
 +						<RuleAction>allow</RuleAction>
 +					</Action>
 +					<UserInteraction>confirm</UserInteraction>
 +				</Rule>
 +			</Rules>
 +		</Chain>
 +		<Chain Id="Command">
 +			<Rules>
 +				<Rule Id="cmd-rule-1">
 +					<AuthClass>certified</AuthClass>
 +					<AnyPeer />
 +					<Command Name="Infobox*">
 +						<Param Name="InfoboxIdentifier">IdentityLink</Param>
 +						<Param Name="PersonIdentifier">*</Param>
 +					</Command>
 +					<Action>
 +						<RuleAction>allow</RuleAction>
 +					</Action>
 +					<UserInteraction>confirm</UserInteraction>
 +				</Rule>
 +				<Rule Id="cmd-rule-2">
 +					<AuthClass>certified</AuthClass>
 +					<URL>https://finanzonline.bmf.gv.at/*</URL>
 +					<Command Name="InfoboxReadRequest">
 +						<Param Name="InfoboxIdentifier">Mandates</Param>
 +						<Param Name="PersonIdentifier">*</Param>
 +					</Command>
 +					<Action>
 +						<RuleAction>allow</RuleAction>
 +					</Action>
 +					<UserInteraction>info</UserInteraction>
 +				</Rule>
 +				<Rule Id="cmd-rule-3">
 +					<AuthClass>certified</AuthClass>
 +					<AnyPeer />
 +					<Command Name="InfoboxReadRequest" />
 +					<Action>
 +						<RuleAction>allow</RuleAction>
 +					</Action>
 +					<UserInteraction>none</UserInteraction>
 +				</Rule>
 +			</Rules>
 +		</Chain>
 +	</Chains>
 +</AccessControl>
 | 
