Zikula_Core
[ class tree: Zikula_Core ] [ index: Zikula_Core ] [ all elements ]

Source for file SecurityUtil.class.php

Documentation is available at SecurityUtil.class.php

  1. <?php
  2. /**
  3.  * Zikula Application Framework
  4.  *
  5.  * @copyright (c) 2001, Zikula Development Team
  6.  * @link http://www.zikula.org
  7.  * @version $Id: SecurityUtil.class.php 24342 2008-06-06 12:03:14Z markwest $
  8.  * @license GNU/GPL - http://www.gnu.org/copyleft/gpl.html
  9.  * @package Zikula_Core
  10.  */
  11.  
  12. /**
  13.  * SecurityUtil
  14.  *
  15.  * @package Zikula_Core
  16.  * @subpackage SecurityUtil
  17.  * @author Drak
  18.  */
  19. {
  20.     /**
  21.      * Check permissions
  22.      *
  23.      * @param string $component 
  24.      * @param string $instance 
  25.      * @param string $level 
  26.      * @param string $user 
  27.      * @return bool 
  28.      */
  29.     function checkPermission($component=null$instance=null$level=null$user=null)
  30.     {
  31.         static $groupperms array();
  32.  
  33.         if (!is_numeric($level)) {
  34.             return pn_exit ("Invalid security level [$level] received in SecurityUtil::checkPermission");
  35.         }
  36.  
  37.         if (!$user{
  38.             $user pnUserGetVar('uid');
  39.         }
  40.  
  41.         if (!isset($GLOBALS['authinfogathered'][$user]|| (int)$GLOBALS['authinfogathered'][$user== 0{
  42.             $groupperms[$userSecurityUtil::getAuthInfo($user)// First time here - get auth info
  43.             if (count($groupperms[$user]== 0{
  44.                 return false// No permissions
  45.             }
  46.         }
  47.  
  48.         $res SecurityUtil::getSecurityLevel($groupperms[$user]$component$instance>= $level;
  49.  
  50.         // if the check failed, we save the info so that LogUtil has it readily available
  51.         if (!$res{
  52.             global $PNRuntime;
  53.             $PNRuntime['security']['last_failed_check']['component'$component;
  54.             $PNRuntime['security']['last_failed_check']['instance']  $instance;
  55.             $PNRuntime['security']['last_failed_check']['level']     $level;
  56.             $PNRuntime['security']['last_failed_check']['user']      $user;
  57.         }
  58.  
  59.         return $res;
  60.     }
  61.  
  62.  
  63.     /**
  64.      * register a permission schema
  65.      *
  66.      * @param string $component 
  67.      * @param string $schema 
  68.      * @return bool 
  69.      */
  70.     function registerPermissionSchema($component$schema)
  71.     {
  72.         return pnSecAddSchema($component$schema);
  73.     }
  74.  
  75.  
  76.     /**
  77.      * confirm auth key
  78.      *
  79.      * @param string $modname 
  80.      * @param string $varname 
  81.      *
  82.      * @return bool 
  83.      */
  84.     function confirmAuthKey($modname=''$varname='authid')
  85.     {
  86.         if (!$varname{
  87.             $varname 'authid';
  88.     }
  89.  
  90.         $authid FormUtil::getPassedValue($varname);
  91.  
  92.         if (empty($modname)) {
  93.             $modname pnModGetName();
  94.         }
  95.  
  96.         // get the module info
  97.         $modinfo pnModGetInfo(pnModGetIDFromName($modname));
  98.  
  99.         // Regenerate static part of key
  100.         $key SessionUtil::getVar('rand'strtolower($modinfo['name']);
  101.  
  102.         // validate useragent
  103.         if (pnConfigGetVar('sessionauthkeyua')) {
  104.             $useragent sha1(pnServerGetVar('HTTP_USER_AGENT'));
  105.             if (SessionUtil::getVar('useragent'!= $useragent{
  106.                 return false;
  107.             }
  108.         }
  109.  
  110.         // Test works because timestamp is embedded in authkey and appended
  111.         // at the end of the authkey, so we can test validity of authid as
  112.         // well as the number of seconds elapsed since generation.
  113.         $keyexpiry = (int)pnConfigGetVar('keyexpiry');
  114.         $timestamp ($keyexpiry substr($authid40strlen($authid)) '');
  115.         $key .= $timestamp;
  116.         // check build key against authid
  117.         if (sha1($key== substr($authid040)) {
  118.             // now test if time expired
  119.             $elapsedTime = (int)((int)$timestamp time($timestamp$keyexpiry-1);
  120.             if ($elapsedTime $keyexpiry{
  121.                 SessionUtil::setVar('rand'RandomUtil::getString(3240falsetruetruefalsetruetruefalse));
  122.                 return true;
  123.             }
  124.         }
  125.         return false;
  126.     }
  127.  
  128.  
  129.     /**
  130.      * generate auth key
  131.      *
  132.      * @param string $modname module name
  133.      * @return string an encrypted key for use in authorisation of operations
  134.      */
  135.     function generateAuthKey($modname '')
  136.     {
  137.         // since we need sessions for authorisation keys we should check
  138.         // if a session exists and if not create one
  139.         SessionUtil::requireSession();
  140.  
  141.         if (empty($modname)) {
  142.             $modname pnModGetName();
  143.         }
  144.  
  145.         // get the module info
  146.         $modinfo pnModGetInfo(pnModGetIDFromName($modname));
  147.  
  148.         $key SessionUtil::getVar('rand'strtolower($modinfo['name']);
  149.         if (pnConfigGetVar('keyexpiry'0{
  150.             $timestamp time();
  151.             $authid sha1($key.$timestamp$timestamp;
  152.         else {
  153.             $authid sha1($key);
  154.         }
  155.  
  156.         // Return encrypted key
  157.         return $authid;
  158.     }
  159.  
  160.  
  161.     /**
  162.      * get auth info
  163.      *
  164.      * @param unknown_type $user 
  165.      * @return array two element array of user and group permissions
  166.      */
  167.     function getAuthInfo($user=null)
  168.     {
  169.         // Table columns we use - pnModDBInfoLoad is done in pnInit
  170.         $pntable pnDBGetTables();
  171.         $groupmembershipcolumn $pntable['group_membership_column'];
  172.         $grouppermcolumn $pntable['group_perms_column'];
  173.  
  174.         // Empty arrays
  175.         $groupperms array();
  176.  
  177.         $uids[= -1;
  178.         // Get user ID
  179.         if (!isset($user)) {
  180.             if (!pnUserLoggedIn()) {
  181.                 // Unregistered UID
  182.                 $uids[0;
  183.                 $vars['Active User''unregistered';
  184.             else {
  185.                 $uids[pnUserGetVar('uid');
  186.                 $vars['Active User'pnUserGetVar('uid');
  187.             }
  188.         else {
  189.             $uids[$user;
  190.             $vars['Active User'$user;
  191.         }
  192.         $uids implode(','$uids);
  193.  
  194.         // Get all groups that user is in
  195.         $where "WHERE $groupmembershipcolumn[uid] IN (DataUtil::formatForStore($uids')';
  196.         $fldArray DBUtil::selectFieldArray('group_membership''gid'$where);
  197.         if ($fldArray === false{
  198.             return $groupperms;
  199.         }
  200.  
  201.         static $usergroups array();
  202.         if (!$usergroups{
  203.             $usergroups[= -1;
  204.             if (!pnUserLoggedIn()) {
  205.                 $usergroups[0// Unregistered GID
  206.             }
  207.         }
  208.  
  209.         $allgroups array_merge ($usergroups$fldArray);
  210.         $allgroups implode(','$allgroups);
  211.  
  212.         // Get all group permissions
  213.         $where    "WHERE $grouppermcolumn[gid] IN (DataUtil::formatForStore($allgroups')';
  214.         $orderBy  "ORDER BY $grouppermcolumn[sequence]";
  215.         $objArray DBUtil::selectObjectArray('group_perms'$where$orderBy);
  216.         if (!$objArray{
  217.             return $groupperms;
  218.         }
  219.  
  220.         foreach ($objArray as $obj{
  221.             $component SecurityUtil::_fixsecuritystring($obj['component']);
  222.             $instance  SecurityUtil::_fixsecuritystring($obj['instance']);
  223.             $level     SecurityUtil::_fixsecuritystring($obj['level']);
  224.             // Search/replace of special names
  225.             preg_match_all('/<([^>]+)>/'$instance$res);
  226.             $size count($res[1]);
  227.             for($i=0$i<$size$i++{
  228.                 $instance preg_replace('/<([^>]+)>/'$vars[$res[1][$i]]$instance1);
  229.             }
  230.             $groupperms[array('component' => $component,
  231.                                   'instance'  => $instance,
  232.                                   'level'     => $level);
  233.         }
  234.  
  235.         // we've now got the permissions info
  236.         $GLOBALS['authinfogathered'][$user1;
  237.         return $groupperms;
  238.     }
  239.  
  240.  
  241.     /**
  242.      * get security level
  243.      *
  244.      * @param array $perms 
  245.      * @param string $component 
  246.      * @param string $instance 
  247.      * @return int matching security level
  248.      */
  249.     function getSecurityLevel($perms$component$instance)
  250.     {
  251.         $level ACCESS_INVALID;
  252.  
  253.         // If we get a test component or instance purely consisting of ':' signs
  254.         // then it counts as blank
  255.         //itevo
  256.         if ($component == str_repeat(':'strlen($component)) ) {
  257.             $component '';
  258.         }
  259.         if ($instance == str_repeat(':'strlen($instance)) ) {
  260.             $instance '';
  261.         }
  262.  
  263.         // Test for generic permission
  264.         if ((empty($component)) && (empty($instance))) {
  265.             // Looking for best permission
  266.             foreach ($perms as $perm{
  267.                 if ($perm['level'$level{
  268.                     $level $perm['level'];
  269.                 }
  270.             }
  271.             return $level;
  272.         }
  273.  
  274.         // Test for generic instance
  275.         // additional fixes by BMW [larsneo]
  276.         // if the instance is empty, then we're looking for the per-module
  277.         // permissions.
  278.         if (empty($instance)) {
  279.             // if $instance is empty, then there must be a component.
  280.             // Looking for best permission
  281.             foreach ($perms as $perm{
  282.                 // component check
  283.                 if (!preg_match("=^$perm[component]$="$component)) {
  284.                     continue// component doestn't match.
  285.                 }
  286.  
  287.                 // check that the instance matches :: or '' (nothing)
  288.                 if ((preg_match("=^$perm[instance]$="'::'||
  289.                        preg_match("=^$perm[instance]$=",'')) ) {
  290.                     continue// instance does not match
  291.                 }
  292.  
  293.                 // We have a match - set the level and quit
  294.                 $level $perm['level'];
  295.                 break;
  296.  
  297.             }
  298.             return $level;
  299.         }
  300.  
  301.         // Normal permissions check
  302.         // there *is* a $instance at this point.
  303.         foreach ($perms as $perm{
  304.  
  305.             // if there is a component, check that it matches
  306.             if ( ($component != ''&&
  307.                  (!preg_match("=^$perm[component]$="$component)) ) {
  308.                 // component exists, and doestn't match.
  309.                 continue;
  310.             }
  311.  
  312.             // Confirm that instance matches
  313.             if (!preg_match("=^$perm[instance]$="$instance)) {
  314.                 // instance does not match
  315.                 continue;
  316.             }
  317.  
  318.             // We have a match - set the level and quit looking
  319.             $level $perm['level'];
  320.             break;
  321.         }
  322.  
  323.         return $level;
  324.     }
  325.  
  326.  
  327.     /**
  328.      * fix security string
  329.      *
  330.      * @access private
  331.      * @param string $string 
  332.      * @return string 
  333.      */
  334.     function _fixsecuritystring($string)
  335.     {
  336.         if (empty($string)) {
  337.             $string '.*';
  338.         }
  339.         if (strpos($string':'=== 0{
  340.             $string '.*' $string;
  341.         }
  342.         $string str_replace('::'':.*:'$string);
  343.         if (strrpos($string':'=== strlen($string1{
  344.             $string $string '.*';
  345.         }
  346.         return $string;
  347.     }
  348.  
  349.  
  350.     /**
  351.      * sign data object leaving data clearly visible
  352.      *
  353.      * @param unknown_type $data 
  354.      * @return serialized string of signed data
  355.      */
  356.     function signData($data)
  357.     {
  358.         $key pnConfigGetVar('signingkey');
  359.         $unsignedData serialize($data);
  360.         $signature sha1($unsignedData.$key);
  361.         $signedData serialize(array($unsignedData$signature));
  362.  
  363.         return $signedData;
  364.     }
  365.  
  366.  
  367.     /**
  368.      * verify signed data object
  369.      *
  370.      * @param string of serialized $data
  371.      * @return mixed array or string of data if true or bool false if false
  372.      */
  373.     function checkSignedData($data)
  374.     {
  375.         $key pnConfigGetVar('signingkey');
  376.         $signedData unserialize($data);
  377.         $signature sha1($signedData[0].$key);
  378.         if ($signature != $signedData[1]{
  379.             return false;
  380.         }
  381.  
  382.         return unserialize($signedData[0]);
  383.     }
  384.  
  385. }

Documentation generated on Fri, 18 Jul 2008 21:56:46 +0200 by phpDocumentor 1.4.1