AccessPolicy | Line # 65 | 48 | 17 | 80.5% |
0.8051948
|
No Tests | |||
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 | package issrg.pba.rbac.policies; | |
33 | ||
34 | import issrg.pba.DecisionWithObligationException; | |
35 | import issrg.pba.Obligations; | |
36 | import issrg.utils.repository.Entry; | |
37 | import issrg.pba.PbaException; | |
38 | import issrg.pba.Response; | |
39 | import issrg.pba.PERMISResponse; | |
40 | import issrg.pba.rbac.xmlpolicy.XMLPolicyParser; | |
41 | import java.util.Map; | |
42 | import java.util.Hashtable; | |
43 | import java.util.Vector; | |
44 | import org.apache.log4j.*;// added for logging | |
45 | /** | |
46 | * This is the class representing the Target Access Policy. It delivers the | |
47 | * decision | |
48 | * on whether a user with a certain set of credentials is allowed to access a | |
49 | * target. | |
50 | * <p> | |
51 | * It knows the rules for accessing targets, and can make a decision based on | |
52 | * those rules, when passed the set of credentials, the action and the target | |
53 | * parameters. | |
54 | * <p> | |
55 | * It is aware of the Target domains and all Target Access Policy statements, | |
56 | * including the IF statement. | |
57 | * <p> | |
58 | * | |
59 | * @see AccessRule | |
60 | * | |
61 | * @author A Otenko | |
62 | * @version 1.0 | |
63 | */ | |
64 | ||
65 | public class AccessPolicy { | |
66 | private Logger logger = Logger.getLogger(AccessPolicy.class); | |
67 | /** | |
68 | * This is where the action policy is stored for internal purposes | |
69 | */ | |
70 | protected XMLPolicyParser.ActionPolicyNode actionPolicy; | |
71 | ||
72 | /** | |
73 | * This is where the target domain policy is stored for internal purposes | |
74 | */ | |
75 | protected XMLPolicyParser.DomainPolicyNode targetPolicy; | |
76 | ||
77 | /** | |
78 | * This is where the Access Rules are stored | |
79 | */ | |
80 | protected java.util.Map rules; | |
81 | ||
82 | /** | |
83 | * This is added for MSoD. | |
84 | * | |
85 | */ | |
86 | MSoDPolicySet msodPolicySet; | |
87 | ||
88 | /** | |
89 | * This is used to determine where the parameters start in the action | |
90 | * definition String array. It is 1 now, but can be 0 if we decide to remove | |
91 | * the return type of the action. | |
92 | */ | |
93 | private final static int SHIFT_ACTIONS=1; | |
94 | ||
95 | 0 | protected AccessPolicy(){} |
96 | ||
97 | /** | |
98 | * This constructor creates the object out of a set of the access Rules. There | |
99 | * are two special kinds of rules. One of the rules is | |
100 | * the Action Policy that defines the methods. To find it among the rules, | |
101 | * the XMLPolicyParser.ActionPolicyNode.class is used as the key, and the | |
102 | * value is assumed to be an XMLPolicyParser.ActionPolicyNode object | |
103 | * containing the | |
104 | * action definitions accessible by the action name. | |
105 | * | |
106 | * <p>The other special rule is the Target Policy, specifying the domains of | |
107 | * targets. To find it among the rules, XMLPolicyParser.DomainPolicyNode.class | |
108 | * is used as the key and the value is assumed to be a | |
109 | * XMLPolicyParser.DomainPolicyNode | |
110 | * | |
111 | * <p>All the other rules are indexed by Action name and constitute Vectors | |
112 | * of AccessRule objects. There is a special action with an empty name (""). | |
113 | * The entry for this action contains the rules that allow any action to be | |
114 | * executed, without explicitly naming them. So to make a decision, the | |
115 | * AccessPolicy finds all the rules that belong to the named action | |
116 | * (i.e. the TargetAccess names the action explicitly) and all the rules | |
117 | * that do not name any action (i.e. the TargetAccess allows any action | |
118 | * to be executed, if the condition is met). If there is a rule that can be | |
119 | * satisfied (the Subject has the required Credentials and the IF-condition | |
120 | * evaluates to true, if present), then access can be granted. | |
121 | * | |
122 | * @param accessRules is a map of rules, created by the PolicyParser; the map | |
123 | * is indexed by Action name, and contains | |
124 | * Vectors of Target access rules for each of them, including the | |
125 | * specification of what targets can execute this action, and what is the | |
126 | * minimal set of credentials for gaining that access; | |
127 | */ | |
128 | 24 | public AccessPolicy(java.util.Map accessRules) { |
129 | 24 | rules = accessRules; |
130 | 24 | actionPolicy = (XMLPolicyParser.ActionPolicyNode)accessRules.get(XMLPolicyParser.ActionPolicyNode.class); |
131 | 24 | targetPolicy = (XMLPolicyParser.DomainPolicyNode)accessRules.get(XMLPolicyParser.DomainPolicyNode.class); |
132 | } | |
133 | ||
134 | ||
135 | /** | |
136 | * This constructor is for MSoD. | |
137 | * DONT YOU EVER COPY PASTE IN YOUR LIFE! IT IS A SIN! | |
138 | */ | |
139 | 4 | public AccessPolicy(java.util.Map accessRules, MSoDPolicySet msodPS) { |
140 | 4 | this(accessRules); // this is the right way to ensure this constructor does the same as the other one |
141 | 4 | msodPolicySet = msodPS; // added for MSoD |
142 | //rules = accessRules; | |
143 | //actionPolicy = (XMLPolicyParser.ActionPolicyNode)accessRules.get(XMLPolicyParser.ActionPolicyNode.class); | |
144 | //targetPolicy = (XMLPolicyParser.DomainPolicyNode)accessRules.get(XMLPolicyParser.DomainPolicyNode.class); | |
145 | } | |
146 | ||
147 | ||
148 | /** | |
149 | * This method performs the actual access control. Given a set of credentials, | |
150 | * it checks whether there is any statement in the TargetAccessPolicy that | |
151 | * allows to perform the given Action on the given Target. After matching | |
152 | * the set of credentials and the Target domain, the IF statement is | |
153 | * evaluated, | |
154 | * involving the Environment and the arguments to the Action. | |
155 | * | |
156 | * <p>Note that the IF statement is the interpretation tree, which is built | |
157 | * by the PolicyParser, and it can evaluate itself. | |
158 | * | |
159 | * <p>To find the rules, the rule set provided to the constructor is searched | |
160 | * for rules mentioning the Action explicitly, and for the rules implying the | |
161 | * Action (i.e. the rules allowing "any" action). | |
162 | * | |
163 | * @param creds is the set of credentials the user possesses | |
164 | * @param a is the action the user wants to perform (name + action ADI) | |
165 | * @param t is the target the user wants to perform (name + target ADI); | |
166 | * Target must return TargetADI implementing Entry interface | |
167 | * @param environment is the collection of environmental parameters to the | |
168 | * action; contextual ADI | |
169 | * | |
170 | * @return true, if the requested access can be granted; false, if the access | |
171 | * is denied by the policy | |
172 | * @throws PbaException in any case of error; for example, malformed | |
173 | * parameters | |
174 | * to the method, or an error in decision evaluation, thrown by an Access | |
175 | * Rule | |
176 | * @throws DecisionWithObligationException, if the policy requires some | |
177 | * Obligations to be enforced along with the decision; either handle this | |
178 | * case specially to enforce the obligations, or use response method | |
179 | * @see AccessPolicy#response | |
180 | */ | |
181 | 0 | public boolean decision(issrg.pba.Credentials creds, issrg.pba.Action a, |
182 | issrg.pba.Target t, java.util.Map environment) | |
183 | throws PbaException{ | |
184 | 0 | Response resp = response(creds,a,t,environment); |
185 | 0 | Obligations oblgs=resp.getObligations(); |
186 | 0 | if((oblgs!=null)||(oblgs.isEmpty()==false)){ |
187 | //thorw an error here, telling that the decision shall be enforced with obligations. | |
188 | 0 | throw new DecisionWithObligationException("There are obligations associated with this decision, which must be fulfiled with the enforcement of the decision.",resp); |
189 | } | |
190 | ||
191 | 0 | return resp.isAuthorised(); |
192 | ||
193 | } | |
194 | ||
195 | /** | |
196 | * This method makes a decision, and returns a response regarding to the | |
197 | * request represented by a set of Credentials, an Action, the Target and | |
198 | * the Environment. The response may contain obligations. | |
199 | * | |
200 | * @param creds is the set of credentials the user possesses | |
201 | * @param a is the action the user wants to perform (name + action ADI) | |
202 | * @param t is the target the user wants to perform (name + target ADI); | |
203 | * Target | |
204 | * must return TargetADI implementing Entry interface | |
205 | * @param environment is the collection of environmental parameters to the | |
206 | * action; contextual ADI | |
207 | * | |
208 | * @return a Response that contains the authorisation decision and the | |
209 | * obligations that must be enforced along with it. | |
210 | */ | |
211 | 1359 | public Response response(issrg.pba.Credentials creds, issrg.pba.Action a, |
212 | issrg.pba.Target t, java.util.Map environment) | |
213 | throws PbaException{ | |
214 | ||
215 | //System.out.println("\t\t*** ACCESS POLICY INVOCATION ***\n\t"+rules); //***** | |
216 | ||
217 | 1359 | Object targetADI = t.getTargetADI(); |
218 | ||
219 | 1359 | PERMISResponse sd; |
220 | ||
221 | 1359 | if (!(targetADI instanceof Entry) || !targetPolicy.getCoverageDomain().contains((Entry)targetADI)){ |
222 | 241 | logger.debug("Target is out of target domain"); |
223 | 241 | throw new TargetOutOfDomainException("Target is out of target domain"); |
224 | } | |
225 | 1118 | logger.debug("target check : pass"); |
226 | 1118 | if ((a==null) ^ (actionPolicy==null)){ |
227 | // the condition reads: the action cannot be null, if actionPolicy is not null | |
228 | // however, it must be null, if the actionPolicy is null | |
229 | 0 | logger.debug("Unacceptable Action for this Policy"); |
230 | 0 | throw new PbaException("Unacceptable Action for this Policy"); |
231 | } | |
232 | 1118 | logger.debug("action check : pass"); |
233 | 1118 | Map actionADI = new Hashtable(); |
234 | 1118 | String aName="\0"; // the default action name, if the action is null |
235 | // the first loop (see below) will always skip in that case | |
236 | // (because the actionPolicy would be null) | |
237 | ||
238 | 1118 | if (a!=null){ |
239 | // actionPolicy is not null here | |
240 | 1118 | aName=a.getActionName(); |
241 | 1118 | String [] paramNames = actionPolicy.getActionDefinition(aName); |
242 | 1118 | Object o = a.getContextualADI(); // this should be an array of actual parameters, within Permis RBAC |
243 | 1118 | if (o==null) o=new Object[0]; |
244 | 1118 | Object [] o1; |
245 | ||
246 | //String hihix = (!(o instanceof Object[]))?"contextual ADI is not an Argument[]: "+o: | |
247 | // (paramNames==null?"paramNames==null": | |
248 | // ( | |
249 | // ((o1=((Argument[])o)).length!=paramNames.length-SHIFT_ACTIONS)? | |
250 | // ("array lengths do not match: "+o1.length+"!="+paramNames.length+"-"+SHIFT_ACTIONS) | |
251 | // :null | |
252 | // ) | |
253 | // ); | |
254 | 0 | if (!(o instanceof Object[]) || // is it an array of parameters? |
255 | paramNames==null || // is there such an action? | |
256 | (o1 = (Object [])o).length!=paramNames.length-SHIFT_ACTIONS){ // are the arrays of actual parameters and argument names of the same length? | |
257 | 60 | logger.debug("Unacceptable Action for this Policy "+aName); |
258 | 60 | throw new PbaException("Unacceptable Action for this Policy: "+aName); |
259 | } | |
260 | 1058 | logger.debug("action parameters check : pass"); |
261 | // prepare the actionADI now | |
262 | // array index ranges are checked | |
263 | 1814 | for (int i=0; i<o1.length; i++){ |
264 | 756 | actionADI.put(paramNames[i+SHIFT_ACTIONS], o1[i]); |
265 | } | |
266 | } | |
267 | ||
268 | 2940 | for(String bName=""; aName!=null; aName=bName, bName=null){ // loop twice: once for the real action name, the second time for "" name: any Action |
269 | // look for rules applicable to this action (either aName or AnyAction) | |
270 | ||
271 | 1999 | Vector accessRules = (Vector)rules.get(aName); // they are vectors there |
272 | //System.out.println("access rules for action: "+aName+" - "+accessRules);//*************** | |
273 | /** | |
274 | * TODO: check class cast there ^^^ and throw an exception on error | |
275 | */ | |
276 | ||
277 | 1999 | if (accessRules==null){ |
278 | 943 | continue; // it may happen that there is no rule for this action |
279 | // alone, but there can be a rule for AnyAction; or vice versa | |
280 | } | |
281 | ||
282 | 4429 | for (int i=accessRules.size(); i-->0; ){ |
283 | 3490 | AccessRule ar = (AccessRule)accessRules.get(i); |
284 | 3490 | logger.debug("access rule = "+ar.toString()); |
285 | 3490 | if (ar.decide(creds, targetADI, actionADI, environment)){ |
286 | //System.out.println("granted access because: "+ar); //************** this should be turned into a logging message - by which authority access has been granted | |
287 | ||
288 | //return true; // found one rule that is applicable and grants access | |
289 | ||
290 | //@todo this is where we found the rule that can be applied to the current request. | |
291 | ||
292 | 117 | logger.debug("permit"); |
293 | // This line is changed to insert MSoD. added for MSoD | |
294 | 117 | if (msodPolicySet == null) { |
295 | 83 | return new PERMISResponse(true, ar.getObligations()); |
296 | } | |
297 | else { | |
298 | 34 | return new PERMISResponse( |
299 | !msodPolicySet.separationOfDutiesApplies(creds, /*ar.getCreds(),*/ /*subject, */a, t, environment) , | |
300 | ar.getObligations()); | |
301 | //when msodPolicySet.separationOfDutiesApplies() returns true, it means a Separation of Duty rule applies here, | |
302 | // this rule should forbid the user to get the access, i.e. the access request should be forbidden. | |
303 | // So please note that "true" here means to deny access, "false" here means to grant access. | |
304 | } | |
305 | } | |
306 | ||
307 | //System.out.println("access rule "+ar+" denied access"); //************** | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | 941 | return new PERMISResponse(false); |
313 | ||
314 | //return false; | |
315 | } | |
316 | } | |
317 | ||
318 |
|