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
25 #include <dpl/assert.h>
26 #include <dpl/foreach.h>
28 #include <ace/Attribute.h>
29 #include <ace/PolicyEvaluator.h>
30 #include <ace/TreeNode.h>
31 #include <ace/Policy.h>
33 #include <ace/Attribute.h>
34 #include <ace/SettingsLogic.h>
35 #include <ace-dao-rw/AceDAO.h>
36 #include <ace-dao-ro/PreferenceTypes.h>
37 #include <ace/parser.h>
39 using namespace AceDB;
41 PolicyEvaluator::~PolicyEvaluator()
46 PolicyEvaluator::PolicyEvaluator(PolicyInformationPoint * pip) :
47 m_uniform_policy(NULL),
50 m_policy_to_use(PolicyType::WAC2_0),
51 m_combiner(new CombinerImpl()),
52 m_verdictListener(NULL),
56 bool PolicyEvaluator::initPDP()
59 // TODO change return value someday to void?
63 bool PolicyEvaluator::fillAttributeWithPolicy()
65 if (m_attributeSet.empty()) {
66 if (!extractAttributes(m_uniform_policy)) {
67 LogInfo("Warning attribute set cannot be extracted. "
71 // Adding widget type attribute to distinguish WAC/Tizen widgets
73 * This special attribute of WidgetParam type is handled
74 * in PolicyInformationPoint, it is based on WidgetType
77 * It is needed to distinguish cached policy results and cached prompt
78 * responses for different policies (WAC/Tizen/any possible
79 * other in the future).
81 AceDB::BaseAttributePtr attribute(new AceDB::BaseAttribute());
82 attribute->setName(POLICY_WIDGET_TYPE_ATTRIBUTE_NAME);
83 attribute->setType(AceDB::BaseAttribute::Type::WidgetParam);
84 m_attributeSet.insert(attribute);
85 AceDAO::addAttributes(m_attributeSet);
87 LogDebug("Required attribute set already loaded");
92 PolicyResult PolicyEvaluator::effectToPolicyResult(Effect effect)
94 if (Effect::Deny == effect) {
95 return PolicyEffect::DENY;
97 if (Effect::Undetermined == effect) {
98 return PolicyResult::Value::UNDETERMINED;
100 if (Effect::PromptOneShot == effect) {
101 return PolicyEffect::PROMPT_ONESHOT;
103 if (Effect::PromptSession == effect) {
104 return PolicyEffect::PROMPT_SESSION;
106 if (Effect::PromptBlanket == effect) {
107 return PolicyEffect::PROMPT_BLANKET;
109 if (Effect::Permit == effect) {
110 return PolicyEffect::PERMIT;
112 if (Effect::Inapplicable == effect) {
113 return PolicyDecision::Value::NOT_APPLICABLE;
115 return PolicyEffect::DENY;
118 OptionalExtendedPolicyResult PolicyEvaluator::getPolicyForRequestInternal(
121 //ADD_PROFILING_POINT("Search cached verdict in database", "start");
123 OptionalExtendedPolicyResult result = AceDAO::getPolicyResult(m_attributeSet);
125 //ADD_PROFILING_POINT("Search cached verdict in database", "stop");
127 if (fromCacheOnly || !!result) {
131 //ADD_PROFILING_POINT("EvaluatePolicy", "start");
133 ExtendedEffect policyEffect = evaluatePolicies(getCurrentPolicyTree());
135 //ADD_PROFILING_POINT("EvaluatePolicy", "stop");
137 LogDebug("Policy effect is: " << toString(policyEffect.getEffect()));
139 ExtendedPolicyResult exResult(
140 effectToPolicyResult(policyEffect.getEffect()),
141 policyEffect.getRuleId());
143 AceDAO::setPolicyResult(this->m_attributeSet, exResult);
144 return OptionalExtendedPolicyResult(exResult);
147 // +----------------+---------+---------+------+--------+
148 // |\User setting | PERMIT | PROMPT* | DENY | DEF |
150 // |Policy result\ | | | | |
151 // |----------------+---------+---------+------+--------+
152 // |PERMIT | PERMIT | PROMPT* | DENY | PERMIT |
153 // |----------------+---------+---------+------+--------+
154 // |PROMPT* | PROMPT* | PR MIN | DENY | PROMPT*|
155 // |----------------+---------+---------+------+--------+
156 // |DENY | DENY | DENY | DENY | DENY |
157 // |----------------+---------+---------+------+--------+
158 // |UNDETERMIND | UNDET | UNDET | DENY | UNDET |
159 // |----------------+---------+---------+------+--------+
160 // |NOT_AP | PEMIT | PROMPT* | DENY | NOT_AP |
161 // +----------------+---------+---------+------+--------+
163 static PolicyResult getMostRestrict(
164 PreferenceTypes globalPreference,
165 const PolicyResult &policyResult)
167 if (globalPreference == PreferenceTypes::PREFERENCE_PERMIT
168 && policyResult == PolicyEffect::PERMIT) {
169 return PolicyEffect::PERMIT;
172 if (globalPreference == PreferenceTypes::PREFERENCE_DENY
173 || policyResult == PolicyEffect::DENY) {
174 return PolicyEffect::DENY;
177 if (policyResult == PolicyResult::UNDETERMINED) {
178 return PolicyResult::UNDETERMINED;
181 if (globalPreference == PreferenceTypes::PREFERENCE_DEFAULT) {
185 if (globalPreference == PreferenceTypes::PREFERENCE_ONE_SHOT_PROMPT
186 || policyResult == PolicyEffect::PROMPT_ONESHOT) {
187 return PolicyEffect::PROMPT_ONESHOT;
190 if (globalPreference == PreferenceTypes::PREFERENCE_SESSION_PROMPT
191 || policyResult == PolicyEffect::PROMPT_SESSION) {
192 return PolicyEffect::PROMPT_SESSION;
195 if (globalPreference == PreferenceTypes::PREFERENCE_BLANKET_PROMPT
196 || policyResult == PolicyEffect::PROMPT_BLANKET) {
197 return PolicyEffect::PROMPT_BLANKET;
200 return PolicyEffect::PERMIT;
203 OptionalExtendedPolicyResult PolicyEvaluator::getPolicyForRequestFromCache(
204 const Request &request)
206 return getPolicyForRequest(request, true);
209 ExtendedPolicyResult PolicyEvaluator::getPolicyForRequest(const Request &request)
211 auto result = this->getPolicyForRequest(request, false);
213 && "Policy always has to be evaluated to valid state");
217 OptionalExtendedPolicyResult PolicyEvaluator::getPolicyForRequest(
218 const Request &request,
221 //ADD_PROFILING_POINT("getPolicyForRequest", "start");
222 m_attributeSet.clear();
224 switch (request.getAppType()) {
225 case Request::APP_TYPE_TIZEN:
226 m_policy_to_use = PolicyType::Tizen;
227 LogDebug("==== Using Tizen policy ====");
229 case Request::APP_TYPE_WAC20:
230 m_policy_to_use = PolicyType::WAC2_0;
231 LogDebug("==== Using WAC policy ====");
234 LogError("Unsupported(unknown) widget type. Access denied.");
235 return OptionalExtendedPolicyResult(
236 ExtendedPolicyResult(PolicyEffect::DENY));
240 // Check which attributes should be used
241 // memory alocated, free in destructor
242 //ADD_PROFILING_POINT("getAttributes", "start");
243 AceDB::AceDAO::getAttributes(&m_attributeSet);
244 //ADD_PROFILING_POINT("getAttributes", "stop");
246 // If attributes can't be resolved then check the policy
247 if (!fillAttributeWithPolicy()) {
248 //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
249 return OptionalExtendedPolicyResult(
250 ExtendedPolicyResult(PolicyEffect::DENY));
253 //ADD_PROFILING_POINT("getAttributesValues", "start");
254 m_pip->getAttributesValues(&request, &m_attributeSet);
255 //ADD_PROFILING_POINT("getAttributesValues", "stop");
256 LogDebug("==== Attributes set by PIP ====");
257 printAttributes(m_attributeSet);
258 LogDebug("==== End of attributes set by PIP ====");
260 OptionalExtendedPolicyResult policyResult = getPolicyForRequestInternal(
264 if (!fromCacheOnly) {
265 LogError("Policy evaluated to NULL value");
266 Assert(false && "Policy evaluated to NULL value");
268 return OptionalExtendedPolicyResult();
270 LogDebug("==== getPolicyForRequestInternal result (PolicyResult): "
271 << policyResult->policyResult << "=====");
273 PreferenceTypes globalPreference =
274 SettingsLogic::findGlobalUserSettings(request);
276 auto ret = getMostRestrict(globalPreference, policyResult->policyResult);
277 //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
278 return OptionalExtendedPolicyResult(
279 ExtendedPolicyResult(ret, policyResult->ruleId));
281 } catch (AceDB::AceDAO::Exception::DatabaseError &e) {
282 LogError("Database error");
283 DPL::Exception::DisplayKnownException(e);
284 //ADD_PROFILING_POINT("getPolicyForRequest", "stop");
285 return OptionalExtendedPolicyResult(
286 ExtendedPolicyResult(PolicyEffect::DENY));
290 bool PolicyEvaluator::extractAttributes(TreeNode* policyTree)
292 if (NULL == policyTree) {
296 //We check if root target matches. In general the root's target should
297 //be empty. Otherwise it would have to have all the subjects available
298 //specified but just to be on the safe side (and for tests) this checking
299 const Policy * policy =
300 dynamic_cast<const Policy *>(policyTree->getElement());
301 Assert(policy != NULL
302 && "Policy element has been null while attribute extracting");
304 extractTargetAttributes(policy);
305 extractAttributesFromSubtree(policyTree); //Enter recursion
310 void PolicyEvaluator::extractTargetAttributes(const Policy *policy)
312 std::list<const Subject *>::const_iterator it =
313 policy->getSubjects()->begin();
314 for (; it != policy->getSubjects()->end(); ++it) {
315 const std::list<Attribute> & attrList = (*it)->getTargetAttributes();
316 FOREACH(it2, attrList)
318 BaseAttributePtr attr(
319 new Attribute((*it2).getName(), (*it2).getMatchFunction(),
321 m_attributeSet.insert(attr);
326 TreeNode * PolicyEvaluator::getCurrentPolicyTree()
328 TreeNode * currentPolicy = NULL;
329 switch (m_policy_to_use) {
330 case PolicyType::Tizen: {
331 currentPolicy = m_tizen_policy;
333 case PolicyType::WAC2_0: {
334 currentPolicy = m_wac_policy;
337 LogError("Invalid policy type to use");}
339 return currentPolicy;
344 * @param *root - the root of the original (full) subtree of politics
345 * @param *newRoot - the pointer to the root of the copy (reduced) subtree of politics
347 void PolicyEvaluator::extractAttributesFromSubtree(const TreeNode *root)
349 const ChildrenSet & children = root->getChildrenSet();
351 for (std::list<TreeNode *>::const_iterator it = children.begin();
352 it != children.end(); ++it) {
353 TreeNode * node = *it;
354 if (node->getTypeID() != TreeNode::Policy
355 && node->getTypeID() != TreeNode::PolicySet) {
356 //It is not a policy so we may be sure that we have already
357 //checked that SubjectId matches
358 //Add new node to new tree and extract attributes
360 extractAttributesFromRules(node);
361 } else { //TreeNode is a Policy or PolicySet
362 const Policy * policy =
363 dynamic_cast<const Policy *>(node->getElement());
364 //We will be needing also the attributes from target
366 extractTargetAttributes(policy);
368 LogError(" extractAttributesFromSubtree policy=NULL");
371 extractAttributesFromSubtree(node);
376 bool PolicyEvaluator::extractAttributesFromRules(const TreeNode *root)
378 Assert(root->getTypeID() == TreeNode::Rule
379 && "Tree structure, extracting attributes from node that is not a rule");
380 Rule * rule = dynamic_cast<Rule *>(root->getElement());Assert
382 //Get attributes from rule
383 rule->getAttributes(&m_attributeSet);
385 //[CR] consider returned value, because its added only to eliminate errors
389 ExtendedEffect PolicyEvaluator::evaluatePolicies(const TreeNode * root)
392 LogInfo("Error: policy tree doesn't exist. "
393 "Probably xml file is missing");
397 if (m_attributeSet.empty()) {
398 LogInfo("Warning: evaluatePolicies: attribute set was empty");
400 m_combiner->setAttributeSet(&m_attributeSet);
401 return m_combiner->combinePolicies(root);
405 int PolicyEvaluator::updatePolicy(const char* newPolicy)
407 LogError("PolicyEvaluator::updatePolicy is DEPRECATED");
408 ConfigurationManager* configMgr = ConfigurationManager::getInstance();
409 if (NULL == configMgr) {
410 LogError("ACE fatal error: failed to create configuration manager");
411 return POLICY_PARSING_ERROR;
413 int result = POLICY_PARSING_SUCCESS;
414 if (newPolicy == NULL) {
415 LogError("Policy Update: incorrect policy name");
416 return POLICY_FILE_ERROR;
418 LogDebug("Starting update policy: " << newPolicy);
421 TreeNode *backup = m_uniform_policy;
423 m_uniform_policy = parser.parse(newPolicy,
424 configMgr->getFullPathToPolicyXMLSchema());
426 if (NULL == m_uniform_policy) {
427 m_uniform_policy = backup;
428 LogError("Policy Update: corrupted policy file");
429 result = POLICY_PARSING_ERROR;
431 m_currentPolicyFile = newPolicy;
432 m_wac_policy = m_uniform_policy; //we must be able to use WAC widgets
433 m_tizen_policy = m_uniform_policy;//we must be able to use Tizen widgets
434 m_attributeSet.clear();
435 backup->releaseResources();
436 LogInfo("Policy Update: successful.");
438 AceDAO::resetDatabase(); // TODO: this is strange, but this
439 // method is deprecated so not changing
440 // it (will disappear with entire method)
441 } catch (AceDAO::Exception::DatabaseError &e) {
447 TreeNode * PolicyEvaluator::getDefaultSafePolicyTree(void)
449 Policy * policy = new Policy;
450 Rule * rule = new Rule;
451 TreeNode * mainTree = NULL,
454 policy->setCombineAlgorithm(Policy::CombineAlgorithm::DenyOverride);
455 rule->setEffect(Deny);
457 mainTree = new TreeNode(m_uniform_policy, TreeNode::Policy, policy);
458 childTree = new TreeNode(mainTree, TreeNode::Rule, rule);
459 mainTree->addChild(childTree);
461 LogError("Loading default safe policy tree");
465 void PolicyEvaluator::updatePolicy()
467 ConfigurationManager *configMgr = ConfigurationManager::getInstance();
468 Assert(NULL != configMgr && "ACE fatal error: failed to "
469 "create configuration manager");
470 AceDAO::clearPolicyCache();
471 if (NULL != m_uniform_policy) {
472 m_uniform_policy->releaseResources();
474 Parser parserWac, parserTizen;
475 m_wac_policy = parserWac.parse(
476 configMgr->getFullPathToPolicyFile(PolicyType::WAC2_0),
477 configMgr->getFullPathToPolicyXMLSchema());
478 if (NULL == m_wac_policy) {
479 LogError("ACE fatal error: cannot parse XML file (WAC policy)");
480 m_wac_policy = getDefaultSafePolicyTree();
482 m_tizen_policy = parserTizen.parse(
483 configMgr->getFullPathToPolicyFile(PolicyType::Tizen),
484 configMgr->getFullPathToPolicyXMLSchema());
485 if (NULL == m_tizen_policy) {
486 LogError("ACE fatal error: cannot parse XML file (Tizen policy)");
487 m_tizen_policy = getDefaultSafePolicyTree();
489 // Policy set is usefull for releasing all policies in case of
491 Policy * policySet = new PolicySet();
492 policySet->setCombineAlgorithm(Policy::CombineAlgorithm::DenyOverride);
493 m_uniform_policy = new TreeNode(NULL, TreeNode::PolicySet, policySet);
494 m_uniform_policy->addChild(m_wac_policy);
495 m_uniform_policy->addChild(m_tizen_policy);
497 // Creating attribute set for the first time after loading policy
498 // to speed up queries
499 m_attributeSet.clear();
500 fillAttributeWithPolicy();
503 std::string PolicyEvaluator::getCurrentPolicy()
505 LogError("PolicyEvaluator::getCurrentPolicy is DEPRECATED");
506 return m_currentPolicyFile;
509 const char * toString(Validity validity)
515 case Validity::SESSION:
517 case Validity::ALWAYS:
520 return "WRONG VALIDITY";
524 const char * toString(Verdict verdict)
527 case Verdict::VERDICT_PERMIT:
529 case Verdict::VERDICT_DENY:
531 case Verdict::VERDICT_INAPPLICABLE:
532 return "Inapplicable";
533 case Verdict::VERDICT_UNKNOWN:
535 case Verdict::VERDICT_UNDETERMINED:
536 return "Undetermined";
537 case Verdict::VERDICT_ERROR:
539 case Verdict::VERDICT_ASYNC:
542 return "Wrong verdict value";