Happy New Year
[squirrelmail.git] / plugins / change_password / backend / ldap.php
index b94bf0532d2690c77ebb7831846b21eb0073ba62..24baf48a58a4c05955770f9cfab8d9df2121f006 100644 (file)
@@ -1,14 +1,30 @@
 <?php
+
 /**
  * Change password LDAP backend
  *
+ * @copyright 2005-2018 The SquirrelMail Project Team
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package plugins
  * @subpackage change_password
  */
 
-/** get imap server global */
-global $imapServerAddress;
+/**
+ * do not allow to call this file directly
+ */
+if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) {
+    header("Location: ../../../src/login.php");
+    die();
+}
+
+/** load required functions */
+
+/** sqimap_get_user_server() function */
+include_once(SM_PATH . 'functions/imap_general.php');
+
+/** get imap server and username globals */
+global $imapServerAddress, $username;
 
 /** Default plugin configuration.*/
 /**
@@ -38,7 +54,7 @@ $cpw_ldap_port=389;
 /**
  * LDAP basedn that is used for binding to LDAP server.
  * this option must be set to correct value.
- * @global $cpw_ldap_basedn;
+ * @global string $cpw_ldap_basedn;
  */
 global $cpw_ldap_basedn;
 $cpw_ldap_basedn='';
@@ -78,7 +94,7 @@ $cpw_ldap_bindpw='';
 
 /**
  * BindDN that should be able to change password.
- * WARNING: usually user has enough privileges to change own password.
+ * WARNING: sometimes user has enough privileges to change own password.
  * If you leave default value, plugin will try to connect with DN that
  * is detected in $cpw_ldap_username_attr=$username search and current
  * user password will be used for authentication.
@@ -125,6 +141,9 @@ if (isset($cpw_ldap['adminpw'])) $cpw_ldap_adminpw=$cpw_ldap['adminpw'];
 if (isset($cpw_ldap['userid_attr'])) $cpw_ldap_userid_attr=$cpw_ldap['userid_attr'];
 if (isset($cpw_ldap['default_crypto'])) $cpw_ldap_default_crypto=$cpw_ldap['default_crypto'];
 
+/** make sure that setting does not contain mapping */
+$cpw_ldap_server=sqimap_get_user_server($cpw_ldap_server,$username);
+
 /**
  * Adding plugin hooks
  */
@@ -135,45 +154,36 @@ $squirrelmail_plugin_hooks['change_password_init']['ldap'] =
         'cpw_ldap_init';
 
 /**
- * Backend specific functions
+ * Makes sure that required functions and configuration options are set.
  */
 function cpw_ldap_init() {
-    global $color;
-    global $cpw_ldap_basedn;
-
-    /**
-     * If SM_PATH isn't defined, define it.  Required to include files.
-     * @ignore
-     */
-    if (!defined('SM_PATH')) define('SM_PATH','../../../');
-
-    // load error_box() function
-    include_once(SM_PATH . 'functions/display_messages.php');
+    global $oTemplate, $cpw_ldap_basedn;
 
     // set initial value for error tracker
     $cpw_ldap_initerr=false;
 
     // check for ldap support in php
     if (! function_exists('ldap_connect')) {
-        error_box(_("Current configuration requires LDAP support in PHP."),$color);
+        error_box(_("Current configuration requires LDAP support in PHP."));
         $cpw_ldap_initerr=true;
     }
 
     // chech required configuration settings.
     if ($cpw_ldap_basedn=='') {
-        error_box(_("Plugin is not configured correctly."),$color);
+        error_box(_("Plugin is not configured correctly."));
         $cpw_ldap_initerr=true;
     }
 
     // if error var is positive, close html and stop execution
     if ($cpw_ldap_initerr) {
-        echo '</body></html>';
+        $oTemplate->display('footer.tpl');
         exit;
     }
 }
 
 
 /**
+ * Changes password. Main function attached to hook
  * @param array $data The username/curpw/newpw data.
  * @return array Array of error messages.
  */
