/* * Copyrighted (C) 2002, Networks Associates Technology, Inc. * All rights reserved */ package com.nailabs.abac.trust; import com.nailabs.abac.process.*; import com.nailabs.abac.test.*; import edu.stanford.peer.rbtm.credential.*; import java.util.*; import java.io.*; /** * A trust target graph node, representing a linking goal. This node has a * triplet uniqueness based on the verifier, rolename, and subject. It can * have multiple parents (via linking monintor edges) and multiple childen * (via linking solution edges). */ public class LinkingGoalNode extends TTGNode implements SatisfactionListener { // Node state information constants /** Reserved for future use */ public static final String OPAQUE = "opaque"; private CompletionState state = new CompletionState(); private int completionCount = 0; /** string constructor */ public LinkingGoalNode(String goal) throws TrustTargetParsingException, CredentialParsingException { this(new LinkingGoal(goal)); } /** parsed object constructor */ public LinkingGoalNode(Entity verifier, RoleName target, Entity subject) throws TrustTargetParsingException, CredentialParsingException { this(new LinkingGoal(verifier, target, subject)); } /** default constructor */ public LinkingGoalNode(LinkingGoal goal) { super(goal); subName = "LinkingGoal"; state.addObserver(this); } /** * Notify observers that this node's completion state has been changed. */ public void update(Observable obs, Object obj) { if(obs == state) { setChanged(); notifyObservers(state); } else { super.update(obs, obj); } } /** * Each distinct node type should know how to process itself, so this * method should be overridden in subclasses. * @param context A context w/helper functions required for processing */ public void verifierProcess(NegotiationContext context) { //this case should not occur } /** * Each distinct node type should know how to process itself, so this * method should be overridden in subclasses. * @param context A context w/helper functions required for processing */ public void opponentProcess(NegotiationContext context) { TTG graph = context.getGraph(); LinkingGoal goal = (LinkingGoal)getGoal(); FrontierManager f = context.getFrontier(); Entity verifier = goal.getVerifier(); EntityExpression subject = goal.getSubject(); HashSet solutions = new HashSet(); debug("linking-goal", "Opponent processing " + goal); // (1) O adds a linking solution edge G <--< , for // any A.r2 which is an element of sensitiveRole(O) or // A.r2 defined by a credentials in CsuperS(O) // collect the sensitive roles which match with r2 Iterator sensitiveRoles = f.getAckPolicy().getSensitiveRoles().iterator(); while(sensitiveRoles.hasNext()) { Role sensitive = (Role)sensitiveRoles.next(); if(sensitive.getName().equals(getTargetRoleName())) { solutions.add(sensitive); debug("linking-goal", "found sensitive role = " + sensitive); } } // add the roles (r2) where it is definied by a credential Iterator defined = f.getCredentialsDefiningRole(getTargetRoleName()); if(!defined.hasNext()) { debug("linking-goal", "no credentials foudn defining role: " + getTargetRoleName()); } while(defined.hasNext()) { StaticCredential credential = (StaticCredential)defined.next(); Role solution = credential.getDefinedRole(); solutions.add(solution); debug("linking-goal", "found matching r2 = " + solution); } // iterate through the solution and add the linking solution edges Iterator i = solutions.iterator(); while(i.hasNext()) { try { Role solution = (Role)i.next(); TrustTarget child = new TrustTarget(verifier, solution, subject); graph.addLinkingSolutionEdge(goal, child); } catch(Exception ex) { ex.printStackTrace(); } } // (2) O can mark this node opponent-processed only after (1) is done. graph.setOpponentProcessed(goal); } public void addLinkingImplicationEdges(TrustTarget target) { NegotiationContext context = getContext(); FrontierManager fm = context.getFrontier(); Entity v = getVerifier(); Entity b = ((Role)target.getTargetRole()).getBase(); TTG graph = getContext().getGraph(); Iterator i = parents.values().iterator(); while(i.hasNext()) { try { LinkTTNode parent = (LinkTTNode)i.next(); RoleName r1 = parent.getFirstRole().getName(); boolean subjectTraceable = fm.isSubjectTraceable(r1); if(context.getSelf().equals(getVerifier())) { // if we're the verifier if(!subjectTraceable) { // check r1 that is not subject traceable TrustTarget parentTarget = (TrustTarget)parent.getGoal(); TrustTarget child = new TrustTarget(v, parent.getFirstRole(), b); graph.addLinkingImplicationEdge(parentTarget, child); } } else { // else we are the opponent if(subjectTraceable) { // check r1 that is not subject traceable TrustTarget parentTarget = (TrustTarget)parent.getGoal(); TrustTarget child = new TrustTarget(v, parent.getFirstRole(), b); graph.addLinkingImplicationEdge(parentTarget, child); } } } catch(Exception ex) { ex.printStackTrace(); } } } /** * A linking goal uses this interface to act as a monitor for its own * completion state and to add linking-implication edges */ public TTGNodeSet receive(TrustTarget target, SatisfactionState state) { // a satisfied linking solution does step 2 in linked role processing if(state.getState() == SatisfactionState.SATISFIED) { debug("linking-goal", "received SATISFIED from " + target); addLinkingImplicationEdges(target); } // Just in case we get unknown satisfaction state propagation check //for it here to make certain we have an accurate completion count if(state.getState() != SatisfactionState.UNKNOWN) { completionCount++; if(completionCount <= children.size()) { this.state.setComplete(true); } } // if this node is complete, we should notify the parent(s) if(isComplete()) { Iterator i = parents.values().iterator(); notifyObservers(this.state); while(i.hasNext()) { LinkTTNode parent = (LinkTTNode)i.next(); parent.receive((LinkingGoal)getGoal(), new CompletionState(true) ); } } return new TTGNodeSet(); } public boolean isComplete() { return state.isComplete(); } /** convenience method for extracting the target role name for this node */ public RoleName getTargetRoleName() { return ((LinkingGoal)getGoal()).getTargetRoleName(); } public String toXML() { // Add node state here (eg. in/complete, etc.) StringBuffer state = new StringBuffer("state=\""); state.append(this.state); // Add linking solutions if any */ return toXML(state.toString(), ""); } }