AllocationPolicy | Line # 134 | 149 | 55 | 80.9% |
0.8093385
|
(1) | |||
Result | |||
0.5175097
|
issrg.test.ds.TestDS.testIssuing issrg.test.ds.TestDS.testIssuing | 1 PASS | |
1 | /* | |
2 | * Copyright (c) 2000-2005, University of Salford | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * | |
8 | * Redistributions of source code must retain the above copyright notice, this | |
9 | * list of conditions and the following disclaimer. | |
10 | * | |
11 | * Redistributions in binary form must reproduce the above copyright notice, | |
12 | * this list of conditions and the following disclaimer in the documentation | |
13 | * and/or other materials provided with the distribution. | |
14 | * | |
15 | * Neither the name of the University of Salford nor the names of its | |
16 | * contributors may be used to endorse or promote products derived from this | |
17 | * software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Copyright (c) 2006, University of Kent | |
34 | * All rights reserved. | |
35 | * | |
36 | * Redistribution and use in source and binary forms, with or without | |
37 | * modification, are permitted provided that the following conditions are met: | |
38 | * | |
39 | * Redistributions of source code must retain the above copyright notice, this | |
40 | * list of conditions and the following disclaimer. | |
41 | * | |
42 | * Redistributions in binary form must reproduce the above copyright notice, | |
43 | * this list of conditions and the following disclaimer in the documentation | |
44 | * and/or other materials provided with the distribution. | |
45 | * | |
46 | * 1. Neither the name of the University of Kent nor the names of its | |
47 | * contributors may be used to endorse or promote products derived from this | |
48 | * software without specific prior written permission. | |
49 | * | |
50 | * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
51 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
52 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
53 | * PURPOSE ARE DISCLAIMED. | |
54 | * | |
55 | * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
56 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
57 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
58 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
59 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
60 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
61 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
62 | * POSSIBILITY OF SUCH DAMAGE. | |
63 | * | |
64 | * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE | |
65 | * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS | |
66 | * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS | |
67 | * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH | |
68 | * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH | |
69 | * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY | |
70 | * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE | |
71 | * SERIOUS FAULTS, IN THIS SOFTWARE. | |
72 | * | |
73 | * 5. This license is governed, except to the extent that local laws | |
74 | * necessarily apply, by the laws of England and Wales. | |
75 | */ | |
76 | ||
77 | package issrg.pba.rbac.policies; | |
78 | ||
79 | import issrg.pba.repository.AuthzTokenRepository; | |
80 | import issrg.pba.Credentials; | |
81 | import issrg.pba.DelegatableToken; | |
82 | import issrg.pba.ParsedToken; | |
83 | import issrg.utils.repository.TokenLocator; | |
84 | import issrg.pba.PbaException; | |
85 | import issrg.pba.rbac.Clock; | |
86 | import issrg.pba.rbac.RuleComparator; | |
87 | import issrg.pba.rbac.CustomisePERMIS; | |
88 | import issrg.pba.rbac.LDAPDNPrincipal; | |
89 | import issrg.pba.rbac.SetOfSubsetsCredentials; | |
90 | import java.util.*; | |
91 | import java.util.Vector; | |
92 | import issrg.utils.repository.Entry; | |
93 | import issrg.simplePERMIS.SimplePERMISAuthzTokenRepository; | |
94 | ||
95 | import org.apache.log4j.*;// added for logging | |
96 | ||
97 | ||
98 | ||
99 | /** | |
100 | * This class represents an Allocation and Delegation Policy. Its responsibility | |
101 | * is to return a set of Credentials (Roles in Permis) that have been assigned | |
102 | * to the subject in accordance with the (Role) Assignment policy and delegation | |
103 | * rules. | |
104 | * | |
105 | * <p>This class is quite abstract and can be used for many other projects, | |
106 | * even non-role based, and non-AC based, because it operates on abstract | |
107 | * authorisation tokens and credentials. | |
108 | * | |
109 | * <p>The delegation model assumed is: the policy states a number of trusted | |
110 | * Sources of Authority, along with the specification of what they can delegate | |
111 | * and to whom; these entities can delegate their powers or subset of it | |
112 | * (i.e. the Credentials specified in the policy or the subset of it) to | |
113 | * the other entities that must be from their Subject Domain. This way a | |
114 | * delegation chain is established from one of the Sources of Authority (SOAs) | |
115 | * to the end users. | |
116 | * | |
117 | * <p>AllocationPolicy can recursively trace the delegation | |
118 | * chains by looking up the Authorisation Tokens of the Issuer of each | |
119 | * Authorisation Token available to it, until one of the SOAs is reached. | |
120 | * To validate the chain, the same rule is applied on each iteration: the | |
121 | * subordinate authority can have the same or less power as the superior | |
122 | * authority; so a subordinate authority has the intersection of the Credentials | |
123 | * that it has in the Authorisation Tokens with the Credentials of the superior | |
124 | * authority, the Subject | |
125 | * Domain is an intersection of the superior's Subject Domain and the | |
126 | * subordinate's Subject Domain excluding the subordinate himself, the | |
127 | * delegation depth is at most one less than the delegation depth of the | |
128 | * superior authority. | |
129 | * | |
130 | * @author A Otenko | |
131 | * @version 0.1 | |
132 | */ | |
133 | ||
134 | public class AllocationPolicy { | |
135 | ||
136 | // * <p>TODO: implement something like CacheMaintainer object for efficiency. | |
137 | ||
138 | protected Clock theClock = CustomisePERMIS.getSystemClock(); // this is needed to maintain the Cache properly - we don't rely on System time directly | |
139 | ||
140 | java.util.Map assignmentRules = null; | |
141 | Subtree coverageDomain = null; | |
142 | RuleComparator comparator = null; | |
143 | ||
144 | Logger logger = Logger.getLogger("issrg.pba.rbac.policies.AllocationPolicy"); | |
145 | ||
146 | 0 | protected AllocationPolicy(){} |
147 | ||
148 | /** | |
149 | * The constructor builds a policy out of assignment Rules and the | |
150 | * reference to | |
151 | * the AuthTokenParser. The constructor updates the rules in such a way, | |
152 | * that | |
153 | * the SOA name becomes case insensitive. | |
154 | * | |
155 | * <p>The rule set contains a special rule, which is the coverage domain of | |
156 | * the whole AllocationPolicy. This rule is found by using Subtree.class as | |
157 | * the key, and the value is assumed to be a Subtree. | |
158 | * | |
159 | * @param assignmentRules is a Map of Vectors of AssignmentRule objects; the | |
160 | * key for each AssignmentRule collection is the SOA's DN | |
161 | * @param comparator defines the preference in validation of Authorisation | |
162 | * Tokens, so that the most relevant ones are validated first, and the | |
163 | * less relevant or irrelevant ones are not validated at all; if it is | |
164 | * null, the default RuleComparator will be used as defined in | |
165 | * CustomisePERMIS.getComparator() | |
166 | * | |
167 | * @see issrg.pba.rbac.CustomisePERMIS#getComparator | |
168 | */ | |
169 | 25 | public AllocationPolicy(java.util.Map assignmentRules, RuleComparator comparator) { |
170 | 25 | coverageDomain = (Subtree)(assignmentRules.remove(Subtree.class)); |
171 | ||
172 | 25 | this.assignmentRules = assignmentRules; |
173 | 25 | Object [] keys = assignmentRules.keySet().toArray(); |
174 | ||
175 | 63 | for (int i=keys.length; i-->0;){ |
176 | 38 | assignmentRules.put(keys[i].toString().toUpperCase(), assignmentRules.remove(keys[i])); |
177 | } | |
178 | ||
179 | 25 | if (comparator==null) comparator = CustomisePERMIS.getComparator(); |
180 | 25 | this.comparator = comparator; |
181 | } | |
182 | ||
183 | /** | |
184 | * This constructor builds an AllocationPolicy with the default | |
185 | * RuleComparator; this is a shortcut to AllocationPolicy(assignmentRules, null) | |
186 | * See that constructor for details of the meaning. | |
187 | * | |
188 | * @see AllocationPolicy(java.util.Map,RuleComparator) | |
189 | */ | |
190 | 25 | public AllocationPolicy(java.util.Map assignmentRules){ |
191 | 25 | this(assignmentRules, null); |
192 | } | |
193 | ||
194 | /** | |
195 | * This method does the allocation. It picks the Authorisation Tokens from | |
196 | * the | |
197 | * given Authorisation Token Repository (assuming it returns only valid | |
198 | * tokens), and uses AuthTokenParser to retrieve the credentials. After that | |
199 | * it applies each Assignment Rule to ensure that the credentials have been | |
200 | * assigned | |
201 | * according to the policy; all credentials that do not comply to the policy | |
202 | * are discarded | |
203 | * and a credentials object containing only complying credentials is | |
204 | * returned. | |
205 | * | |
206 | * <p>Note that if the User does not match any Subject Domain, an exception | |
207 | * will | |
208 | * be thrown. | |
209 | * | |
210 | * <p>X.509 semantics: It picks all recognisable Roles | |
211 | * from the given set of Attribute Certificates, then it exercises the | |
212 | * actual Role assignment: looks | |
213 | * what roles from the given set of ACs could have been delegated by the | |
214 | * AC | |
215 | * issuer. The latter step involves RoleAssignmentPolicy interpretation, | |
216 | * with | |
217 | * SubjectDomain matching, Role matching, SOA matching and the delegation | |
218 | * depth matching. The resulting Role will contain validity, as calculated | |
219 | * by combining the AC Validity time and Validity restrictions in the | |
220 | * RoleAssignmentPolicy. | |
221 | * | |
222 | * <p>The issuer name is case insensitive. | |
223 | * | |
224 | * <p>End of recursion:<br> | |
225 | * 0. All the roles have been granted by the SOA (which should have been | |
226 | * defined in the SOAPolicy)<br> | |
227 | * 1. The delegator is already being calculated in this recursion (somewhere | |
228 | * down the stack). (Thus eliminating delegation loops; such delegations are | |
229 | * invalidated; depending on the role caching mechanism, a flag can be set | |
230 | * the role assignment to be calculated later)<br> | |
231 | * 2. No ACs obtained for the delegator.<br> | |
232 | * | |
233 | * @param who is the user identifier; it contains either user DN, or the | |
234 | * PKC | |
235 | * Issuer DN+Serial Number; it is used when performing SubjectDomain | |
236 | * match and to retrieve the Authorisation Tokens of the Subject | |
237 | * @param acR is the repository with the Authorisation Tokens the user has | |
238 | * got; | |
239 | * it is assumed the signature has already been verified, when the | |
240 | * Authorisation Tokens | |
241 | * are retrieved; if null, no AuthorisationTokens can be obtained for | |
242 | * the Subject, so only public access can be granted at decision time | |
243 | * (an empty set of Credentials will be returned) | |
244 | */ | |
245 | 1548 | public issrg.pba.Credentials getCredentials(TokenLocator who, AuthzTokenRepository acR) throws PbaException{ |
246 | ||
247 | 1548 | Vector holders = new Vector(); |
248 | 1548 | long start = 0; |
249 | 1548 | long end = 0; |
250 | 0 | if (logger.isDebugEnabled())logger.debug("getCredentials called with the following parameters :"); |
251 | 0 | if (logger.isDebugEnabled())logger.debug("token locator = " + who.getEntry().getEntryName().getName()); |
252 | 0 | if (logger.isDebugEnabled())logger.debug("Auth token Repository = " + acR.toString()); |
253 | ||
254 | ||
255 | 1548 | holders.add(who.getEntry()); |
256 | ||
257 | ||
258 | ||
259 | 1548 | if (coverageDomain==null || !coverageDomain.contains(who.getEntry())){ |
260 | 0 | if (logger.isDebugEnabled())logger.debug("User is out of the Subject Domain"); |
261 | 199 | throw new PbaException("User is out of the Subject Domain"); |
262 | } | |
263 | ||
264 | 1349 | try{ |
265 | 1349 | java.util.Vector tmp; |
266 | 1349 | Entry issuer; |
267 | 1349 | issrg.pba.Credentials sumCreds = new SetOfSubsetsCredentials(); //this is the total credentials of "who" |
268 | ||
269 | 1349 | ParsedToken[] a; |
270 | 1349 | if (acR != null){ // acR may be null in some cases - i.e. if PERMIS was initialised in a weird way; empty set of Credentials will grant public access |
271 | ||
272 | 1348 | a = acR.getParsedAuthTokens(who); |
273 | ||
274 | 1348 | if (a != null) { // anything has been retrieved |
275 | 3024 | for (int i=a.length; i-->0; ) { |
276 | 1682 | ParsedToken token = a[i]; |
277 | 0 | if (logger.isDebugEnabled())logger.debug("token " + i+1 + " = " +token.getCredentials().toString()); |
278 | 1682 | if (token==null) { |
279 | 0 | if (logger.isDebugEnabled())logger.debug("token " + i+1 + " = null"); |
280 | 0 | continue; |
281 | } | |
282 | ||
283 | 1682 | if (!who.getEntry().getEntryName().equals(token.getHolder().getEntryName())) { |
284 | 0 | if (logger.isDebugEnabled())logger.debug("token " + i+1 + " = Entry name does not match " + who.getEntry().getEntryName()); |
285 | 0 | continue; // ignore this AC |
286 | } | |
287 | ||
288 | 1682 | TokenLocator issuerTokenLocator = token.getIssuerTokenLocator(); |
289 | ||
290 | 0 | if (logger.isDebugEnabled())logger.debug("token " + i+1 + " issuer = " + token.getIssuerTokenLocator().getEntry().getEntryName().getName() ); |
291 | 1682 | issrg.pba.Credentials credentials = token.getCredentials(); |
292 | 0 | if (logger.isDebugEnabled())logger.debug("token " + i+1 + " credentials = " + token.getCredentials().toString() ); |
293 | ||
294 | 1682 | Credentials o = validate(who.getEntry(), issuerTokenLocator, credentials, acR, holders); |
295 | 1682 | if ((o != null)){ |
296 | 0 | if (logger.isDebugEnabled())logger.debug("token " + o.toString() + " is added" ); |
297 | 1682 | sumCreds = sumCreds.union(o); //sumCreds is added-up by the valid credentials of the current AC |
298 | } | |
299 | } | |
300 | } | |
301 | 6 | else logger.debug("nothing has been retrieved"); |
302 | } | |
303 | ||
304 | 1349 | return sumCreds; |
305 | }catch (PbaException e){ | |
306 | 0 | throw e; |
307 | }catch (Throwable th){ | |
308 | 0 | throw new PbaException("Internal error", th); |
309 | } | |
310 | } | |
311 | ||
312 | /** | |
313 | * This method checks if there is a loop in the delegation chain. This kind | |
314 | * of loop assignment can happen when issuer uses ACM tool to issue ACs. | |
315 | * The issuer of an AC in a delegation chain should not be a holder in that | |
316 | * delegation chain. | |
317 | * | |
318 | * @param holders - a Vector of holder Entry objects discovered along the | |
319 | * chain | |
320 | * @param issuer - the Entry that should not be among the holders | |
321 | * | |
322 | * @return true, if the issuer is among the holders; false otherwise | |
323 | */ | |
324 | 403 | private boolean checkLoopAssignment(Vector holders, Entry issuer) { |
325 | 403 | int size = holders.size(); |
326 | 829 | for (int i = 0; i < size; i++) { |
327 | 426 | Entry e = (Entry) holders.get(i); |
328 | 0 | if (e.getEntryName().getName().equals(issuer.getEntryName().getName())) return true; |
329 | } | |
330 | 403 | return false; |
331 | } | |
332 | ||
333 | /** | |
334 | * This method validates a requested set of Credentials. | |
335 | * | |
336 | * @param holder is the holder Entry. It is matched against the Subject | |
337 | * Domain of the issuer's RAR | |
338 | * @param issuerTokenLocator specifies the location of the issuer's | |
339 | * Authorisation Tokens | |
340 | * @param credentials is the credentials asserted by the holder and issued | |
341 | * by the issuer identified by issuerTokenLocator | |
342 | * @param acR is the default repository for the Authorisation Tokens; if | |
343 | * null, the Authorisation Token Repository mentioned in the | |
344 | * issuerTokenLocator will be used; if neither is specified, the issuer's | |
345 | * Authorisation Tokens cannot be found and the assignment will only be | |
346 | * validated using the RARs available in the policy | |
347 | * @param holders is the vector that stores list of holders on the | |
348 | * delegation path; it is used for detecting loops in assignment | |
349 | * | |
350 | * @return validated credentials | |
351 | */ | |
352 | 1699 | public Credentials validate(Entry holder, TokenLocator issuerTokenLocator, Credentials credentials, AuthzTokenRepository acR, Vector holders) throws PbaException { |
353 | //@Gansen : The following 3 lines were the original code. We keep a copy here in case of bugs | |
354 | 1699 | Object o = validate(holder, issuerTokenLocator, (Object) credentials, acR, holders); |
355 | 1699 | if (o instanceof Credentials) return (Credentials)o; else { |
356 | 0 | throw new PbaException("Validating Credentials failed: Credentials was expected, but "+o.getClass()+" found"); |
357 | } | |
358 | // | |
359 | // boolean bValidationSuccess=false; | |
360 | // Object o = validate(holder, issuerTokenLocator, (Object) credentials, acR, holders); | |
361 | // | |
362 | // //there are 2 ways that this function failed. | |
363 | // //the first is that, it return a set of rars, | |
364 | // //the second one is that, it returns an empty set of credentials | |
365 | // if(o instanceof Credentials ){//returns a set of credentials | |
366 | // //try to test if the set is empty or not | |
367 | // Credentials result=(Credentials) o; | |
368 | // } | |
369 | // | |
370 | // if (o instanceof Credentials) return (Credentials)o; else { | |
371 | // throw new PbaException("Validating Credentials failed: Credentials was expected, but "+o.getClass()+" found"); | |
372 | // } | |
373 | ||
374 | ||
375 | } | |
376 | ||
377 | /** | |
378 | * This function validates a requested RAR. | |
379 | * | |
380 | * @param holder is the Entry of the holder of the asserted RAR | |
381 | * @param issuerTokenLocator specifies the location of the issuer's | |
382 | * Authorisation Tokens | |
383 | * @param rule is the RAR asserted by the holder and issued by the issuer | |
384 | * identified by issuerTokenLocator | |
385 | * @param acR is the default repository for the Authorisation Tokens; if | |
386 | * null, the Authorisation Token Repository mentioned in the | |
387 | * issuerTokenLocator will be used; if neither is specified, the issuer's | |
388 | * Authorisation Tokens cannot be found and the assignment will only be | |
389 | * validated using the RARs available in the policy | |
390 | * @param holders is the vector that stores list of holders on the | |
391 | * delegation path; it is used for detecting loops in assignment | |
392 | * | |
393 | * @return a vector of validated RARs, each element of which is an | |
394 | * AssignmentRule | |
395 | */ | |
396 | 447 | public Vector validate(Entry holder, TokenLocator issuerTokenLocator, AssignmentRule rule, AuthzTokenRepository acR, Vector holders) throws PbaException { |
397 | 447 | Object o = validate(holder, issuerTokenLocator, (Object) rule, acR, holders); |
398 | 447 | if (o instanceof Vector) return (Vector)o; else { |
399 | 0 | throw new PbaException("Validating RARs failed: Vector of RARs was expected, but "+o.getClass()+" found"); |
400 | } | |
401 | } | |
402 | ||
403 | /** | |
404 | * This function validates a RAR or Credentials. It will retrieve the | |
405 | * issuer's Authorisation Tokens from a repository and validate | |
406 | * the requested object. Note that issuer's Authorisation Tokens will be | |
407 | * sorted according to suitability for the requested object using the | |
408 | * RuleComparator specified at construction time and is | |
409 | * validated one | |
410 | * by one until the constrained result is "good enough" (the criterion is | |
411 | * specified by the RuleComparator, too). | |
412 | * | |
413 | * <p>The logic of it is: "discover the chain from user to one of the SOAs, | |
414 | * then validate the chain back from SOA to user". Discovering | |
415 | * the chain | |
416 | * starts with the end entity and stops with the SOA. It gets the asserted | |
417 | * rules of intermediate | |
418 | * issuers from their attributes and tries to recursively validate these | |
419 | * rules. To | |
420 | * validate a rule, it has to get the valid rules of the issuer of this | |
421 | * rule. | |
422 | * | |
423 | * <p>At the last step, it gets rules of SOA out of the policy (which are | |
424 | * valid, since they | |
425 | * come from the policy, do not | |
426 | * check) and validates the rules issued by the SOA to subordinates. Then | |
427 | * the recursion comes back down the chain from SOA to end entity and | |
428 | * validates the | |
429 | * rules on its way and finally validates rules/Credentials of the end | |
430 | * entity. | |
431 | * | |
432 | * <p>First of all, the function get the issuer's valid RARs | |
433 | * (validIssuerRARs) from the assginmentRules object. This object comes | |
434 | * from the policy and it stores the valid RARs of each SOA. | |
435 | * <ol> | |
436 | * <li>If the validIssuerRARs is not null then the issuer of the holder's | |
437 | * attribute is a SOA</li> | |
438 | * <ol> | |
439 | * <li>With each issuer's RAR, constrain (allocate) the assertion and | |
440 | * union the results</li> | |
441 | * <li>After the above step, the results is returned because a SOA is | |
442 | * the issuer</li> | |
443 | * </ol> | |
444 | * <li>If the validIssuerRARs is null then the issuer of the holder's | |
445 | * attribute is not a SOA</li> | |
446 | * <ol> | |
447 | * <li>Get the issuer's parsed tokens from issuerTokenLocator and put them | |
448 | * on the issuerTokens vector (after some checks)</li> | |
449 | * <li>If the issuerTokens is empty then the issuer does not have any | |
450 | * attribute so the assertion can not be valid. Return with empty | |
451 | * object result.<br> | |
452 | * Otherwise, go to the next step.</li> | |
453 | * <li>Call the Comparator object and sort the issuerTokens according to | |
454 | * the assertion and the sorting rules in the comparator object.</li> | |
455 | * <li>For each issuer's parsed token, do the following: | |
456 | * <ol> | |
457 | * <li>If the token is not a delegateable token, throw it away and continue | |
458 | * with the next token</li> | |
459 | * <li>Get the assignment rule (RAR) from the current DelegatableToken.</li> | |
460 | * <li>If the issuer (issuerToken.getHolder()) is one of the holder in the | |
461 | * holders vector then there is a loop assignment. Throw the token | |
462 | * away and continue with the next token</li> | |
463 | * <li>Add the issuer to the holders vector. The issuer now is one of the | |
464 | * entry in the delegation chain.</li> | |
465 | * <li>Validate the issuer's RAR. This step will make a recursive call. | |
466 | * Get the vector of valid RARs. The result here is a vector of RARs | |
467 | * because one issuer may have some valid attributes and each valid | |
468 | * attribute may result one valid RAR</li> | |
469 | * <li>One delegation chain from the issuer to one of the SOA has been | |
470 | * validated. Remove the issuer from the holders vector.<br> | |
471 | * Note: just one (yes, one) delegation chain from the issuer to one | |
472 | * of the SOA has been validated.</li> | |
473 | * <li>With the valid vector of RARs of the issuer, constrain the request | |
474 | * to get the valid credentials or RARs</li> | |
475 | * <li>Use the comparator to check that the valid result is good enough | |
476 | * for the request. If it is ok, return the results, otherwise, | |
477 | * continue with the next issuer's parsed token. The | |
478 | * isSufficient method of the default RuleComparator is very simple - | |
479 | * if the result is not empty then it is fine. What is "enough" | |
480 | * depends on purpose and it can be modified and plugged in the Permis | |
481 | * by the comparator object via the CustomisePERMIS class.</li> | |
482 | * </ol> | |
483 | * </ol> | |
484 | * </ol> | |
485 | * | |
486 | * @param holder is the Entry of the holder of the asserted RAR | |
487 | * @param issuerTokenLocator specifies the location of the issuer's | |
488 | * Authorisation Tokens | |
489 | * @param assertion is either the RAR or Credentials asserted by the holder | |
490 | * and issued by the issuer | |
491 | * identified by issuerTokenLocator | |
492 | * @param acR is the default repository for the Authorisation Tokens; if | |
493 | * null, the Authorisation Token Repository mentioned in the | |
494 | * issuerTokenLocator will be used; if neither is specified, the issuer's | |
495 | * Authorisation Tokens cannot be found and the assignment will only be | |
496 | * validated using the RARs available in the policy | |
497 | * @param holders is the vector that stores list of holders on the | |
498 | * delegation path; it is used for detecting loops in assignment | |
499 | * | |
500 | * @return an Object, the type of which depends on the type of assertion; | |
501 | * if the assertion is Credentials, the result is a Credentials; | |
502 | * otherwise it is Vector of valid RARs, each element being an | |
503 | * AssignmentRule | |
504 | * | |
505 | * @see issrg.pba.rbac.CustomisePERMIS | |
506 | * @see issrg.pba.rbac.xmlpolicy.DefaultRuleComparator | |
507 | */ | |
508 | 2146 | private Object validate(Entry holder, TokenLocator issuerTokenLocator, Object assertion, AuthzTokenRepository acR, Vector holders) throws PbaException { |
509 | 2146 | if (Credentials.class.isAssignableFrom(assertion.getClass())) { |
510 | 1699 | logger.debug("to validate "+((Credentials)assertion).toString()); |
511 | } | |
512 | 2146 | Date date = new Date(); |
513 | 2146 | long start = date.getTime(); |
514 | 2146 | long end = 0; |
515 | 2146 | issrg.pba.Credentials emptyCred = new SetOfSubsetsCredentials(); |
516 | //sumup is used to store the valid credentials. If the assertion is credentials then this function will return the sumup credentials | |
517 | 2146 | Credentials sumup = assertion instanceof Credentials ? new SetOfSubsetsCredentials() : null; |
518 | //validRARs stores the valid RARs. If the assertion is a RAR then this function will return the validRARs vector | |
519 | 2146 | Vector validRARs = assertion instanceof Credentials ? null : new Vector(); |
520 | 2146 | Object result = assertion instanceof Credentials ? (Object)sumup : (Object)validRARs; |
521 | 2146 | Vector validIssuerRARs = new Vector(); |
522 | //@TuanAnh: check if there is more than one SOA in the policy. | |
523 | //If there is more than one then set the flag in the DefaultRuleComparator to true | |
524 | 2146 | if (assignmentRules.keySet().size() > 1) comparator.setFlag(true); |
525 | 2146 | Vector tmp = (java.util.Vector)assignmentRules.get(issuerTokenLocator.getEntry().getEntryName().getName().toUpperCase()); |
526 | 2146 | if (tmp!=null) validIssuerRARs.addAll(tmp); // add any rules given to the specific SOA, if any |
527 | ||
528 | 2146 | tmp = (java.util.Vector)assignmentRules.get(""); |
529 | 2146 | if (tmp!=null) validIssuerRARs.addAll(tmp); // add any rules given to "ANY" SOA, if any rules are present |
530 | ||
531 | 2146 | ParsedToken[] issuerToks=null; |
532 | 2146 | Vector issuerTokens = new Vector(); |
533 | 2146 | AssignmentRule assertRule = null; |
534 | 2146 | AssignmentRule validRule = null; |
535 | 2146 | try { |
536 | 2146 | if (!validIssuerRARs.isEmpty()) { |
537 | 5515 | for (int i = 0; i < validIssuerRARs.size(); i++) { |
538 | 3939 | AssignmentRule validSOARAR = (AssignmentRule) validIssuerRARs.get(i); |
539 | 3939 | if (assertion instanceof Credentials) { |
540 | 2789 | Credentials credentials = validSOARAR.allocate(holder,(Credentials) assertion); |
541 | 2789 | if ((credentials != null) && !(credentials.equals(emptyCred))) { |
542 | 891 | sumup = sumup.union(credentials); |
543 | } | |
544 | 2789 | result = sumup; |
545 | } else { | |
546 | 1150 | Vector rules = validSOARAR.allocate(holder, (AssignmentRule)assertion); |
547 | //rules is always not null | |
548 | 1150 | validRARs.addAll(rules); |
549 | 1150 | result = validRARs; |
550 | } | |
551 | ||
552 | } | |
553 | ||
554 | 1576 | if (!comparator.isSufficient(null, null, assertion, result)) validIssuerRARs=new Vector(); |
555 | 570 | } else logger.debug("no RARs in the policy"); |
556 | ||
557 | 2146 | if (validIssuerRARs.isEmpty()) { // there were no RARs in the policy, |
558 | // or applying them wasn't sufficient - look for Authorisation Tokens of the Issuer | |
559 | ||
560 | 876 | if (acR!=null) issuerToks = acR.getParsedAuthTokens(issuerTokenLocator); |
561 | ||
562 | 876 | if (issuerToks != null) { |
563 | ||
564 | 1083 | for (int i = 0; i < issuerToks.length; i++) { |
565 | 556 | ParsedToken tok = issuerToks[i]; |
566 | 0 | if (tok==null) continue; |
567 | ||
568 | 0 | if (!issuerTokenLocator.getEntry().getEntryName().equals(tok.getHolder().getEntryName())) continue; |
569 | 556 | issuerTokens.add(tok); |
570 | } | |
571 | 349 | } else logger.debug("no issuer token"); |
572 | } | |
573 | ||
574 | 2146 | if ((!issuerTokens.isEmpty())) { |
575 | ||
576 | 527 | ParsedToken[] issuerOrderedTokens = comparator.predict(assertion, issuerTokens, holder); |
577 | //after predict function, issuerToken should be a DelegatableToken | |
578 | 527 | no_more_tokens: |
579 | 540 | for (int i = 0; i < issuerOrderedTokens.length; i++) { |
580 | 403 | ParsedToken issuerToken = issuerOrderedTokens[i]; |
581 | 0 | if (!(issuerToken instanceof DelegatableToken)) continue; |
582 | 403 | DelegatableToken issuerDT = (DelegatableToken) issuerToken; |
583 | 403 | AssignmentRule aRule = new AssignmentRule(issuerDT.getSubjectDomain(), issuerDT.getDepth(), issuerDT.getDelegateableCredentials()); |
584 | ||
585 | 403 | if ((issuerDT.getDepth()>-1 && issuerDT.getDepth()+1<holders.size()) // ignore the Tokens whose Delegation Depth is smaller than the length of the rest of the chain |
586 | 0 | || checkLoopAssignment(holders, issuerToken.getHolder())) continue; |
587 | ||
588 | 403 | holders.add(issuerTokenLocator.getEntry()); |
589 | 403 | Vector v = validate(issuerToken.getHolder(), issuerToken.getIssuerTokenLocator(), aRule, acR, holders); |
590 | 403 | holders.remove(issuerTokenLocator.getEntry()); |
591 | 797 | for (int j = 0; j < v.size(); j++) { |
592 | 784 | AssignmentRule vRule = (AssignmentRule)v.get(j); |
593 | 784 | if (assertion instanceof Credentials) { |
594 | 687 | Credentials credentials = vRule.allocate(holder, (Credentials) assertion); |
595 | 687 | if ((credentials != null) && !(credentials.equals(emptyCred))) { |
596 | 340 | sumup = sumup.union(credentials); |
597 | } | |
598 | 687 | result = sumup; |
599 | } else { | |
600 | 97 | Vector rules = vRule.allocate(holder, (AssignmentRule) assertion); |
601 | 97 | if (!(rules.isEmpty())) { |
602 | 50 | validRARs.addAll(rules); |
603 | } | |
604 | 97 | result = validRARs; |
605 | } | |
606 | 784 | if (comparator.isSufficient(aRule, vRule, assertion, result)) { |
607 | 390 | break no_more_tokens; |
608 | } | |
609 | } | |
610 | } | |
611 | } | |
612 | ||
613 | 2146 | return result; |
614 | ||
615 | }catch (issrg.pba.PbaException e) { | |
616 | 0 | throw e; |
617 | } | |
618 | ||
619 | } | |
620 | } |
|