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]&& // attribute is stored
  115.                                 isset($attrs[$compound]&& // attribute is set
  116.                                 // attribute IS NOT an array and the value is stored
  117.                                 ((!is_array($attrs[$compound]&& $stored['attributes'][$compound=== $attrs[$compound]||
  118.                                 // attribute IS an array and the value stored is in it
  119.                                 (is_array($attrs[$compound]&& in_array($stored['attributes'][$compound]$attrs[$compound])));
  120.                 }
  121.                 $rslt |= $partial;
  122.             else {
  123.                 $rslt |= isset($stored['attributes'][$attr]&& // attribute is stored
  124.                          isset($attrs[$attr]&& // attribute is set
  125.                          // attribute IS NOT an array and the value is stored
  126.                          ((!is_array($attrs[$attr]&& $stored['attributes'][$attr=== $attrs[$attr]||
  127.                          // attribute IS an array and the value stored is in it
  128.                          (is_array($attrs[$attr]&& in_array($stored['attributes'][$attr]$attrs[$attr])));
  129.             }
  130.             if ($rsltbreak;
  131.         }
  132.         return $rslt;
  133.     }
  134.  
  135.     /**
  136.      * Get a list of all authorized users.
  137.      * @return array The list of all users currently authorized. An empty
  138.      *  array if none found.
  139.      */
  140.     public function getAuthorizedList({
  141.         $this->registerHandler();
  142.         if (!$this->authz_db->open()) {
  143.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  144.             return false;
  145.         }
  146.  
  147.         $all $this->authz_db->fetch_all();
  148.         $this->clean();
  149.         return $this->finish($all);
  150.     }
  151.  
  152.     /**
  153.      * Get a list of all pending invitations.
  154.      * @return array The list of all pending invitations. An empty array if
  155.      *  none found.
  156.      */
  157.     public function getPendingInvites({
  158.         $this->registerHandler();
  159.         if (!$this->invites_db->open()) {
  160.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  161.             return false;
  162.         }
  163.  
  164.         $all $this->invites_db->fetch_all();
  165.         $this->clean();
  166.         return $this->finish($all);
  167.     }
  168.  
  169.     /**
  170.      * Authorize the specified user.
  171.      * @param user 
  172.      * @param attrs 
  173.      * @param ref 
  174.      * @param expires 
  175.      * @return boolean true if the user was successfully authorized, false otherwise.
  176.      */
  177.     public function authorize($user$attrs$ref$expires 0{
  178.         if (!$this->authz_db->open()) {
  179.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  180.             return false;
  181.         }
  182.  
  183.         if (!$this->invites_db->open()) {
  184.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  185.             return false;
  186.         }
  187.  
  188.         $invited $this->invites_db->check($ref);
  189.         $exists $this->authz_db->check($user);
  190.  
  191.         // run hook before actually performing authorization
  192.         $args array($invited);
  193.         $this->runHooks(INVITES_BEFORE_AUTHORIZATION$args);
  194.         $invited $args[0];
  195.  
  196.         // the user wasn't previously invited
  197.         if (!$invited{
  198.             if ($exists// the user was previously authorized
  199.                 $stored $this->authz_db->fetch($user);
  200.                 $matches true;
  201.                 foreach ($stored['attributes'as $name => $value{
  202.                     $matches &= ($attrs[$name== $value);
  203.                 }
  204.                 if ($matches// is the same user, skip
  205.                     trigger_error(PoAUtils::msg('user-already-authz'array($user))E_USER_WARNING);
  206.                     return $this->finish(false);
  207.                 }
  208.             }
  209.             trigger_error(PoAUtils::msg('invite-non-existant'array($ref))E_USER_WARNING);
  210.             return $this->finish(false);
  211.         }
  212.  
  213.         // either the invite exists or we are asked to force authorization
  214.         $invite $this->invites_db->fetch($ref);
  215.  
  216.         // check if the user has some of the mandatory attributes
  217.         $unique $this->cfg->getUniqueAttributes();
  218.         foreach ($unique as $item{
  219.             $save array()// restore on each iteration
  220.             if (is_array($item)) // a combination of attributes
  221.                 $complete true;
  222.                 foreach ($item as $name{
  223.                     $complete &= !empty($attrs[$name]);
  224.                     $value $attrs[$name];
  225.                     // multiple values?
  226.                     if (is_array($attrs[$name])) {
  227.                         $value $attrs[$name][0];
  228.                     }
  229.                     $save[$name$value;
  230.                 }
  231.                 if ($complete{
  232.                     break// all attributes found, ok!
  233.                 }
  234.             else // a single attribute
  235.                 if (!empty($attrs[$item])) // attribute found, ok!
  236.                     $value $attrs[$item];
  237.                     // multiple values?
  238.                     if (is_array($attrs[$item])) {
  239.                         $value $attrs[$item][0];
  240.                     }
  241.                     $save[$item$value;
  242.                     break;
  243.                 }
  244.             }
  245.         }
  246.         if (empty($save)) // no available attributes!
  247.             trigger_error(PoAUtils::msg('missing-attrs')E_USER_WARNING);
  248.             return $this->finish(false);
  249.         }
  250.  
  251.         // e-mail verification
  252.         if (!$this->emailVerify($invite['email']$attrs)) {
  253.              return $this->finish(false);
  254.         }
  255.  
  256.         // now save the user in the authorized database
  257.         if (@!$this->authz_db->replace_authorization($user$save$invite['email']$expires)) {
  258.             trigger_error(PoAUtils::msg('cannot-authorize'array($user))E_USER_WARNING);
  259.             return $this->finish(false);
  260.         }
  261.  
  262.         // remove invite
  263.         if (@!$this->invites_db->delete($ref)) {
  264.             trigger_error(PoAUtils::msg('cannot-del-invite'array($user$ref))E_USER_WARNING);
  265.             return $this->finish(false);
  266.         }
  267.  
  268.         // look for any other pending invites for this user, and delete them
  269.         $pending $this->invites_db->fetch_all();
  270.         foreach ($pending as $key => $stored{
  271.             if ($stored['email'=== $invite['email']{
  272.                 // clean up
  273.                 if (@!$this->invites_db->delete($key)) {
  274.                     trigger_error(PoAUtils::msg('cannot-del-invite'array($user$key))E_USER_WARNING);
  275.                     return $this->finish(false);
  276.                 }
  277.             }
  278.         }
  279.  
  280.         // success
  281.         trigger_error(PoAUtils::msg('user-authorized'array($user))E_USER_NOTICE);
  282.         return $this->finish(true);
  283.     }
  284.  
  285.     /**
  286.      * Revoke authorization for the specified user.
  287.      * @param 
  288.      * @return boolean true if authorization was successfully revoked, false otherwise.
  289.      */
  290.     public function revoke($mail{
  291.         if (!$this->authz_db->open()) {
  292.             trigger_error(PoAUtils::msg('cannot-open-authz-db')E_USER_WARNING);
  293.             return false;
  294.         }
  295.  
  296.         // JPC20110124
  297.         // Library should leave the address as is.
  298.         // sanitize email
  299.         //$mail = strtolower($mail);
  300.  
  301.         // get a list with all users authorized 
  302.         $all $this->authz_db->fetch_all();
  303.  
  304.         // iterate to find the user
  305.         foreach ($all as $key => $values{
  306.             if ($values['email'== $mail{
  307.                 // found, remove!
  308.                 return $this->finish($this->authz_db->delete($key));
  309.             }
  310.         }
  311.  
  312.         // not found!
  313.         return $this->finish(false);
  314.     }
  315.  
  316.     /**
  317.      * Send an invitation to an e-mail address (that is, send an e-mail to that
  318.      * address with instructions on how to get authorized and an URL to follow).
  319.      * @param mail The e-mail of the user.
  320.      * @param expires The time (POSIX) when authorization will expire. Use 0 if authorization
  321.      *  should never expire. Defaults to 0.
  322.      * @return boolean true if the invitation was correctly sent, false in any other case.
  323.      */
  324.     public function invite($mail$expires 0{
  325.         $this->registerHandler();
  326.         if (!$this->invites_db->open()) {
  327.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  328.             return false;
  329.         }
  330.  
  331.         // JPC20110124
  332.         // Library should leave the address as is.
  333.         // sanitize e-mail
  334.         //$mail = strtolower($mail);
  335.  
  336.         // generate random reference
  337.         $ref mt_rand();
  338.  
  339.         if (@!$this->invites_db->replace_invite($ref$mail$expires)) {
  340.             trigger_error(PoAUtils::msg('cannot-save-invite'array($mail))E_USER_WARNING);
  341.             return $this->finish(false);
  342.         }
  343.  
  344.         // setup email
  345.         $sep (!strstr($this->cfg->getInviteURL()"?")) "?" "&";
  346.         $url $this->cfg->getInviteURL().$sep."ref=".$ref;
  347.         $text preg_replace("/##URL##/"$url$this->cfg->getInviteText());
  348.         $headers "From: ".$this->cfg->getAdminEmail();
  349.         $command_params "-f ".$this->cfg->getAdminEmail();
  350.  
  351.         // send it
  352.         mail($mail$this->cfg->getInviteSubject()$text$headers$command_params);
  353.  
  354.         trigger_error(PoAUtils::msg('invite-sent-to'array($mail))E_USER_WARNING);
  355.         $this->clean();
  356.         return $this->finish(true);
  357.     }
  358.  
  359.     /**
  360.      * Remove an invitation from the database.
  361.      * @param ref The reference to the invite to remove.
  362.      * @return boolean true if the invite was removed, false otherwise.
  363.      */
  364.     public function removeInvite($ref{
  365.         $this->registerHandler();
  366.         if (!$this->invites_db->open()) {
  367.             trigger_error(PoAUtils::msg('cannot-open-inv-db')E_USER_WARNING);
  368.             return false;
  369.         }
  370.  
  371.         // remove the invite
  372.         $rslt $this->invites_db->delete($ref);
  373.         trigger_error(PoAUtils::msg('invite-removed'array($ref))E_USER_WARNING);
  374.         $this->clean();
  375.         return $this->finish($rslt);
  376.     }
  377.  
  378.     /**
  379.      * Perform e-mail verification for the current user according to the configuration
  380.      * for this site.
  381.      * @param mail The e-mail of the user.
  382.      * @param attrs The array of attributes of the user.
  383.      * @return boolean true if verification succeeds or was not performed, false otherwise.
  384.      */
  385.     protected function emailVerify($mail$attrs{
  386.         $mail_attr $this->cfg->getEmailVerifyAttribute();
  387.         if ($this->cfg->doEmailVerify()) {
  388.             // empty attribute, configuration error!
  389.             if (empty($mail_attr)) {
  390.                 trigger_error(PoAUtils::msg('mail-attr-err')E_USER_WARNING);
  391.                 return false;
  392.             }
  393.             // attribute not set, cannot verify
  394.             if (!isset($attrs[$mail_attr])) {
  395.                 trigger_error(PoAUtils::msg('missing-mail-attr'array($mail_attr))E_USER_WARNING);
  396.                 return false;
  397.             }
  398.  
  399.             $alg_re $this->cfg->getEmailVerifyAlgRegEx();
  400.             $val_re $this->cfg->getEmailVerifyRegEx();
  401.  
  402.             // support for attributes with multiple values
  403.             $mail_attrs $attrs[$mail_attr];
  404.             if (!is_array($attrs[$mail_attr])) {
  405.                 $mail_attrs array($attrs[$mail_attr]);
  406.             }
  407.  
  408.             $match false;
  409.             foreach ($mail_attrs as $attr_val{
  410.                 // extract function for each value
  411.                 $alg "sprintf(\"%s\",";
  412.                 if (!empty($alg_re)) {
  413.                     if (!preg_match("/".$alg_re."/"$attr_val$vals_alg)) {
  414.                         trigger_error(PoAUtils::msg('mail-attr-alg-err'array($mail_attr$attr_val))E_USER_WARNING);
  415.                         continue;
  416.                     }
  417.                     $alg $vals_alg[1]."(";
  418.                 }
  419.  
  420.                 // extract value
  421.                 if (!preg_match("/".$val_re."/"$attr_val$vals_value)) {
  422.                     trigger_error(PoAUtils::msg('mail-attr-val-err'array($mail_attr$attr_val))E_USER_WARNING);
  423.                     continue;
  424.                 }
  425.                 $received[array($alg$vals_value[1]);
  426.                 $match true;
  427.             }
  428.             // none of the mail attributes matched the regular expressions
  429.             if (!$match{
  430.                 return false;
  431.             }
  432.  
  433.             // check all possibilities
  434.             foreach ($received as $value{
  435.                 $alg $value[0];
  436.                 $value $value[1];
  437.                 $computed_value = eval("return ".$alg."\"".$mail."\");");
  438.                 if ($computed_value != $value{
  439.                     // no match, continue searching
  440.                     continue;
  441.                 }
  442.                 // match found, end here
  443.                 trigger_error(PoAUtils::msg('mail-verify-ok'array($mailpreg_replace("/\(.*$/"""$alg)$value))E_USER_WARNING);
  444.                 return true;
  445.             }
  446.             // verification is enabled but we were unable to find any matching e-mail
  447.             trigger_error(PoAUtils::msg('mail-verify-err'array($mail))E_USER_WARNING);
  448.             return false;
  449.         }
  450.         // verification disabled
  451.         return true;
  452.     }
  453.  
  454.     /**
  455.      * Close databases and return the same value received as a parameter.
  456.      * @param value The value that must be returned.
  457.      * @return mixed The first param.
  458.      */
  459.     protected function finish($value{
  460.         $this->invites_db->close();
  461.         $this->authz_db->close();
  462.         return $value;
  463.     }
  464.  
  465. }
  466.  
  467. ?>

Documentation generated on Tue, 14 Jun 2011 12:22:09 +0200 by phpDocumentor 1.4.3