609d0fcc16625ec20b7bc023816c5b82c9b18a1d
[framework/web/wrt-commons.git] / modules / ace / engine / PolicyEvaluator.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 //
17 //
18 //
19 //  @ Project : Access Control Engine
20 //  @ File Name : PolicyEvaluator.cpp
21 //  @ Date : 2009-05-06
22 //  @ Author : Samsung
23 //
24 //
25
26 #include <dpl/assert.h>
27 #include <dpl/foreach.h>
28
29 #include <dpl/ace/PolicyEvaluator.h>
30 #include <dpl/ace/TreeNode.h>
31 #include <dpl/ace/Policy.h>
32 #include <dpl/ace/Rule.h>
33 #include <dpl/ace/Attribute.h>
34 //#include <dpl/ace/"UserDecisionTestStub.h>
35 #include <dpl/ace/SettingsLogic.h>
36 #include <dpl/ace-dao-rw/AceDAO.h>
37 #include <dpl/ace-dao-ro/PreferenceTypes.h>
38 #include <dpl/ace/parser.h>
39
40 using namespace AceDB;
41
42 PolicyEvaluator::~PolicyEvaluator()
43 {
44     delete m_combiner;
45 }
46
47 bool PolicyEvaluator::initPDP()
48 {
49     ConfigurationManager * configMgr = ConfigurationManager::getInstance();
50     if (configMgr == NULL) {
51         LogError("ACE fatal error: failed to create configuration manager");
52         return false;
53     }
54
55     Parser parser;
56     m_root = parser.parse(
57             configMgr->getFullPathToCurrentPolicyFile(),
58             configMgr->getFullPathToCurrentPolicyXMLSchema());
59
60     if (NULL == m_root) {
61         LogError("ACE fatal error: cannot parse XML file");
62     }
63
64     return true;
65 }
66
67 bool PolicyEvaluator::fillAttributeWithPolicy()
68 {
69     if (m_attributeSet.empty()) {
70         if (!extractAttributes()) {
71             LogInfo(
72                 "Warning attribute set cannot be extracted. Returning Deny");
73             return false;
74         }
75     } else {
76         LogDebug("Required attribute set found in database");
77     }
78     return true;
79 }
80
81 PolicyResult PolicyEvaluator::effectToPolicyResult(Effect effect){
82     if (Effect::Deny == effect) {
83         return PolicyEffect::DENY;
84     }
85     if (Effect::Undetermined == effect) {
86         return PolicyResult::Value::UNDETERMINED;
87     }
88     if (Effect::PromptOneShot == effect) {
89         return PolicyEffect::PROMPT_ONESHOT;
90     }
91     if (Effect::PromptSession == effect) {
92         return PolicyEffect::PROMPT_SESSION;
93     }
94     if (Effect::PromptBlanket == effect) {
95         return PolicyEffect::PROMPT_BLANKET;
96     }
97     if (Effect::Permit == effect) {
98         return PolicyEffect::PERMIT;
99     }
100     if (Effect::Inapplicable == effect) {
101         return PolicyDecision::Value::NOT_APPLICABLE;
102     }
103     return PolicyEffect::DENY;
104 }
105
106 OptionalPolicyResult PolicyEvaluator::getPolicyForRequestInternal(bool fromCacheOnly)
107 {
108     //ADD_PROFILING_POINT("Search cached verdict in database", "start");
109
110     OptionalPolicyResult result = AceDAO::getPolicyResult(
111         m_attributeSet);
112
113     //ADD_PROFILING_POINT("Search cached verdict in database", "stop");
114
115     if (fromCacheOnly || !result.IsNull()) {
116         return result;
117     }
118
119     //ADD_PROFILING_POINT("EvaluatePolicy", "start");
120
121     Effect policyEffect = evaluatePolicies(m_root);
122
123     //ADD_PROFILING_POINT("EvaluatePolicy", "stop");
124
125     LogDebug("Policy effect is: " << toString(policyEffect));
126
127     result = effectToPolicyResult(policyEffect);
128
129     AceDAO::setPolicyResult(this->m_attributeSet, *result);
130     return result;
131 }
132
133 // +----------------+---------+---------+------+--------+
134 // |\User setting   | PERMIT  | PROMPT* | DENY | DEF    |
135 // |      \         |         |         |      |        |
136 // |Policy result\  |         |         |      |        |
137 // |----------------+---------+---------+------+--------+
138 // |PERMIT          | PERMIT  | PROMPT* | DENY | PERMIT |
139 // |----------------+---------+---------+------+--------+
140 // |PROMPT*         | PROMPT* | PR MIN  | DENY | PROMPT*|
141 // |----------------+---------+---------+------+--------+
142 // |DENY            | DENY    | DENY    | DENY | DENY   |
143 // |----------------+---------+---------+------+--------+
144 // |UNDETERMIND     | UNDET   | UNDET   | DENY | UNDET  |
145 // |----------------+---------+---------+------+--------+
146 // |NOT_AP          | PEMIT   | PROMPT* | DENY | NOT_AP |
147 // +----------------+---------+---------+------+--------+
148
149 static PolicyResult getMostRestrict(PreferenceTypes globalPreference,
150                                     const PolicyResult &policyResult)
151 {
152         if (globalPreference == PreferenceTypes::PREFERENCE_PERMIT &&
153             policyResult == PolicyEffect::PERMIT)
154         {
155             return PolicyEffect::PERMIT;
156         }
157
158         if (globalPreference == PreferenceTypes::PREFERENCE_DENY ||
159             policyResult == PolicyEffect::DENY)
160         {
161             return PolicyEffect::DENY;
162         }
163
164         if (policyResult == PolicyResult::UNDETERMINED) {
165             return PolicyResult::UNDETERMINED;
166         }
167
168         if (globalPreference == PreferenceTypes::PREFERENCE_DEFAULT)
169         {
170             return policyResult;
171         }
172
173         if (globalPreference == PreferenceTypes::PREFERENCE_ONE_SHOT_PROMPT ||
174             policyResult == PolicyEffect::PROMPT_ONESHOT)
175         {
176             return PolicyEffect::PROMPT_ONESHOT;
177         }
178
179         if (globalPreference == PreferenceTypes::PREFERENCE_SESSION_PROMPT ||
180             policyResult == PolicyEffect::PROMPT_SESSION)
181         {
182             return PolicyEffect::PROMPT_SESSION;
183         }
184
185         if (globalPreference == PreferenceTypes::PREFERENCE_BLANKET_PROMPT ||
186             policyResult == PolicyEffect::PROMPT_BLANKET)
187         {
188             return PolicyEffect::PROMPT_BLANKET;
189         }
190
191         return PolicyEffect::PERMIT;
192 }
193
194 OptionalPolicyResult PolicyEvaluator::getPolicyForRequestFromCache(
195     const Request &request)
196 {
197     return getPolicyForRequest(request, true);
198 }
199
200 PolicyResult PolicyEvaluator::getPolicyForRequest(const Request &request)
201 {
202     auto result = this->getPolicyForRequest(request, false);
203     Assert(!result.IsNull() &&
204            "Policy always has to be evaluated to valid state");
205     return *result;
206 }
207
208 OptionalPolicyResult PolicyEvaluator::getPolicyForRequest(
209     const Request &request,
210     bool fromCacheOnly)
211 {
212     //ADD_PROFILING_POINT("getPolicyForRequest", "start");
213     m_attributeSet.clear();
214
215     try {
216         // Check which attributes should be used
217         // memory alocated, free in destructor
218         //ADD_PROFILING_POINT("getAttributes", "start");
219         AceDB::AceDAO::getAttributes(&m_attributeSet);
220         //ADD_PROFILING_POINT("getAttributes", "stop");
221
222         // If attributes can't be resolved then check the policy
223         if (!fillAttributeWithPolicy()) {
224             //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
225             return OptionalPolicyResult(PolicyEffect::DENY);
226         }
227
228         //ADD_PROFILING_POINT("getAttributesValues", "start");
229         m_pip->getAttributesValues(&request, &m_attributeSet);
230         //ADD_PROFILING_POINT("getAttributesValues", "stop");
231         LogDebug("==== Attributes set by PIP ====");
232         printAttributes(m_attributeSet);
233         LogDebug("==== End of attributes set by PIP ====");
234
235         OptionalPolicyResult policyResult =
236             getPolicyForRequestInternal(fromCacheOnly);
237
238         LogDebug("==== getPolicyForRequestInternal result (PolicyResult): "
239                  << policyResult << "=====");
240
241         if (policyResult.IsNull()) {
242             if (fromCacheOnly) {
243                 return OptionalPolicyResult::Null;
244             } else {
245                 LogError("Policy evaluated to NULL value");
246                 Assert(false && "Policy evaluated to NULL value");
247                 return OptionalPolicyResult::Null;
248             }
249         }
250
251         PreferenceTypes globalPreference =
252             SettingsLogic::findGlobalUserSettings(request);
253
254         auto ret = getMostRestrict(globalPreference, *policyResult);
255         //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
256         return OptionalPolicyResult(ret);
257
258     } catch (AceDB::AceDAO::Exception::DatabaseError &e) {
259         LogError("Database error");
260         DPL::Exception::DisplayKnownException(e);
261         //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
262         return OptionalPolicyResult(PolicyEffect::DENY);
263     }
264 }
265
266
267 bool PolicyEvaluator::extractAttributes()
268 {
269     if (m_root == NULL) {
270         return false;
271     }
272
273     //We check if root target matches. In general the root's target should be empty
274     //Otherwise it would have to have all the subjects available specified
275     //But just to be on the safe side ( and for tests) add this checking
276     const Policy * policy = dynamic_cast<const Policy *>(m_root->getElement());
277             Assert(
278             policy != NULL &&
279                     "Policy element has been null while attribute extracting");
280
281     extractTargetAttributes(policy);
282     extractAttributesFromSubtree(m_root); //Enter recursion
283
284     return true;
285 }
286
287 void PolicyEvaluator::extractTargetAttributes(const Policy *policy)
288 {
289     std::list<const Subject *>::const_iterator it =
290         policy->getSubjects()->begin();
291     for (; it != policy->getSubjects()->end(); ++it)
292     {
293         const std::list<Attribute> & attrList = (*it)->getTargetAttributes();
294         FOREACH(it2, attrList)
295         {
296             BaseAttributePtr attr(new Attribute((*it2).getName(),
297                     (*it2).getMatchFunction(), (*it2).getType()));
298             m_attributeSet.insert(attr);
299         }
300     }
301 }
302
303 /**
304  *
305  * @param *root - the root of the original (full) subtree of politics
306  * @param *newRoot - the pointer to the root of the copy (reduced) subtree of politics
307  */
308 void PolicyEvaluator::extractAttributesFromSubtree(const TreeNode *root)
309 {
310     const ChildrenSet & children = root->getChildrenSet();
311
312     for (
313     std::list<TreeNode *>::const_iterator it = children.begin();
314             it != children.end();
315             ++it
316             ) {
317         TreeNode * node = *it;
318         if (node->getTypeID() != TreeNode::Policy && node->getTypeID() !=
319                 TreeNode::PolicySet) {
320             //It is not a policy so we may be sure that we have already checked that SubjectId matches
321             //Add new node to new tree and extract attributes
322
323             extractAttributesFromRules(node);
324         } else { //TreeNode is a Policy or PolicySet
325             const Policy * policy =
326                 dynamic_cast<const Policy *>(node->getElement());
327             //We will be needing also the attributes from target
328             if (policy) {
329                 extractTargetAttributes(policy);
330             } else {
331                 LogError(" extractAttributesFromSubtree policy=NULL");
332             }
333             //Enter recursion
334             extractAttributesFromSubtree(node);
335         }
336     }
337 }
338
339 bool PolicyEvaluator::extractAttributesFromRules(const TreeNode *root)
340 {
341     Assert(
342             root->getTypeID() == TreeNode::Rule
343                     &&
344                     "Tree structure, extracting attributes from node that is not a rule");
345     Rule * rule = dynamic_cast<Rule *>(root->getElement());
346             Assert(rule != NULL);
347     //Get attributes from rule
348     rule->getAttributes(&m_attributeSet);
349
350     //[CR] consider returned value, because its added only to eliminate errors
351     return true;
352 }
353
354 Effect PolicyEvaluator::evaluatePolicies(const TreeNode * root)
355 {
356     if (root == NULL) {
357         LogInfo("Error: policy tree doesn't exist. "
358                 "Probably xml file is missing");
359         return Deny;
360     }
361
362     if (m_attributeSet.empty()) {
363         LogInfo("Warning: evaluatePolicies: attribute set was empty");
364     }
365     m_combiner->setAttributeSet(&m_attributeSet);
366     return m_combiner->combinePolicies(root);
367 }
368
369 int PolicyEvaluator::updatePolicy(const char* newPolicy)
370 {
371     ConfigurationManager* configMgr = ConfigurationManager::getInstance();
372
373     if (NULL == configMgr) {
374         LogError("ACE fatal error: failed to create configuration manager");
375         return POLICY_PARSING_ERROR;
376     }
377
378     int result = POLICY_PARSING_SUCCESS;
379     if (newPolicy == NULL) {
380         LogError("Policy Update: incorrect policy name");
381         return POLICY_FILE_ERROR;
382     }
383     LogDebug("Starting update policy: " << newPolicy);
384
385     Parser parser;
386     TreeNode *backup = m_root;
387
388     m_root = parser.parse(
389             newPolicy,
390             configMgr->getFullPathToCurrentPolicyXMLSchema());
391
392     if (NULL == m_root) {
393         m_root = backup;
394         LogError("Policy Update: corrupted policy file");
395         result = POLICY_PARSING_ERROR;
396     } else {
397         m_currentPolicyFile = newPolicy;
398         backup->releaseResources();
399         LogInfo("Policy Update: successful.");
400         try {
401             AceDAO::resetDatabase();
402         } catch (AceDAO::Exception::DatabaseError &e) {
403         }
404     }
405     return result;
406 }
407
408 std::string PolicyEvaluator::getCurrentPolicy(){
409     return m_currentPolicyFile;
410 }
411
412 const char * toString(Validity validity)
413 {
414     switch (validity) {
415     case Validity::ONCE:
416         return "Once";
417         break;
418     case Validity::SESSION:
419         return "Session";
420     case Validity::ALWAYS:
421         return "Always";
422     default:
423         return "WRONG VALIDITY";
424     }
425 }
426
427 const char * toString(Verdict verdict)
428 {
429     switch (verdict) {
430     case Verdict::VERDICT_PERMIT:
431         return "Permit";
432     case Verdict::VERDICT_DENY:
433         return "Deny";
434     case Verdict::VERDICT_INAPPLICABLE:
435         return "Inapplicable";
436     case Verdict::VERDICT_UNKNOWN:
437         return "Unknown";
438     case Verdict::VERDICT_UNDETERMINED:
439         return "Undetermined";
440     case Verdict::VERDICT_ERROR:
441         return "Error";
442     case Verdict::VERDICT_ASYNC:
443         return "Async";
444     default:
445         return "Wrong verdict value";
446     }
447 }