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

Source for file InviteAuthzEngine.php

Documentation is available at InviteAuthzEngine.php

  1. <?php
  2. /**
  3.  * @copyright Copyright 2005-2010 RedIRIS, http://www.rediris.es/
  4.  *
  5.  *  This file is part of phpPoA2.
  6.  *
  7.  *  phpPoA2 is free software: you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation, either version 3 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  phpPoA2 is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with phpPoA2. If not, see <http://www.gnu.org/licenses/>.
  19.  *
  20.  * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
  21.  * @version 2.0
  22.  * @author Jaime Perez <jaime.perez@rediris.es>
  23.  * @filesource
  24.  */
  25.  
  26. /**
  27.  * Supported database types.
  28.  */
  29. define('INVITES_DBA''InviteDBADB');
  30. define('INVITES_MYSQL''InviteMySQLDB');
  31. define('INVITES_SESSION''InviteSessionDB');
  32. define('AUTHORIZED_DBA''AuthorizedDBADB');
  33. define('AUTHORIZED_MYSQL''AuthorizedMySQLDB');
  34. define('AUTHORIZED_SESSION''AuthorizedSessionDB');
  35.  
  36. /**
  37.  * This hook is executed right before it is checked whether the user was invited or not to
  38.  * continue with authorization.
  39.  * It can be used to trick the engine to believe the user was previously invited (and therefore
  40.  * forcing authorization).
  41.  * The hook receives a boolean parameter representing whether the referenced invitation was found
  42.  * or not.
  43.  *
  44.  * function invitesBeforeAuthorization(&$invite_exists);
  45.  *
  46.  * Please bear in mind that hooks must return TRUE or they'll keep other hooks from executing.
  47.  */
  48. define("INVITES_BEFORE_AUTHORIZATION""INVITES_BEFORE_AUTHORIZATION");
  49.  
  50. /**
  51.  * Invitation based authorization engine.
  52.  * @package phpPoA2
  53.  * @subpackage InviteAuthorizationEngine
  54.  */
  55.  
  56.     protected $authz_db;
  57.     protected $invites_db;
  58.     protected $valid_hooks = array(INVITES_BEFORE_AUTHORIZATION);
  59.  
  60.     /**
  61.      * Configure the authorization engine.
  62.      * @param file The configuration file.
  63.      * @param section The section of the configuration file to use.
  64.      */
  65.     public function configure($file$section{
  66.         parent::configure($file$section);
  67.  
  68.         // configure authorized DB
  69.         $db_t $this->cfg->getAuthorizedDBType();
  70.         if (class_exists($db_ttrue)) {
  71.             $this->authz_db = new $db_t($this->cfg);
  72.         }
  73.  
  74.         // configure invites DB
  75.         $db_t $this->cfg->getInvitesDBType();
  76.         if (class_exists($db_ttrue)) {
  77.             $this->invites_db = new $db_t($this->cfg);
  78.         }
  79.     }
  80.  
  81.     /**
  82.      * Check if the specified user is authorized with the given attributes.
  83.      * @param user The name of the user to check authorization for.
  84.      * @param attrs The attributes of the user to match his identity.
  85.      * @return boolean true if the user is authorized, false otherwise.
  86.      */
  87.     public function isAuthorized($user$attrs{
  88.         if (!$this->authz_db->open()) {
  89.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  90.             return false;
  91.         }
  92.  
  93.         // retrieve data
  94.         $stored $this->authz_db->fetch($user);
  95.         $this->authz_db->close();
  96.         if (!$stored// not found
  97.             trigger_error(PoAUtils::msg('cannot-fetch-key'array($user))E_USER_WARNING);
  98.             return false;
  99.         }
  100.  
  101.         // check expiration
  102.         $now time();
  103.         if ($stored['expires'&& $now $stored['expires']{
  104.             trigger_error(PoAUtils::msg('authz-expired'array($user))E_USER_WARNING);
  105.             return false;
  106.         }
  107.  
  108.         // check attributes
  109.         $rslt false;
  110.         foreach ($this->cfg->getUniqueAttributes(as $attr{
  111.             if (is_array($attr)) {
  112.                 $partial true;
  113.                 foreach ($attr as $compound{
  114.                     $partial &= isset($stored['attributes'][$compound]&&
  115.                                 isset($attrs[$compound]&&
  116.                                 $stored['attributes'][$compound=== $attrs[$compound];
  117.                 }
  118.                 $rslt |= $partial;
  119.             else {
  120.                 $rslt |= isset($stored['attributes'][$attr]&&
  121.                          isset($attrs[$attr]&&
  122.                          $stored['attributes'][$attr=== $attrs[$attr];
  123.             }
  124.             if ($rsltbreak;
  125.         }
  126.         return $rslt;
  127.     }
  128.  
  129.     /**
  130.      * Get a list of all authorized users.
  131.      * @return array The list of all users currently authorized. An empty
  132.      *  array if none found.
  133.      */
  134.     public function getAuthorizedList({
  135.         $this->registerHandler();
  136.         if (!$this->authz_db->open()) {
  137.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  138.             return false;
  139.         }
  140.  
  141.         $all $this->authz_db->fetch_all();
  142.         $this->clean();
  143.         return $this->finish($all);
  144.     }
  145.  
  146.     /**
  147.      * Get a list of all pending invitations.
  148.      * @return array The list of all pending invitations. An empty array if
  149.      *  none found.
  150.      */
  151.     public function getPendingInvites({
  152.         $this->registerHandler();
  153.         if (!$this->invites_db->open()) {
  154.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  155.             return false;
  156.         }
  157.  
  158.         $all $this->invites_db->fetch_all();
  159.         $this->clean();
  160.         return $this->finish($all);
  161.     }
  162.  
  163.     /**
  164.      * Authorize the specified user.
  165.      * @param user 
  166.      * @param attrs 
  167.      * @param ref 
  168.      * @param expires 
  169.      * @return boolean true if the user was successfully authorized, false otherwise.
  170.      */
  171.     public function authorize($user$attrs$ref$expires 0{
  172.         if (!$this->authz_db->open()) {
  173.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  174.             return false;
  175.         }
  176.  
  177.         if (!$this->invites_db->open()) {
  178.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  179.             return false;
  180.         }
  181.  
  182.         $invited $this->invites_db->check($ref);
  183.         $exists $this->authz_db->check($user);
  184.  
  185.         // run hook before actually performing authorization
  186.         $args array($invited);
  187.         $this->runHooks(INVITES_BEFORE_AUTHORIZATION$args);
  188.         $invited $args[0];
  189.  
  190.         // the user wasn't previously invited
  191.         if (!$invited{
  192.             if ($exists// the user was previously authorized
  193.                 $stored $this->authz_db->fetch($user);
  194.                 $matches true;
  195.                 foreach ($stored['attributes'as $name => $value{
  196.                     $matches &= ($attrs[$name== $value);
  197.                 }
  198.                 if ($matches// is the same user, skip
  199.                     trigger_error(PoAUtils::msg('user-already-authz'array($user))E_USER_WARNING);
  200.                     return $this->finish(false);
  201.                 }
  202.             }
  203.             trigger_error(PoAUtils::msg('invite-non-existant'array($ref))E_USER_WARNING);
  204.             return $this->finish(false);
  205.         }
  206.  
  207.         // either the invite exists or we are asked to force authorization
  208.         $invite $this->invites_db->fetch($ref);
  209.  
  210.         // check if the user has some of the mandatory attributes
  211.         $unique $this->cfg->getUniqueAttributes();
  212.         foreach ($unique as $item{
  213.             $save array()// restore on each iteration
  214.             if (is_array($item)) // a combination of attributes
  215.                 $complete true;
  216.                 foreach ($item as $name{
  217.                     $complete &= !empty($attrs[$name]);
  218.                     $save[$name$attrs[$name];
  219.                 }
  220.                 if ($complete{
  221.                     break// all attributes found, ok!
  222.                 }
  223.             else // a single attribute
  224.                 if (!empty($attrs[$item])) // attribute found, ok!
  225.                     $save[$item$attrs[$item];
  226.                     break;
  227.                 }
  228.             }
  229.         }
  230.         if (empty($save)) // no available attributes!
  231.             trigger_error(PoAUtils::msg('missing-attrs')E_USER_WARNING);
  232.             return $this->finish(false);
  233.         }
  234.  
  235.         // e-mail verification
  236.         if (!$this->emailVerify($invite['email']$attrs)) {
  237.              return $this->finish(false);
  238.         }
  239.  
  240.         // now save the user in the authorized database
  241.         if (@!$this->authz_db->replace_authorization($user$save$invite['email']$expires)) {
  242.             trigger_error(PoAUtils::msg('cannot-authorize'array($user))E_USER_WARNING);
  243.             return $this->finish(false);
  244.         }
  245.  
  246.         // remove invite
  247.         if (@!$this->invites_db->delete($ref)) {
  248.             trigger_error(PoAUtils::msg('cannot-del-invite'array($user$ref))E_USER_WARNING);
  249.             return $this->finish(false);
  250.         }
  251.  
  252.         // look for any other pending invites for this user, and delete them
  253.         $pending $this->invites_db->fetch_all();
  254.         foreach ($pending as $key => $stored{
  255.             if ($stored['email'=== $invite['email']{
  256.                 // clean up
  257.                 if (@!$this->invites_db->delete($key)) {
  258.                     trigger_error(PoAUtils::msg('cannot-del-invite'array($user$key))E_USER_WARNING);
  259.                     return $this->finish(false);
  260.                 }
  261.             }
  262.         }
  263.  
  264.         // success
  265.         trigger_error(PoAUtils::msg('user-authorized'array($user))E_USER_NOTICE);
  266.         return $this->finish(true);
  267.     }
  268.  
  269.     /**
  270.      * Revoke authorization for the specified user.
  271.      * @param 
  272.      * @return boolean true if authorization was successfully revoked, false otherwise.
  273.      */
  274.     public function revoke($mail{
  275.         if (!$this->authz_db->open()) {
  276.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  277.             return false;
  278.         }
  279.  
  280.         // JPC20110124
  281.         // Library should leave the address as is.
  282.         // sanitize email
  283.         //$mail = strtolower($mail);
  284.  
  285.         // get a list with all users authorized 
  286.         $all $this->authz_db->fetch_all();
  287.  
  288.         // iterate to find the user
  289.         foreach ($all as $key => $values{
  290.             if ($values['email'== $mail{
  291.                 // found, remove!
  292.                 return $this->finish($this->authz_db->delete($key));
  293.             }
  294.         }
  295.  
  296.         // not found!
  297.         return $this->finish(false);
  298.     }
  299.  
  300.     /**
  301.      * Send an invitation to an e-mail address (that is, send an e-mail to that
  302.      * address with instructions on how to get authorized and an URL to follow).
  303.      * @param mail The e-mail of the user.
  304.      * @param expires The time (POSIX) when authorization will expire. Use 0 if authorization
  305.      *  should never expire. Defaults to 0.
  306.      * @return boolean true if the invitation was correctly sent, false in any other case.
  307.      */
  308.     public function invite($mail$expires 0{
  309.         $this->registerHandler();
  310.         if (!$this->invites_db->open()) {
  311.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  312.             return false;
  313.         }
  314.  
  315.         // JPC20110124
  316.         // Library should leave the address as is.
  317.         // sanitize e-mail
  318.         //$mail = strtolower($mail);
  319.  
  320.         // generate random reference
  321.         $ref mt_rand();
  322.  
  323.         if (@!$this->invites_db->replace_invite($ref$mail$expires)) {
  324.             trigger_error(PoAUtils::msg('cannot-save-invite'array($mail))E_USER_WARNING);
  325.             return $this->finish(false);
  326.         }
  327.  
  328.         // setup email
  329.         $sep (!strstr($this->cfg->getInviteURL()"?")) "?" "&";
  330.         $url $this->cfg->getInviteURL().$sep."ref=".$ref;
  331.         $text preg_replace("/##URL##/"$url$this->cfg->getInviteText());
  332.         $headers "From: ".$this->cfg->getAdminEmail();
  333.         $command_params "-f ".$this->cfg->getAdminEmail();
  334.  
  335.         // send it
  336.         mail($mail$this->cfg->getInviteSubject()$text$headers$command_params);
  337.  
  338.         trigger_error(PoAUtils::msg('invite-sent-to'array($mail))E_USER_WARNING);
  339.         $this->clean();
  340.         return $this->finish(true);
  341.     }
  342.  
  343.     /**
  344.      * Remove an invitation from the database.
  345.      * @param ref The reference to the invite to remove.
  346.      * @return boolean true if the invite was removed, false otherwise.
  347.      */
  348.     public function removeInvite($ref{
  349.         $this->registerHandler();
  350.         if (!$this->invites_db->open()) {
  351.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  352.             return false;
  353.         }
  354.  
  355.         // remove the invite
  356.         $rslt $this->invites_db->delete($ref);
  357.         trigger_error(PoAUtils::msg('invite-removed'array($ref))E_USER_WARNING);
  358.         $this->clean();
  359.         return $this->finish($rslt);
  360.     }
  361.  
  362.     /**
  363.      * Perform e-mail verification for the current user according to the configuration
  364.      * for this site.
  365.      * @param mail The e-mail of the user.
  366.      * @param attrs The array of attributes of the user.
  367.      * @return boolean true if verification succeeds or was not performed, false otherwise.
  368.      */
  369.     protected function emailVerify($mail$attrs{
  370.         $mail_attr $this->cfg->getEmailVerifyAttribute();
  371.         if ($this->cfg->doEmailVerify()) {
  372.             // empty attribute, configuration error!
  373.             if (empty($mail_attr)) {
  374.                 trigger_error(PoAUtils::msg('mail-attr-err')E_USER_WARNING);
  375.                 return false;
  376.             }
  377.             // attribute not set, cannot verify
  378.             if (!isset($attrs[$mail_attr])) {
  379.                 trigger_error(PoAUtils::msg('missing-mail-attr'array($mail_attr))E_USER_WARNING);
  380.                 return false;
  381.             }
  382.  
  383.             $alg_re $this->cfg->getEmailVerifyAlgRegEx();
  384.             $val_re $this->cfg->getEmailVerifyRegEx();
  385.  
  386.             // support for attributes with multiple values
  387.             $mail_attrs $attrs[$mail_attr];
  388.             if (!is_array($attrs[$mail_attr])) {
  389.                 $mail_attrs array($attrs[$mail_attr]);
  390.             }
  391.  
  392.             $match false;
  393.             foreach ($mail_attrs as $attr_val{
  394.                 // extract function for each value
  395.                 $alg "sprintf(\"%s\",";
  396.                 if (!empty($alg_re)) {
  397.                     if (!preg_match("/".$alg_re."/"$attr_val$vals_alg)) {
  398.                         trigger_error(PoAUtils::msg('mail-attr-alg-err'array($mail_attr$attr_val))E_USER_WARNING);
  399.                         continue;
  400.                     }
  401.                     $alg $vals_alg[1]."(";
  402.                 }
  403.  
  404.                 // extract value
  405.                 if (!preg_match("/".$val_re."/"$attr_val$vals_value)) {
  406.                     trigger_error(PoAUtils::msg('mail-attr-val-err'array($mail_attr$attr_val))E_USER_WARNING);
  407.                     continue;
  408.                 }
  409.                 $received[$alg$vals_value[1];
  410.                 $match true;
  411.             }
  412.             // none of the mail attributes matched the regular expressions
  413.             if (!$match{
  414.                 return false;
  415.             }
  416.  
  417.             // check all possibilities
  418.             foreach ($received as $alg => $value{
  419.                 $computed_value = eval("return ".$alg."\"".$mail."\");");
  420.                 if ($computed_value != $value{
  421.                     // no match, continue searching
  422.                     //trigger_error(PoAUtils::msg('mail-verify-err', array($mail, $computed_value, $value)), E_USER_WARNING);
  423.                     continue;
  424.                 }
  425.                 // match found, end here
  426.                 trigger_error(PoAUtils::msg('mail-verify-ok'array($mailpreg_replace("/\(.*$/"""$alg)$value))E_USER_WARNING);
  427.                 return true;
  428.             }
  429.             // verification is enabled but we were unable to find any matching e-mail
  430.             trigger_error(PoAUtils::msg('mail-verify-err'array($mail))E_USER_WARNING);
  431.             return false;
  432.         }
  433.         // verification disabled
  434.         return true;
  435.     }
  436.  
  437.     /**
  438.      * Close databases and return the same value received as a parameter.
  439.      * @param value The value that must be returned.
  440.      * @return mixed The first param.
  441.      */
  442.     protected function finish($value{
  443.         $this->invites_db->close();
  444.         $this->authz_db->close();
  445.         return $value;
  446.     }
  447.  
  448. }
  449.  
  450. ?>

Documentation generated on Tue, 25 Jan 2011 11:24:31 +0100 by phpDocumentor 1.4.3