2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 // @ Project : Access Control Engine
20 // @ File Name : PolicyEvaluator.cpp
21 // @ Date : 2009-05-06
26 #include <dpl/assert.h>
27 #include <dpl/foreach.h>
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>
40 using namespace AceDB;
42 PolicyEvaluator::~PolicyEvaluator()
47 bool PolicyEvaluator::initPDP()
49 ConfigurationManager * configMgr = ConfigurationManager::getInstance();
50 if (configMgr == NULL) {
51 LogError("ACE fatal error: failed to create configuration manager");
56 m_root = parser.parse(
57 configMgr->getFullPathToCurrentPolicyFile(),
58 configMgr->getFullPathToCurrentPolicyXMLSchema());
61 LogError("ACE fatal error: cannot parse XML file");
67 bool PolicyEvaluator::fillAttributeWithPolicy()
69 if (m_attributeSet.empty()) {
70 if (!extractAttributes()) {
72 "Warning attribute set cannot be extracted. Returning Deny");
76 LogDebug("Required attribute set found in database");
81 PolicyResult PolicyEvaluator::effectToPolicyResult(Effect effect){
82 if (Effect::Deny == effect) {
83 return PolicyEffect::DENY;
85 if (Effect::Undetermined == effect) {
86 return PolicyResult::Value::UNDETERMINED;
88 if (Effect::PromptOneShot == effect) {
89 return PolicyEffect::PROMPT_ONESHOT;
91 if (Effect::PromptSession == effect) {
92 return PolicyEffect::PROMPT_SESSION;
94 if (Effect::PromptBlanket == effect) {
95 return PolicyEffect::PROMPT_BLANKET;
97 if (Effect::Permit == effect) {
98 return PolicyEffect::PERMIT;
100 if (Effect::Inapplicable == effect) {
101 return PolicyDecision::Value::NOT_APPLICABLE;
103 return PolicyEffect::DENY;
106 OptionalPolicyResult PolicyEvaluator::getPolicyForRequestInternal(bool fromCacheOnly)
108 //ADD_PROFILING_POINT("Search cached verdict in database", "start");
110 OptionalPolicyResult result = AceDAO::getPolicyResult(
113 //ADD_PROFILING_POINT("Search cached verdict in database", "stop");
115 if (fromCacheOnly || !result.IsNull()) {
119 //ADD_PROFILING_POINT("EvaluatePolicy", "start");
121 Effect policyEffect = evaluatePolicies(m_root);
123 //ADD_PROFILING_POINT("EvaluatePolicy", "stop");
125 LogDebug("Policy effect is: " << toString(policyEffect));
127 result = effectToPolicyResult(policyEffect);
129 AceDAO::setPolicyResult(this->m_attributeSet, *result);
133 // +----------------+---------+---------+------+--------+
134 // |\User setting | PERMIT | PROMPT* | DENY | DEF |
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 // +----------------+---------+---------+------+--------+
149 static PolicyResult getMostRestrict(PreferenceTypes globalPreference,
150 const PolicyResult &policyResult)
152 if (globalPreference == PreferenceTypes::PREFERENCE_PERMIT &&
153 policyResult == PolicyEffect::PERMIT)
155 return PolicyEffect::PERMIT;
158 if (globalPreference == PreferenceTypes::PREFERENCE_DENY ||
159 policyResult == PolicyEffect::DENY)
161 return PolicyEffect::DENY;
164 if (policyResult == PolicyResult::UNDETERMINED) {
165 return PolicyResult::UNDETERMINED;
168 if (globalPreference == PreferenceTypes::PREFERENCE_DEFAULT)
173 if (globalPreference == PreferenceTypes::PREFERENCE_ONE_SHOT_PROMPT ||
174 policyResult == PolicyEffect::PROMPT_ONESHOT)
176 return PolicyEffect::PROMPT_ONESHOT;
179 if (globalPreference == PreferenceTypes::PREFERENCE_SESSION_PROMPT ||
180 policyResult == PolicyEffect::PROMPT_SESSION)
182 return PolicyEffect::PROMPT_SESSION;
185 if (globalPreference == PreferenceTypes::PREFERENCE_BLANKET_PROMPT ||
186 policyResult == PolicyEffect::PROMPT_BLANKET)
188 return PolicyEffect::PROMPT_BLANKET;
191 return PolicyEffect::PERMIT;
194 OptionalPolicyResult PolicyEvaluator::getPolicyForRequestFromCache(
195 const Request &request)
197 return getPolicyForRequest(request, true);
200 PolicyResult PolicyEvaluator::getPolicyForRequest(const Request &request)
202 auto result = this->getPolicyForRequest(request, false);
203 Assert(!result.IsNull() &&
204 "Policy always has to be evaluated to valid state");
208 OptionalPolicyResult PolicyEvaluator::getPolicyForRequest(
209 const Request &request,
212 //ADD_PROFILING_POINT("getPolicyForRequest", "start");
213 m_attributeSet.clear();
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");
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);
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 ====");
235 OptionalPolicyResult policyResult =
236 getPolicyForRequestInternal(fromCacheOnly);
238 LogDebug("==== getPolicyForRequestInternal result (PolicyResult): "
239 << policyResult << "=====");
241 if (policyResult.IsNull()) {
243 return OptionalPolicyResult::Null;
245 LogError("Policy evaluated to NULL value");
246 Assert(false && "Policy evaluated to NULL value");
247 return OptionalPolicyResult::Null;
251 PreferenceTypes globalPreference =
252 SettingsLogic::findGlobalUserSettings(request);
254 auto ret = getMostRestrict(globalPreference, *policyResult);
255 //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
256 return OptionalPolicyResult(ret);
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);
267 bool PolicyEvaluator::extractAttributes()
269 if (m_root == NULL) {
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());
279 "Policy element has been null while attribute extracting");
281 extractTargetAttributes(policy);
282 extractAttributesFromSubtree(m_root); //Enter recursion
287 void PolicyEvaluator::extractTargetAttributes(const Policy *policy)
289 std::list<const Subject *>::const_iterator it =
290 policy->getSubjects()->begin();
291 for (; it != policy->getSubjects()->end(); ++it)
293 const std::list<Attribute> & attrList = (*it)->getTargetAttributes();
294 FOREACH(it2, attrList)
296 BaseAttributePtr attr(new Attribute((*it2).getName(),
297 (*it2).getMatchFunction(), (*it2).getType()));
298 m_attributeSet.insert(attr);
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
308 void PolicyEvaluator::extractAttributesFromSubtree(const TreeNode *root)
310 const ChildrenSet & children = root->getChildrenSet();
313 std::list<TreeNode *>::const_iterator it = children.begin();
314 it != children.end();
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
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
329 extractTargetAttributes(policy);
331 LogError(" extractAttributesFromSubtree policy=NULL");
334 extractAttributesFromSubtree(node);
339 bool PolicyEvaluator::extractAttributesFromRules(const TreeNode *root)
342 root->getTypeID() == TreeNode::Rule
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);
350 //[CR] consider returned value, because its added only to eliminate errors
354 Effect PolicyEvaluator::evaluatePolicies(const TreeNode * root)
357 LogInfo("Error: policy tree doesn't exist. "
358 "Probably xml file is missing");
362 if (m_attributeSet.empty()) {
363 LogInfo("Warning: evaluatePolicies: attribute set was empty");
365 m_combiner->setAttributeSet(&m_attributeSet);
366 return m_combiner->combinePolicies(root);
369 int PolicyEvaluator::updatePolicy(const char* newPolicy)
371 ConfigurationManager* configMgr = ConfigurationManager::getInstance();
373 if (NULL == configMgr) {
374 LogError("ACE fatal error: failed to create configuration manager");
375 return POLICY_PARSING_ERROR;
378 int result = POLICY_PARSING_SUCCESS;
379 if (newPolicy == NULL) {
380 LogError("Policy Update: incorrect policy name");
381 return POLICY_FILE_ERROR;
383 LogDebug("Starting update policy: " << newPolicy);
386 TreeNode *backup = m_root;
388 m_root = parser.parse(
390 configMgr->getFullPathToCurrentPolicyXMLSchema());
392 if (NULL == m_root) {
394 LogError("Policy Update: corrupted policy file");
395 result = POLICY_PARSING_ERROR;
397 m_currentPolicyFile = newPolicy;
398 backup->releaseResources();
399 LogInfo("Policy Update: successful.");
401 AceDAO::resetDatabase();
402 } catch (AceDAO::Exception::DatabaseError &e) {
408 std::string PolicyEvaluator::getCurrentPolicy(){
409 return m_currentPolicyFile;
412 const char * toString(Validity validity)
418 case Validity::SESSION:
420 case Validity::ALWAYS:
423 return "WRONG VALIDITY";
427 const char * toString(Verdict verdict)
430 case Verdict::VERDICT_PERMIT:
432 case Verdict::VERDICT_DENY:
434 case Verdict::VERDICT_INAPPLICABLE:
435 return "Inapplicable";
436 case Verdict::VERDICT_UNKNOWN:
438 case Verdict::VERDICT_UNDETERMINED:
439 return "Undetermined";
440 case Verdict::VERDICT_ERROR:
442 case Verdict::VERDICT_ASYNC:
445 return "Wrong verdict value";