@@ -204,16 +214,29 @@ function cpw_ldap_dochange($data) {
 
     if ($cpw_ldap_con) {
         $cpw_ldap_con_err=false;
+
         // set connection options
         if (is_array($cpw_ldap_connect_opts) && $cpw_ldap_connect_opts!=array()) {
-            foreach ($cpw_ldap_connect_opts as $opt => $value) {
-                if (! ldap_set_option($cpw_ldap_con,constant('LDAP_OPT_' . $opt),$value)) {
-                    // set error message
-                    array_push($msgs,sprintf(_("Setting of LDAP connection option %s to value %s failed."),$opt,$value));
-                    // FIXME: check if ldap_set_option modifies ldap_error.
-                    array_push($msgs,sprintf(_("Error: %s"),ldap_error($cpw_ldap_con)));
-                    $cpw_ldap_con_err=true;
+            // ldap_set_option() is available only with openldap 2.x and netscape directory sdk.
+            if (function_exists('ldap_set_option')) {
+                foreach ($cpw_ldap_connect_opts as $opt => $value) {
+                    // Make sure that constant is defined defore using it.
+                    if (defined('LDAP_OPT_' . $opt)) {
+                        // ldap_set_option() should not produce E_NOTICE or E_ALL errors and does not modify ldap_error().
+                        // leave it without @ in order to see any weird errors
+                        if (! ldap_set_option($cpw_ldap_con,constant('LDAP_OPT_' . $opt),$value)) {
+                            // set error message
+                            array_push($msgs,sprintf(_("Setting of LDAP connection option %s to value %s failed."),$opt,$value));
+                            $cpw_ldap_con_err=true;
+                        }
+                    } else {
+                        array_push($msgs,sprintf(_("Incorrect LDAP connection option: %s"),$opt));
+                        $cpw_ldap_con_err=true;
+                    }
                 }
+            } else {
+                array_push($msgs,_("Current PHP LDAP extension does not allow use of ldap_set_option() function."));
+                $cpw_ldap_con_err=true;
             }
         }
 
@@ -223,15 +246,17 @@ function cpw_ldap_dochange($data) {
             return $msgs;
         }
 
-        // enable tls
-        // FIXME: untested. use of undocumented ldap function
+        // enable ldap starttls
         if ($cpw_ldap_use_tls &&
             check_php_version(4,2,0) &&
             isset($cpw_ldap_connect_opts['PROTOCOL_VERSION']) &&
-            $cpw_ldap_connect_opts['PROTOCOL_VERSION']>=3) {
-            if (! ldap_use_tls($cpw_ldap_con)) {
-                array_push($msgs,_("Unable to use TLS."));
-                array_push($msgs,sprintf(_("Error: %s"),ldap_error($cpw_ldap_con)));
+            $cpw_ldap_connect_opts['PROTOCOL_VERSION']>=3 &&
+            function_exists('ldap_start_tls')) {
+            // suppress ldap_start_tls errors and process error messages
+            if (! @ldap_start_tls($cpw_ldap_con)) {
+                array_push($msgs,
+                           _("Unable to use TLS."),
+                           sprintf(_("Error: %s"),ldap_error($cpw_ldap_con)));
                 $cpw_ldap_con_err=true;
             }
         } elseif ($cpw_ldap_use_tls) {
@@ -259,8 +284,9 @@ function cpw_ldap_dochange($data) {
 
         // check ldap_bind errors
         if (! $cpw_ldap_binding) {
-            array_push($msgs,_("Unable to bind to LDAP server."));
-            array_push($msgs,sprintf(_("Server replied: %s"),ldap_error($cpw_ldap_con)));
+            array_push($msgs,
+                       _("Unable to bind to LDAP server."),
+                       sprintf(_("Server replied: %s"),ldap_error($cpw_ldap_con)));
             @ldap_unbind($cpw_ldap_con);
             return $msgs;
         }
@@ -270,7 +296,7 @@ function cpw_ldap_dochange($data) {
 
         // check for search errors and stop execution if something is wrong
         if (! $cpw_ldap_search_err) {
-            ldap_unbind($cpw_ldap_con);
+            @ldap_unbind($cpw_ldap_con);
             return $msgs;
         }
 
@@ -295,17 +321,25 @@ function cpw_ldap_dochange($data) {
                 // check for connection errors and stop execution if something is wrong
                 if (! $cpw_ldap_search_err) {
                     @ldap_unbind($cpw_ldap_con);
+                    // errors are added to msgs by cpw_ldap_uid_search()
                     return $msgs;
                 }
 
                 // we should check user password here.
-                $cpw_ldap_cur_pass_array=ldap_get_values($cpw_ldap_con,
+                // suppress errors and check value returned by function call
+                $cpw_ldap_cur_pass_array=@ldap_get_values($cpw_ldap_con,
                                                          ldap_first_entry($cpw_ldap_con,$cpw_ldap_res2),'userpassword');
-                // FIXME: check if ldap_get_values() found userpassword field. Currently it might cause php errors
+
+                // check if ldap_get_values() have found userpassword field
+                if (! $cpw_ldap_cur_pass_array) {
+                    array_push($msgs,_("Unable to find user's password attribute."));
+                    return $msgs;
+                }
 
                 // compare passwords
                 if (! cpw_ldap_compare_pass($cpw_ldap_cur_pass_array[0],$curpw,$msgs)) {
                     @ldap_unbind($cpw_ldap_con);
+                    // errors are added to $msgs by cpw_ldap_compare_pass()
                     return $msgs;
                 }
             }
@@ -314,8 +348,9 @@ function cpw_ldap_dochange($data) {
         }
 
         if (! $cpw_ldap_binding) {
-            array_push($msgs,_("Unable to rebind to LDAP server."));
-            array_push($msgs,sprintf(_("Server replied: %s"),ldap_error($cpw_ldap_con)));
+            array_push($msgs,
+                       _("Unable to rebind to LDAP server."),
+                       sprintf(_("Server replied: %s"),ldap_error($cpw_ldap_con)));
             @ldap_unbind($cpw_ldap_con);
             return $msgs;
         }
@@ -330,9 +365,15 @@ function cpw_ldap_dochange($data) {
             return $msgs;
         }
 
-        // getpassword
-        $cpw_ldap_cur_pass_array=ldap_get_values($cpw_ldap_con,ldap_first_entry($cpw_ldap_con,$cpw_ldap_res2),'userpassword');
-        // FIXME: check if ldap_get_values() found userpassword field
+        // getpassword. suppress errors and check value returned by function call
+        $cpw_ldap_cur_pass_array=@ldap_get_values($cpw_ldap_con,ldap_first_entry($cpw_ldap_con,$cpw_ldap_res2),'userpassword');
+
+        // check if ldap_get_values() have found userpassword field.
+        // Error differs from previous one, because user managed to authenticate.
+        if (! $cpw_ldap_cur_pass_array) {
+            array_push($msgs,_("LDAP server uses different attribute to store user's password."));
+            return $msgs;
+        }
 
         // encrypt new password (old password is needed for plaintext encryption detection)
         $cpw_ldap_new_pass=cpw_ldap_encrypt_pass($newpw,$cpw_ldap_cur_pass_array[0],$msgs,$curpw);
@@ -427,15 +468,19 @@ function cpw_ldap_uid_search($ldap_con,$ldap_basedn,&$msgs,&$results,&$userdn,$o
     $results=ldap_search($ldap_con,$ldap_basedn,cpw_ldap_specialchars($cpw_ldap_userid_attr . '=' . $username));
 
     if (! $results) {
-        array_push($msgs,_("Unable to find user's DN.") . _("Search error."));
-        array_push($msgs,sprintf(_("Error: %s"),ldap_error($ldap_con)));
+        array_push($msgs,
+                   _("Unable to find user's DN."),
+                   _("Search error."),
+                   sprintf(_("Error: %s"),ldap_error($ldap_con)));
         $ret=false;
     } elseif ($onlyone && ldap_count_entries($ldap_con,$results)>1) {
         array_push($msgs,_("Multiple userid matches found."));
         $ret=false;
     } elseif (! $userdn = ldap_get_dn($ldap_con,ldap_first_entry($ldap_con,$results))) {
         // ldap_get_dn() returned error
-        array_push($msgs,_("Unable to find user's DN.") . _("ldap_get_dn error."));
+        array_push($msgs,
+                   _("Unable to find user's DN."),
+                   _("ldap_get_dn error."));
         $ret=false;
     }
     return $ret;
@@ -489,13 +534,22 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
 
     // encrypt/hash password
     switch ($crypto) {
+    case 'md4':
+        // minimal requirement = php with mhash extension
+        if ( function_exists( 'mhash' ) && defined('MHASH_MD4')) {
+            $ret = '{MD4}' . base64_encode( mhash( MHASH_MD4, $pass) );
+        } else {
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'md4'),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
+        }
+        break;
     case 'md5':
         $ret='{MD5}' . base64_encode(pack('H*',md5($pass)));
         break;
     case 'smd5':
-        // minimal requirement mhash extension and php 4.0.4.
-        if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) {
-            sq_mt_seed( (double) microtime() * 1000000 );
+        // minimal requirement = mhash extension with md5 support and php 4.0.4.
+        if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) && defined('MHASH_MD5')) {
             if ($forced_salt!='') {
                 $salt=$forced_salt;
             } else {
@@ -504,26 +558,37 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
             $ret = "{SMD5}".base64_encode( mhash( MHASH_MD5, $pass.$salt ).$salt );
         } else {
             // use two array_push calls in order to display messages in different lines.
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'smd5'));
-            array_push($msgs,_("PHP mhash extension is missing."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'smd5'),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
+        }
+        break;
+    case 'rmd160':
+        // minimal requirement = php with mhash extension
+        if ( function_exists( 'mhash' ) && defined('MHASH_RIPEMD160')) {
+            $ret = '{RMD160}' . base64_encode( mhash( MHASH_RIPEMD160, $pass) );
+        } else {
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'ripe-md160'),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
         }
         break;
     case 'sha':
         // minimal requirement = php 4.3.0+ or php with mhash extension
-        if ( function_exists('sha1') ) {
+        if ( function_exists('sha1') && defined('MHASH_SHA1')) {
             // use php 4.3.0+ sha1 function, if it is available.
-            $new_value = '{SHA}' . base64_encode( pack( 'H*' , sha1( $password_clear) ) );
+            $ret = '{SHA}' . base64_encode(pack('H*',sha1($pass)));
         } elseif( function_exists( 'mhash' ) ) {
             $ret = '{SHA}' . base64_encode( mhash( MHASH_SHA1, $pass) );
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'sha'));
-            array_push($msgs,_("PHP mhash extension is missing."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'sha'),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
         }
         break;
     case 'ssha':
         // minimal requirement = mhash extension and php 4.0.4
-        if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) {
-            sq_mt_seed( (double) microtime() * 1000000 );
+        if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) && defined('MHASH_SHA1')) {
             if ($forced_salt!='') {
                 $salt=$forced_salt;
             } else {
@@ -531,16 +596,18 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
             }
             $ret = "{SSHA}".base64_encode( mhash( MHASH_SHA1, $pass.$salt ).$salt );
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'ssha'));
-            array_push(_("PHP mhash extension is missing."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'ssha'),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
         }
         break;
     case 'crypt':
         if (defined('CRYPT_STD_DES') && CRYPT_STD_DES==1) {
             $ret = '{CRYPT}' . crypt($pass,GenerateRandomString(2,$extra_salt_chars,7));
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'crypt'));
-            array_push($msgs,_("System crypt library doesn't support standard DES crypt."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'crypt'),
+                       _("System crypt library doesn't support standard DES crypt."));
         }
         break;
     case 'md5crypt':
@@ -548,28 +615,29 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
         if (defined('CRYPT_MD5') && CRYPT_MD5==1) {
             $ret = '{CRYPT}' . crypt($pass,'$1$' . GenerateRandomString(9,$extra_salt_chars,7));
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'md5crypt'));
-            array_push($msgs,_("System crypt library doesn't have MD5 support."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'md5crypt'),
+                       _("System crypt library doesn't have MD5 support."));
         }
         break;
     case 'extcrypt':
         // check if crypt() supports extended des
         if (defined('CRYPT_EXT_DES') && CRYPT_EXT_DES==1) {
-            // FIXME: guinea pigs with extended des support needed.
             $ret = '{CRYPT}' . crypt($pass,'_' . GenerateRandomString(8,$extra_salt_chars,7));
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'ext_des'));
-            array_push($msgs,_("System crypt library doesn't support extended DES crypt."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'ext_des'),
+                       _("System crypt library doesn't support extended DES crypt."));
         }
         break;
     case 'blowfish':
         // check if crypt() supports blowfish
         if (defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH==1) {
-            // FIXME: guinea pigs with blowfish support needed.
             $ret = '{CRYPT}' . crypt($pass,'$2a$12$' . GenerateRandomString(13,$extra_salt_chars,7));
         } else {
-            array_push($msgs,sprintf(_("Unsupported crypto: %s"),'Blowfish'));
-            array_push($msgs,_("System crypt library doesn't have Blowfish support."));
+            array_push($msgs,
+                       sprintf(_("Unsupported crypto: %s"),'Blowfish'),
+                       _("System crypt library doesn't have Blowfish support."));
         }
         break;
     case 'plaintext':
