Przeglądaj źródła

#888 Security on the portal incompatible with customizations (regression introduced in 2.0.2), now requires to define PORTAL_USERREQUEST_DISPLAY_QUERY and PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3086 a333f486-631f-4898-b8df-5754b55c2be0
romainq 11 lat temu
rodzic
commit
95bc0b3309

+ 1 - 18
application/portalwebpage.class.inc.php

@@ -793,24 +793,7 @@ EOF
 			}
 		}
 
-		$sOQL = "SELECT $sClass WHERE org_id = :org_id";
-		$oSearch = DBObjectSearch::FromOQL($sOQL);
-		$iUser = UserRights::GetContactId();
-		if ($iUser > 0 && !IsPowerUser())
-		{
-			$oSearch->AddCondition('caller_id', $iUser);
-		}
-		$oSearch->AddCondition('id', $iId);
-		
-		$oContact = MetaModel::GetObject('Contact', $iUser, false); // false => Can fail
-		if (!is_object($oContact))
-		{
-			throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser'));
-		}
-		
-		$oSet = new DBObjectSet($oSearch, array(), array('org_id' => $oContact->Get('org_id')));
-		
-		$oObj = $oSet->Fetch();
+		$oObj = MetaModel::GetObject($sClass, $iId, false);		
 		if (!is_object($oObj))
 		{
 			throw new Exception("Could not find the object $sClass/$iId");

+ 4 - 0
datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml

@@ -17,6 +17,8 @@
     <constant id="PORTAL_USERREQUEST_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
     <constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
     <constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
+    <constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
+    <constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
     <constant id="PORTAL_INCIDENT_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
     <constant id="PORTAL_INCIDENT_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
     <constant id="PORTAL_INCIDENT_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
@@ -24,6 +26,8 @@
     <constant id="PORTAL_INCIDENT_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
     <constant id="PORTAL_INCIDENT_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
     <constant id="PORTAL_INCIDENT_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
+    <constant id="PORTAL_INCIDENT_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
+    <constant id="PORTAL_INCIDENT_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id]]></constant>
     <constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
     <constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
   </constants>

+ 2 - 0
datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml

@@ -17,6 +17,8 @@
     <constant id="PORTAL_TICKETS_SEARCH_CRITERIA" xsi:type="string" _delta="define"><![CDATA[ref,start_date,close_date,service_id,caller_id]]></constant>
     <constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
     <constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
+    <constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
+    <constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
     <constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
     <constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
   </constants>

+ 42 - 0
portal/index.php

@@ -50,6 +50,46 @@ function GetTicketClasses()
 	return $aClasses;
 } 
 
+
+/**
+ * Helper to protect the portal against malicious usages
+ * Throws an exception if the current user is not allowed to view the object details  
+ */
+function ValidateObject($oObject)
+{
+	if (IsPowerUser())
+	{
+		$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_POWERUSER_QUERY';
+	}
+	else
+	{
+		$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_QUERY';
+	}
+	if (defined($sValidationDefine))
+	{
+		$sValidationOql = constant($sValidationDefine);
+		$oSearch = DBObjectSearch::FromOQL($sValidationOql);
+		$oSearch->AddCondition('id', $oObject->GetKey());
+
+		if ($iUser = UserRights::GetContactId())
+		{
+			$oContact = MetaModel::GetObject('Contact', $iUser);
+			$aArgs = $oContact->ToArgs('contact');
+		}
+		else
+		{
+			$aArgs = array();
+		}
+	
+		$oSet = new DBObjectSet($oSearch, array(), $aArgs);
+		if ($oSet->Count() == 0)
+		{
+			throw new SecurityException('You are not allowed to access the object '.get_class($oObject).'::'.$oObject->GetKey());
+		}
+	}
+}
+
+
 /**
  * Helper to get the relevant constant 
  */
@@ -1249,6 +1289,7 @@ try
 				$oP->set_title(Dict::S('Portal:TitleDetailsFor_Request'));
 				DisplayMainMenu($oP);
 				$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
+				ValidateObject($oObj);
 				DisplayObject($oP, $oObj, $oUserOrg);
 				break;
 				
@@ -1258,6 +1299,7 @@ try
 				if (!MetaModel::DBIsReadOnly())
 				{
 					$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
+					ValidateObject($oObj);
 					$aAttList = array(
 						GetConstant(get_class($oObj), 'PUBLIC_LOG'),
 						'user_satisfaction',

+ 2 - 0
portal/readme.txt

@@ -41,6 +41,8 @@ PORTAL_<TICKET-CLASS>_TYPE: optional attribute to be set with the value of "requ
 PORTAL_<TICKET-CLASS>_LIST_ZLIST: list of attribute displayed in the lists (opened and resolved)
 PORTAL_<TICKET-CLASS>_CLOSED_ZLIST: list of attribute displayed in the list of closed tickets
 PORTAL_<TICKET-CLASS>_DETAILS_ZLIST: selection and presentation of attributes in the page that shows their details
+PORTAL_<TICKET-CLASS>_DISPLAY_QUERY: selection of displayable objects (use parameters contact->attcode to check things against the user/contact)
+PORTAL_<TICKET-CLASS>_DISPLAY_POWERUSER_QUERY: selection of displayable objects for power users (use parameters contact->attcode to check things against the user/contact)
 
 
 How to add a type of ticket (example: Incident)