Source for file auth.php

Documentation is available at auth.php

  1. <?php
  2.  
  3. /**
  4.  * auth.php
  5.  *
  6.  * Contains functions used to do authentication.
  7.  * 
  8.  * Dependencies:
  9.  *  functions/global.php
  10.  *  functions/strings.php.
  11.  *
  12.  * @copyright &copy; 1999-2006 The SquirrelMail Project Team
  13.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  14.  * @version $Id: auth.php,v 1.59 2006/08/05 08:22:45 tokul Exp $
  15.  * @package squirrelmail
  16.  */
  17.  
  18.  
  19. /**
  20.  * Detect whether user is logged in
  21.  *
  22.  * Function is similar to is_logged_in() function. If user is logged in, function
  23.  * returns true. If user is not logged in or session is expired, function saves $_POST
  24.  * and $PHP_SELF in session and returns false. POST information is saved in
  25.  * 'session_expired_post' variable, PHP_SELF is saved in 'session_expired_location'.
  26.  *
  27.  * Script that uses this function instead of is_logged_in() function, must handle user
  28.  * level messages.
  29.  * @return boolean 
  30.  * @since 1.5.1
  31.  */
  32. function sqauth_is_logged_in({
  33.     if sqsession_is_registered('user_is_logged_in') ) {
  34.         return true;
  35.     }
  36.  
  37.     //  First we store some information in the new session to prevent
  38.     //  information-loss.
  39.     sqGetGlobalVar('PHP_SELF'$PHP_SELFSQ_SERVER);
  40.  
  41.     $session_expired_post $_POST;
  42.     $session_expired_location $PHP_SELF;
  43.     if (!sqsession_is_registered('session_expired_post')) {
  44.         sqsession_register($session_expired_post,'session_expired_post');
  45.     }
  46.     if (!sqsession_is_registered('session_expired_location')) {
  47.         sqsession_register($session_expired_location,'session_expired_location');
  48.     }
  49.  
  50.     return false;
  51. }
  52.  
  53. /**
  54.  * Reads and decodes stored user password information
  55.  *
  56.  * Direct access to password information is deprecated.
  57.  * @return string password in plain text
  58.  * @since 1.5.1
  59.  */
  60. function sqauth_read_password({
  61.     sqgetGlobalVar('key',         $key,       SQ_COOKIE);
  62.     sqgetGlobalVar('onetimepad',  $onetimepad,SQ_SESSION);
  63.  
  64.     return OneTimePadDecrypt($key$onetimepad);
  65. }
  66.  
  67. /**
  68.  * Saves or updates user password information
  69.  *
  70.  * This function is used to update password information that SquirrelMail
  71.  * stores during existing web session. It does not modify password stored
  72.  * in authentication system used by IMAP server.
  73.  *
  74.  * Function must be called before any html output started. Direct access
  75.  * to password information is deprecated. Saved password information is
  76.  * available only to next executed SquirrelMail script. If your script needs
  77.  * access to saved password after sqauth_save_password() call, use returned
  78.  * OTP encrypted key.
  79.  * @param string $pass password
  80.  * @return string password encrypted with OTP. In case script wants to access
  81.  *   password information before reloading page.
  82.  * @since 1.5.1
  83.  */
  84. function sqauth_save_password($pass{
  85.     sqgetGlobalVar('base_uri',    $base_uri,   SQ_SESSION);
  86.  
  87.     $onetimepad OneTimePadCreate(strlen($pass));
  88.     sqsession_register($onetimepad,'onetimepad');
  89.     $key OneTimePadEncrypt($pass$onetimepad);
  90.     sqsetcookie('key'$keyfalse$base_uri);
  91.     return $key;
  92. }
  93.  
  94. /**
  95.  * Given the challenge from the server, supply the response using cram-md5 (See
  96.  * RFC 2195 for details)
  97.  *
  98.  * @param string $username User ID
  99.  * @param string $password User password supplied by User
  100.  * @param string $challenge The challenge supplied by the server
  101.  * @return string The response to be sent to the IMAP server
  102.  * @since 1.4.0
  103.  */
  104. function cram_md5_response ($username,$password,$challenge{
  105.     $challenge=base64_decode($challenge);
  106.     $hash=bin2hex(hmac_md5($challenge,$password));
  107.     $response=base64_encode($username " " $hash"\r\n";
  108.     return $response;
  109. }
  110.  
  111. /**
  112.  * Return Digest-MD5 response.
  113.  * Given the challenge from the server, calculate and return the
  114.  * response-string for digest-md5 authentication.  (See RFC 2831 for more
  115.  * details)
  116.  *
  117.  * @param string $username User ID
  118.  * @param string $password User password supplied by User
  119.  * @param string $challenge The challenge supplied by the server
  120.  * @param string $service The service name, usually 'imap'; it is used to
  121.  *    define the digest-uri.
  122.  * @param string $host The host name, usually the server's FQDN; it is used to
  123.  *    define the digest-uri.
  124.  * @return string The response to be sent to the IMAP server
  125.  * @since 1.4.0
  126.  */
  127. function digest_md5_response ($username,$password,$challenge,$service,$host{
  128.     $result=digest_md5_parse_challenge($challenge);
  129.  
  130.     // verify server supports qop=auth
  131.     // $qop = explode(",",$result['qop']);
  132.     //if (!in_array("auth",$qop)) {
  133.     // rfc2831: client MUST fail if no qop methods supported
  134.     // return false;
  135.     //}
  136.     $cnonce base64_encode(bin2hex(hmac_md5(microtime())));
  137.     $ncount "00000001";
  138.  
  139.     /* This can be auth (authentication only), auth-int (integrity protection), or
  140.        auth-conf (confidentiality protection).  Right now only auth is supported.
  141.        DO NOT CHANGE THIS VALUE */
  142.     $qop_value "auth";
  143.  
  144.     $digest_uri_value $service '/' $host;
  145.  
  146.     // build the $response_value
  147.     //FIXME This will probably break badly if a server sends more than one realm
  148.     $string_a1 utf8_encode($username).":";
  149.     $string_a1 .= utf8_encode($result['realm']).":";
  150.     $string_a1 .= utf8_encode($password);
  151.     $string_a1 hmac_md5($string_a1);
  152.     $A1 $string_a1 ":" $result['nonce'":" $cnonce;
  153.     $A1 bin2hex(hmac_md5($A1));
  154.     $A2 "AUTHENTICATE:$digest_uri_value";
  155.     // If qop is auth-int or auth-conf, A2 gets a little extra
  156.     if ($qop_value != 'auth'{
  157.         $A2 .= ':00000000000000000000000000000000';
  158.     }
  159.     $A2 bin2hex(hmac_md5($A2));
  160.  
  161.     $string_response $result['nonce'':' $ncount ':' $cnonce ':' $qop_value;
  162.     $response_value bin2hex(hmac_md5($A1.":".$string_response.":".$A2));
  163.  
  164.     $reply 'charset=utf-8,username="' $username '",realm="' $result["realm"'",';
  165.     $reply .= 'nonce="' $result['nonce''",nc=' $ncount ',cnonce="' $cnonce '",';
  166.     $reply .= "digest-uri=\"$digest_uri_value\",response=$response_value";
  167.     $reply .= ',qop=' $qop_value;
  168.     $reply base64_encode($reply);
  169.     return $reply "\r\n";
  170.  
  171. }
  172.  
  173. /**
  174.  * Parse Digest-MD5 challenge.
  175.  * This function parses the challenge sent during DIGEST-MD5 authentication and
  176.  * returns an array. See the RFC for details on what's in the challenge string.
  177.  *
  178.  * @param string $challenge Digest-MD5 Challenge
  179.  * @return array Digest-MD5 challenge decoded data
  180.  * @since 1.4.0
  181.  */
  182. function digest_md5_parse_challenge($challenge{
  183.     $challenge=base64_decode($challenge);
  184.     while (isset($challenge)) {
  185.         if ($challenge{0== ','// First char is a comma, must not be 1st time through loop
  186.             $challenge=substr($challenge,1);
  187.         }
  188.         $key=explode('=',$challenge,2);
  189.         $challenge=$key[1];
  190.         $key=$key[0];
  191.         if ($challenge{0== '"'{
  192.             // We're in a quoted value
  193.             // Drop the first quote, since we don't care about it
  194.             $challenge=substr($challenge,1);
  195.             // Now explode() to the next quote, which is the end of our value
  196.             $val=explode('"',$challenge,2);
  197.             $challenge=$val[1]// The rest of the challenge, work on it in next iteration of loop
  198.             $value=explode(',',$val[0]);
  199.             // Now, for those quoted values that are only 1 piece..
  200.             if (sizeof($value== 1{
  201.                 $value=$value[0];  // Convert to non-array
  202.             }
  203.         else {
  204.             // We're in a "simple" value - explode to next comma
  205.             $val=explode(',',$challenge,2);
  206.             if (isset($val[1])) {
  207.                 $challenge=$val[1];
  208.             else {
  209.                 unset($challenge);
  210.             }
  211.             $value=$val[0];
  212.         }
  213.         $parsed["$key"]=$value;
  214.     // End of while loop
  215.     return $parsed;
  216. }
  217.  
  218. /**
  219.  * Creates a HMAC digest that can be used for auth purposes
  220.  * See RFCs 2104, 2617, 2831
  221.  * Uses mhash() extension if available
  222.  *
  223.  * @param string $data Data to apply hash function to.
  224.  * @param string $key Optional key, which, if supplied, will be used to
  225.  *  calculate data's HMAC.
  226.  * @return string HMAC Digest string
  227.  * @since 1.4.0
  228.  */
  229. function hmac_md5($data$key=''{
  230.     if (extension_loaded('mhash')) {
  231.         if ($key== ''{
  232.             $mhash=mhash(MHASH_MD5,$data);
  233.         else {
  234.             $mhash=mhash(MHASH_MD5,$data,$key);
  235.         }
  236.         return $mhash;
  237.     }
  238.     if (!$key{
  239.         return pack('H*',md5($data));
  240.     }
  241.     $key str_pad($key,64,chr(0x00));
  242.     if (strlen($key64{
  243.         $key pack("H*",md5($key));
  244.     }
  245.     $k_ipad =  $key str_repeat(chr(0x36)64;
  246.     $k_opad =  $key str_repeat(chr(0x5c)64;
  247.     /* Heh, let's get recursive. */
  248.     $hmac=hmac_md5($k_opad pack("H*",md5($k_ipad $data)) );
  249.     return $hmac;
  250. }
  251.  
  252. /**
  253.  * Fillin user and password based on SMTP auth settings.
  254.  *
  255.  * @param string $user Reference to SMTP username
  256.  * @param string $pass Reference to SMTP password (unencrypted)
  257.  * @since 1.5.0
  258.  */
  259. function get_smtp_user(&$user&$pass{
  260.     global $username$smtp_auth_mech,
  261.            $smtp_sitewide_user$smtp_sitewide_pass;
  262.  
  263.     if ($smtp_auth_mech == 'none'{
  264.         $user '';
  265.         $pass '';
  266.     elseif isset($smtp_sitewide_user&& isset($smtp_sitewide_pass&&
  267.                !empty($smtp_sitewide_user)) {
  268.         $user $smtp_sitewide_user;
  269.         $pass $smtp_sitewide_pass;
  270.     else {
  271.         $user $username;
  272.         $pass sqauth_read_password();
  273.     }
  274. }

Documentation generated on Sat, 07 Oct 2006 16:08:57 +0300 by phpDocumentor 1.3.0RC6