@@ -578,7 +646,7 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
         break;
     default:
         array_push($msgs,sprintf(_("Unsupported crypto: %s"),
-                                 (is_string($ldap_crypto) ? htmlspecialchars($ldap_crypto) : _("unknown"))));
+                                 (is_string($ldap_crypto) ? sm_encode_html_special_chars($ldap_crypto) : _("unknown"))));
     }
     return $ret;
 }
@@ -588,9 +656,9 @@ function cpw_ldap_password_hash($pass,$crypto,&$msgs,$forced_salt='') {
  * Code reuse. See phpldapadmin password_compare() function.
  * Some parts of code was rewritten to backend specifics.
  * @link http://phpldapadmin.sf.net
- * @param string $pass_hash
- * @param string $pass_clear
- * @param array $msgs
+ * @param string $pass_hash hashed password string with password type indicators
+ * @param string $pass_clear plain text password
+ * @param array $msgs error messages
  * @return boolean true, if passwords match
  */
 function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
@@ -607,29 +675,31 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
     case 'ssha':
         // Salted SHA
         // check for mhash support
-        if ( function_exists('mhash') ) {
+        if ( function_exists('mhash') && defined('MHASH_SHA1')) {
             $hash = base64_decode($pass_hash);
             $salt = substr($hash, -4);
             $new_hash = base64_encode( mhash( MHASH_SHA1, $pass_clear.$salt).$salt );
             if( strcmp( $pass_hash, $new_hash ) == 0 )
                 $ret=true;
         } else {
-            array_push($msgs,_("Unable to validate user's password."));
-            array_push($msgs, _("PHP mhash extension is missing."));
+            array_push($msgs,
+                       _("Unable to validate user's password."),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
         }
         break;
     case 'smd5':
         // Salted MD5
         // check for mhash support
-        if ( function_exists('mhash') ) {
+        if ( function_exists('mhash') && defined('MHASH_MD5')) {
             $hash = base64_decode($pass_hash);
             $salt = substr($hash, -4);
             $new_hash = base64_encode( mhash( MHASH_MD5, $pass_clear.$salt).$salt );
             if( strcmp( $pass_hash, $new_hash ) == 0)
                 $ret=true;
         } else {
-            array_push($msgs,_("Unable to validate user's password."));
-            array_push($msgs, _("PHP mhash extension is missing."));
+            array_push($msgs,
+                       _("Unable to validate user's password."),
+                       _("PHP mhash extension is missing or does not support selected crypto."));
         }
         break;
     case 'sha':
@@ -637,11 +707,21 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
         if( strcasecmp( cpw_ldap_password_hash($pass_clear,'sha',$msgs), "{SHA}".$pass_hash ) == 0)
             $ret=true;
         break;
+    case 'rmd160':
+        // RIPE-MD160 crypted passwords
+        if( strcasecmp( cpw_ldap_password_hash($pass_clear,'rmd160',$msgs), "{RMD160}".$pass_hash ) == 0 )
+            $ret=true;
+        break;
     case 'md5':
         // MD5 crypted passwords
         if( strcasecmp( cpw_ldap_password_hash($pass_clear,'md5',$msgs), "{MD5}".$pass_hash ) == 0 )
             $ret=true;
         break;
+    case 'md4':
+        // MD4 crypted passwords
+        if( strcasecmp( cpw_ldap_password_hash($pass_clear,'md4',$msgs), "{MD4}".$pass_hash ) == 0 )
+            $ret=true;
+        break;
     case 'crypt':
         // Crypt passwords
         if(  preg_match( "/^\\\$2+/",$pass_hash ) ) { // Check if it's blowfish crypt
@@ -651,8 +731,9 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
                 if( crypt( $pass_clear, $pass_hash ) == $pass_hash )
                     $ret=true;
             } else {
-                array_push($msgs,_("Unable to validate user's password."));
-                array_push($msgs,_("Blowfish is not supported by webserver's system crypt library."));
+                array_push($msgs,
+                           _("Unable to validate user's password."),
+                           _("Blowfish is not supported by webserver's system crypt library."));
             }
         } elseif( strstr( $pass_hash, '$1$' ) ) { // Check if it's md5 crypt
             // check CRYPT_MD5 here.
@@ -662,8 +743,9 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
                 if( crypt( $pass_clear, '$1$' .$salt ) == $pass_hash )
                     $ret=true;
             } else {
-                array_push($msgs,_("Unable to validate user's password."));
-                array_push($msgs,_("MD5 is not supported by webserver's system crypt library."));
+                array_push($msgs,
+                           _("Unable to validate user's password."),
+                           _("MD5 is not supported by webserver's system crypt library."));
             }
         } elseif( strstr( $pass_hash, '_' ) ) { // Check if it's extended des crypt
             // check CRYPT_EXT_DES here.
@@ -672,8 +754,9 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
                 if( crypt( $pass_clear, $pass_hash ) == $pass_hash )
                     $ret=true;
             } else {
-                array_push($msgs,_("Unable to validate user's password."));
-                array_push($msgs,_("Extended DES crypt is not supported by webserver's system crypt library."));
+                array_push($msgs,
+                           _("Unable to validate user's password."),
+                           _("Extended DES crypt is not supported by webserver's system crypt library."));
             }
         } else {
             // it is possible that this test is useless and any crypt library supports it, but ...
@@ -682,8 +765,9 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
                 if( crypt($pass_clear, $pass_hash ) == $pass_hash )
                     $ret=true;
             } else {
-                array_push($msgs,_("Unable to validate user's password."));
-                array_push($msgs,_("Standard DES crypt is not supported by webserver's system crypt library."));
+                array_push($msgs,
+                           _("Unable to validate user's password."),
+                           _("Standard DES crypt is not supported by webserver's system crypt library."));
             }
         }
         break;
@@ -698,4 +782,3 @@ function cpw_ldap_compare_pass($pass_hash,$pass_clear,&$msgs) {
     }
     return $ret;
 }
-?>
\ No newline at end of file