With a little help from Marc (ok, a lot), CRAM-MD5 and DIGEST-MD5 no longer require...
authortassium <tassium@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sat, 7 Dec 2002 04:02:05 +0000 (04:02 +0000)
committertassium <tassium@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sat, 7 Dec 2002 04:02:05 +0000 (04:02 +0000)
git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@4220 7612ce4b-ef26-0410-bec9-ea0150e637f0

class/deliver/Deliver_SMTP.class.php
config/conf.pl
doc/authentication.txt
functions/auth.php
functions/imap_general.php

index 4c8e49a..d367078 100644 (file)
@@ -51,8 +51,7 @@ class Deliver_SMTP extends Deliver {
        }
     
        /* Lets introduce ourselves */
-       if ((( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) and (extension_loaded('mhash')))
-       {
+       if (( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) {
          // Doing some form of non-plain auth
          fputs($stream, "EHLO $domain\r\n");
          $tmp = fgets($stream,1024);
index eaa2a58..ad1ff4f 100755 (executable)
@@ -1152,8 +1152,8 @@ sub command112a {
        } 
          print "\nWhat authentication mechanism do you want to use for IMAP connections?\n\n";
          print $WHT . "plain" . $NRM . " - Plaintext. If you can do better, you probably should.\n";
-         print $WHT . "cram-md5" . $NRM . " - Slightly better than plaintext. (Requires PHP mhash extension)\n";
-         print $WHT . "digest-md5" . $NRM . " - Privacy protection - better than cram-md5.  (Requires PHP mhash extension)\n";
+         print $WHT . "cram-md5" . $NRM . " - Slightly better than plaintext.\n";
+         print $WHT . "digest-md5" . $NRM . " - Privacy protection - better than cram-md5.\n";
          print "\n*** YOUR IMAP SERVER MUST SUPPORT THE MECHANISM YOU CHOOSE HERE ***\n";
          print "If you don't understand or are unsure, you probably want \"plain\"\n\n";
          print "plain, cram-md5, or digest-md5 [$WHT$imap_auth_mech$NRM]: $WHT";
@@ -1245,8 +1245,8 @@ sub command112b {
     print "\tWhat authentication mechanism do you want to use for SMTP connections?\n";
     print $WHT . "none" . $NRM . " - Your SMTP server does not require authorization.\n";
     print $WHT . "plain" . $NRM . " - Plaintext. If you can do better, you probably should.\n";
-    print $WHT . "cram-md5" . $NRM . " - Slightly better than plaintext. (Requires PHP mhash extension)\n";
-    print $WHT . "digest-md5" . $NRM . " - Privacy protection - better than cram-md5. (Requires PHP mhash extension)\n";
+    print $WHT . "cram-md5" . $NRM . " - Slightly better than plaintext.\n";
+    print $WHT . "digest-md5" . $NRM . " - Privacy protection - better than cram-md5.\n";
     print "\n*** YOUR SMTP SERVER MUST SUPPORT THE MECHANISM YOU CHOOSE HERE ***\n";
     print "If you don't understand or are unsure, you probably want \"none\"\n\n";
     print "none, plain, cram-md5, or digest-md5 [$WHT$smtp_auth_mech$NRM]: $WHT";
index 73d1ed6..48d46a8 100644 (file)
@@ -1,6 +1,6 @@
 **********************************************
 IMAP AND SMTP AUTHENTICATION WITH SQUIRRELMAIL
-Preliminary documentation - 20 Nov 2002
+Preliminary documentation - 6 Dec 2002
 Chris Hilts chilts@birdbrained.org
 **********************************************
 
@@ -17,8 +17,9 @@ REQUIREMENTS
 
 CRAM/DIGEST-MD5
 * SquirrelMail 1.3.3 or higher
-* The mhash extension for PHP. (Debian users: You're lucky.  Type 'apt-get
-  install php4-mhash' and you're done.)
+* If you have the mhash extension to PHP, it will automatically
+  be used, which may help performance on heavily loaded servers.
+  ** NOTE: mhash is optional and no longer a requirement **
 
 TLS
 * SquirrelMail 1.3.3 or higher
index b00efd4..cb149da 100644 (file)
@@ -59,10 +59,9 @@ function cram_md5_response ($username,$password,$challenge) {
 
 /* Given the challenge from the server, supply the response using
    cram-md5 (See RFC 2195 for details)
-   NOTE: Requires mhash extension to PHP
 */
 $challenge=base64_decode($challenge);
-$hash=bin2hex(mhash(MHASH_MD5,$challenge,$password));
+$hash=bin2hex(hmac($challenge,$password));
 $response=base64_encode($username . " " . $hash) . "\r\n";
 return $response;
 }
@@ -78,7 +77,7 @@ function digest_md5_response ($username,$password,$challenge,$service,$host) {
     // rfc2831: client MUST fail if no qop methods supported
    // return false;
   //}
-  $cnonce = base64_encode(bin2hex(mhash(MHASH_MD5, microtime())));
+  $cnonce = base64_encode(bin2hex(hmac(microtime())));
   $ncount = "00000001";
 
   /* This can be auth (authentication only), auth-int (integrity protection), or
@@ -93,18 +92,18 @@ function digest_md5_response ($username,$password,$challenge,$service,$host) {
   $string_a1 = utf8_encode($username).":";
   $string_a1 .= utf8_encode($result['realm']).":";
   $string_a1 .= utf8_encode($password);
-  $string_a1 = mhash(MHASH_MD5, $string_a1);
+  $string_a1 = hmac($string_a1);
   $A1 = $string_a1 . ":" . $result['nonce'] . ":" . $cnonce;
-  $A1 = bin2hex(mhash(MHASH_MD5, $A1));
+  $A1 = bin2hex(hmac($A1));
   $A2 = "AUTHENTICATE:$digest_uri_value";
   // If qop is auth-int or auth-conf, A2 gets a little extra
   if ($qop_value != 'auth') {
     $A2 .= ':00000000000000000000000000000000';
   }
-  $A2 = bin2hex(mhash(MHASH_MD5, $A2));
+  $A2 = bin2hex(hmac($A2));
 
   $string_response = $result['nonce'] . ':' . $ncount . ':' . $cnonce . ':' . $qop_value;
-  $response_value = bin2hex(mhash(MHASH_MD5, $A1.":".$string_response.":".$A2));
+  $response_value = bin2hex(hmac($A1.":".$string_response.":".$A2));
 
   $reply = 'charset=utf-8,username="' . $username . '",realm="' . $result["realm"] . '",';
   $reply .= 'nonce="' . $result['nonce'] . '",nc=' . $ncount . ',cnonce="' . $cnonce . '",';
@@ -154,4 +153,30 @@ function digest_md5_parse_challenge($challenge) {
   return $parsed;
 }
 
+function hmac($data, $key='') {
+    // Creates a HMAC digest that can be used for auth purposes
+    // See RFCs 2104, 2617, 2831
+    // Uses mhash() extension if available
+    if (extension_loaded('mhash')) {
+      if ($key== '') {
+        $mhash=mhash(MHASH_MD5,$data);
+      } else {
+        $mhash=mhash(MHASH_MD5,$data,$key);
+      }
+      return $mhash;
+    }
+    if (!$key) {
+         return pack('H*',md5($data));
+    }
+    $key = str_pad($key,64,chr(0x00));
+    if (strlen($key) > 64) {
+        $key = pack("H*",md5($key));
+    }
+    $k_ipad =  $key ^ str_repeat(chr(0x36), 64) ;
+    $k_opad =  $key ^ str_repeat(chr(0x5c), 64) ;
+    /* Heh, let's get re-entrant. PHP is so kinky */
+    $hmac=hmac($k_opad . pack("H*",md5($k_ipad . $data)) );
+    return $hmac;
+}
+
 ?>
index ab73231..1268831 100755 (executable)
@@ -237,7 +237,7 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
     /* Decrypt the password */
     $password = OneTimePadDecrypt($password, $onetimepad);
 
-       if ((($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) AND (extension_loaded('mhash')))  {
+       if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
       // We're using some sort of authentication OTHER than plain
          $tag=sqimap_session_id(false);
          if ($imap_auth_mech == 'digest-md5') {