[31b67d5] | 1 | package net.deterlab.abac; |
---|
| 2 | |
---|
| 3 | import org.apache.commons.collections15.*; |
---|
| 4 | import org.apache.commons.collections15.functors.*; |
---|
| 5 | |
---|
| 6 | import edu.uci.ics.jung.graph.*; |
---|
| 7 | import edu.uci.ics.jung.graph.event.*; |
---|
| 8 | import edu.uci.ics.jung.graph.util.*; |
---|
| 9 | |
---|
| 10 | import java.awt.geom.Point2D; |
---|
| 11 | import java.io.*; |
---|
| 12 | import java.util.*; |
---|
| 13 | |
---|
| 14 | /** |
---|
| 15 | * Represents a global graph of credentials in the form of principals and |
---|
| 16 | * attributes. |
---|
| 17 | */ |
---|
| 18 | public class CredentialGraph { |
---|
[a2a1555] | 19 | protected Graph<Role,Credential> g = null; |
---|
| 20 | protected java.util.Set<Credential> derived_edges = new HashSet<Credential>(); |
---|
| 21 | protected Query pq; |
---|
| 22 | protected boolean m_dirty; |
---|
[31b67d5] | 23 | |
---|
| 24 | public CredentialGraph() { |
---|
| 25 | /* create the graph */ |
---|
[a624bd1] | 26 | g = Graphs.<Role,Credential>synchronizedDirectedGraph( |
---|
| 27 | new DirectedSparseGraph<Role,Credential>()); |
---|
[31b67d5] | 28 | pq = new Query(g); |
---|
| 29 | } |
---|
| 30 | |
---|
| 31 | /** |
---|
[5bf874d] | 32 | * Returns a Query object which can be used to query the graph. This object |
---|
| 33 | * becomes invalid if the graph is modified. |
---|
[31b67d5] | 34 | */ |
---|
| 35 | public Query querier() { |
---|
[cac4c76] | 36 | derive_implied_edges(); |
---|
[31b67d5] | 37 | return new Query(g); |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | /** |
---|
| 41 | * Add a credential to the graph. |
---|
| 42 | */ |
---|
| 43 | public void add_credential(Credential cred) { |
---|
| 44 | Role tail = cred.tail(); |
---|
| 45 | Role head = cred.head(); |
---|
| 46 | |
---|
| 47 | /* explicitly add the vertices, otherwise get a null pointer exception */ |
---|
[88e139a] | 48 | if ( !g.containsVertex(tail)) |
---|
| 49 | g.addVertex(tail); |
---|
| 50 | if ( !g.containsVertex(tail)) |
---|
| 51 | g.addVertex(head); |
---|
[31b67d5] | 52 | |
---|
[88e139a] | 53 | if (!g.containsEdge(cred)) |
---|
| 54 | g.addEdge(cred, tail, head); |
---|
[cac4c76] | 55 | |
---|
| 56 | // add the prereqs of an intersection to the graph |
---|
| 57 | if (tail.is_intersection()) |
---|
| 58 | for (Role prereq : tail.prereqs()) |
---|
| 59 | g.addVertex(prereq); |
---|
[5bf874d] | 60 | |
---|
| 61 | m_dirty = true; |
---|
[31b67d5] | 62 | } |
---|
| 63 | |
---|
| 64 | /** |
---|
| 65 | * Remove a credential from the graph. |
---|
| 66 | */ |
---|
| 67 | public void remove_credential(Credential cred) { |
---|
[622bdbc] | 68 | if (g.containsEdge(cred)) |
---|
| 69 | g.removeEdge(cred); |
---|
[5bf874d] | 70 | m_dirty = true; |
---|
[31b67d5] | 71 | } |
---|
| 72 | |
---|
[88e139a] | 73 | /** |
---|
| 74 | * Add a role w/o an edge |
---|
| 75 | */ |
---|
| 76 | public void add_vertex(Role v) { |
---|
| 77 | if (!g.containsVertex(v)) { |
---|
| 78 | g.addVertex(v); |
---|
| 79 | m_dirty = true; |
---|
| 80 | } |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | public void remove_vertex(Role v) { |
---|
| 84 | if (g.containsVertex(v)) { |
---|
| 85 | g.removeVertex(v); |
---|
| 86 | m_dirty = true; |
---|
| 87 | } |
---|
| 88 | } |
---|
| 89 | |
---|
[31b67d5] | 90 | /** |
---|
| 91 | * Returns a collection of the credentials in the graph. |
---|
| 92 | */ |
---|
| 93 | public Collection<Credential> credentials() { |
---|
| 94 | Collection<Credential> creds = new HashSet<Credential>(); |
---|
| 95 | |
---|
[90f939f] | 96 | // only return creds with a cert: all others are derived edges |
---|
| 97 | for (Credential cred : g.getEdges()) |
---|
| 98 | if (cred.cert() != null) |
---|
[31b67d5] | 99 | creds.add(cred); |
---|
[90f939f] | 100 | |
---|
[31b67d5] | 101 | return creds; |
---|
| 102 | } |
---|
| 103 | |
---|
[88e139a] | 104 | public Collection<Role> roles() { |
---|
| 105 | return g.getVertices(); |
---|
| 106 | } |
---|
| 107 | |
---|
[31b67d5] | 108 | /** |
---|
[cac4c76] | 109 | * Derive the implied edges in the graph, according to RT0 derivation rules. |
---|
| 110 | * They are added to this graph. See "Distributed Credential Chain Discovery |
---|
| 111 | * in Trust Management" by Ninghui Li et al. for details. Note that a |
---|
| 112 | * derived linking edge can imply a new intersection edge and vice versa. |
---|
| 113 | * Therefore we iteratively derive edges, giving up when an iteration |
---|
| 114 | * produces 0 new edges. |
---|
| 115 | */ |
---|
[a2a1555] | 116 | protected synchronized void derive_implied_edges() { |
---|
[5bf874d] | 117 | // nothing to do on a clean graph |
---|
| 118 | if (!m_dirty) |
---|
| 119 | return; |
---|
| 120 | |
---|
| 121 | clear_old_edges(); |
---|
[cac4c76] | 122 | |
---|
| 123 | // iteratively derive links. continue as long as new links are added |
---|
| 124 | while (derive_links_iter() > 0) |
---|
| 125 | ; |
---|
[5bf874d] | 126 | m_dirty = false; |
---|
[cac4c76] | 127 | } |
---|
| 128 | |
---|
| 129 | /** |
---|
| 130 | * Single iteration of deriving implied edges. Returns the number of new |
---|
| 131 | * links added. |
---|
[31b67d5] | 132 | */ |
---|
[a2a1555] | 133 | protected int derive_links_iter() { |
---|
[cac4c76] | 134 | int count = 0; |
---|
[31b67d5] | 135 | |
---|
| 136 | /* for every node in the graph.. */ |
---|
[cac4c76] | 137 | for (Role vertex : g.getVertices()) { |
---|
| 138 | if (vertex.is_intersection()) { |
---|
| 139 | // for each prereq edge: |
---|
| 140 | // find set of principals that have the prereq |
---|
| 141 | // find the intersection of all sets (i.e., principals that satisfy all prereqs) |
---|
| 142 | // for each principal in intersection: |
---|
| 143 | // add derived edge |
---|
| 144 | |
---|
| 145 | Set<Role> principals = null; |
---|
| 146 | |
---|
| 147 | for (Role prereq : vertex.prereqs()) { |
---|
| 148 | Set<Role> cur_principals = pq.find_principals(prereq); |
---|
| 149 | |
---|
| 150 | if (principals == null) |
---|
| 151 | principals = cur_principals; |
---|
| 152 | else |
---|
| 153 | // no, they couldn't just call it "intersection" |
---|
| 154 | principals.retainAll(cur_principals); |
---|
| 155 | |
---|
| 156 | if (principals.size() == 0) |
---|
| 157 | break; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | // add em |
---|
| 161 | for (Role principal : principals) |
---|
| 162 | if (add_derived_edge(vertex, principal)) |
---|
| 163 | ++count; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | else if (vertex.is_linking()) { |
---|
| 167 | // make the rest of the code a bit clearer |
---|
| 168 | Role A_r1_r2 = vertex; |
---|
[31b67d5] | 169 | |
---|
[cac4c76] | 170 | Role A_r1 = new Role(A_r1_r2.A_r1()); |
---|
| 171 | String r2 = A_r1_r2.r2(); |
---|
[31b67d5] | 172 | |
---|
[cac4c76] | 173 | /* locate the node A.r1 */ |
---|
| 174 | if (!g.containsVertex(A_r1)) continue; /* boring: nothing of the form A.r1 */ |
---|
[31b67d5] | 175 | |
---|
[cac4c76] | 176 | /* for each B that satisfies A_r1 */ |
---|
| 177 | for (Role principal : pq.find_principals(A_r1)) { |
---|
| 178 | Role B_r2 = new Role(principal + "." + r2); |
---|
| 179 | if (!g.containsVertex(B_r2)) continue; |
---|
[31b67d5] | 180 | |
---|
[cac4c76] | 181 | if (add_derived_edge(A_r1_r2, B_r2)) |
---|
| 182 | ++count; |
---|
| 183 | } |
---|
[31b67d5] | 184 | } |
---|
| 185 | } |
---|
[cac4c76] | 186 | |
---|
| 187 | return count; |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | /** |
---|
| 191 | * Add a derived edge in the graph. Returns true only if the edge does not |
---|
| 192 | * exist. |
---|
| 193 | */ |
---|
[a2a1555] | 194 | protected boolean add_derived_edge(Role head, Role tail) { |
---|
[cac4c76] | 195 | // edge exists: return false |
---|
| 196 | if (g.findEdge(tail, head) != null) |
---|
| 197 | return false; |
---|
| 198 | |
---|
| 199 | // add the new edge |
---|
| 200 | Credential derived_edge = new Credential(head, tail); |
---|
| 201 | derived_edges.add(derived_edge); |
---|
| 202 | g.addEdge(derived_edge, tail, head); |
---|
| 203 | |
---|
| 204 | return true; |
---|
[31b67d5] | 205 | } |
---|
| 206 | |
---|
| 207 | /** |
---|
| 208 | * Clear the derived edges that currently exist in the graph. This is done |
---|
| 209 | * before the edges are rederived. The derived edges in filtered graphs are |
---|
| 210 | * also cleared. |
---|
| 211 | */ |
---|
[622bdbc] | 212 | protected void clear_old_edges() { |
---|
| 213 | for (Credential i: derived_edges) |
---|
[31b67d5] | 214 | g.removeEdge(i); |
---|
| 215 | derived_edges = new HashSet<Credential>(); |
---|
| 216 | } |
---|
| 217 | } |
---|