X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-core%2Finclude%2Ffunctions.inc;h=1ec22f9c8ed277d71848605817745c0a5ada8a34;hb=03d89924406ea00f16b84462d08e48d0436ee285;hp=a543c7cf6360bc2d166976ac08af65ef08776504;hpb=276bccef2e66d21a62ccbcf667b7089f6a3af454;p=gosa.git diff --git a/gosa-core/include/functions.inc b/gosa-core/include/functions.inc index a543c7cf6..1ec22f9c8 100644 --- a/gosa-core/include/functions.inc +++ b/gosa-core/include/functions.inc @@ -23,6 +23,10 @@ /*! \file * Common functions and named definitions. */ +/* Define globals for revision comparing */ +$svn_path = '$HeadURL$'; +$svn_revision = '$Revision$'; + /* Configuration file location */ if(!isset($_SERVER['CONFIG_DIR'])){ define ("CONFIG_DIR", "/etc/gosa"); @@ -68,10 +72,6 @@ define('DES_CBC_MD5',3); define('DES3_CBC_MD5',5); define('DES3_CBC_SHA1',16); -/* Define globals for revision comparing */ -$svn_path = '$HeadURL$'; -$svn_revision = '$Revision$'; - /* Include required files */ require_once("class_location.inc"); require_once ("functions_debug.inc"); @@ -90,6 +90,13 @@ define ("DEBUG_SI", 256); /*! Debug level for communication with gosa-si */ define ("DEBUG_MAIL", 512); /*! Debug level for all about mail (mailAccounts, imap, sieve etc.) */ define ("DEBUG_FAI", 1024); // FAI (incomplete) + +// Define shadow states +define ("POSIX_ACCOUNT_EXPIRED", 1); +define ("POSIX_WARN_ABOUT_EXPIRATION", 2); +define ("POSIX_FORCE_PASSWORD_CHANGE", 4); +define ("POSIX_DISALLOW_PASSWORD_CHANGE", 8); + /* Rewrite german 'umlauts' and spanish 'accents' to get better results */ $REWRITE= array( "ä" => "ae", @@ -120,7 +127,7 @@ $REWRITE= array( "ä" => "ae", * * \param string 'class_name' The currently requested class */ -function __autoload($class_name) { +function __gosa_autoload($class_name) { global $class_mapping, $BASE_DIR; if ($class_mapping === NULL){ @@ -135,6 +142,7 @@ function __autoload($class_name) { exit; } } +spl_autoload_register('__gosa_autoload'); /*! \brief Checks if a class is available. @@ -644,108 +652,126 @@ function ldap_login_user ($username, $password) } -/*! \brief Test if account is about to expire +/*! \brief Checks the posixAccount status by comparing the shadow attributes. * - * \param string 'userdn' the DN of the user - * \param string 'username' the username - * \return int Can be one of the following values: - * - 1 the account is locked - * - 2 warn the user that the password is about to expire and he should change - * his password - * - 3 force the user to change his password - * - 4 user should not be able to change his password - * */ -function ldap_expired_account($config, $userdn, $username) + * @param Object The GOsa configuration object. + * @param String The 'dn' of the user to test the account status for. + * @param String The 'uid' of the user we're going to test. + * @return Const + * POSIX_ACCOUNT_EXPIRED - If the account is expired. + * POSIX_WARN_ABOUT_EXPIRATION - If the account is going to expire. + * POSIX_FORCE_PASSWORD_CHANGE - The password has to be changed. + * POSIX_DISALLOW_PASSWORD_CHANGE - The password cannot be changed right now. + * + * + * + * shadowLastChange + * | + * |---- shadowMin ---> | <-- shadowMax -- + * | | | + * |------- shadowWarning -> | + * |-- shadowInactive --> DEACTIVATED + * | + * EXPIRED + * + */ +function ldap_expired_account($config, $userdn, $uid) { + + // Skip this for the admin account, we do not want to lock him out. + if($uid == 'admin') return(0); + $ldap= $config->get_ldap_link(); + $ldap->cd($config->current['BASE']); $ldap->cat($userdn); $attrs= $ldap->fetch(); - - /* default value no errors */ - $expired = 0; - - $sExpire = 0; - $sLastChange = 0; - $sMax = 0; - $sMin = 0; - $sInactive = 0; - $sWarning = 0; - - $current= date("U"); - - $current= floor($current /60 /60 /24); - - /* special case of the admin, should never been locked */ - /* FIXME should allow any name as user admin */ - if($username != "admin") - { + $current= floor(date("U") /60 /60 /24); - if(isset($attrs['shadowExpire'][0])){ - $sExpire= $attrs['shadowExpire'][0]; - } else { - $sExpire = 0; - } - - if(isset($attrs['shadowLastChange'][0])){ - $sLastChange= $attrs['shadowLastChange'][0]; - } else { - $sLastChange = 0; - } - - if(isset($attrs['shadowMax'][0])){ - $sMax= $attrs['shadowMax'][0]; - } else { - $smax = 0; - } + // Fetch required attributes + foreach(array('shadowExpire','shadowLastChange','shadowMax','shadowMin', + 'shadowInactive','shadowWarning') as $attr){ + $$attr = (isset($attrs[$attr][0]))? $attrs[$attr][0] : null; + } - if(isset($attrs['shadowMin'][0])){ - $sMin= $attrs['shadowMin'][0]; - } else { - $sMin = 0; - } - - if(isset($attrs['shadowInactive'][0])){ - $sInactive= $attrs['shadowInactive'][0]; - } else { - $sInactive = 0; - } - - if(isset($attrs['shadowWarning'][0])){ - $sWarning= $attrs['shadowWarning'][0]; - } else { - $sWarning = 0; - } - - /* is the account locked */ - /* shadowExpire + shadowInactive (option) */ - if($sExpire >0){ - if($current >= ($sExpire+$sInactive)){ - return(1); + + // Check if the account has expired. + // --------------------------------- + // An account is locked/expired once its expiration date has reached (shadowExpire). + // If the optional attribute (shadowInactive) is set, we've to postpone + // the account expiration by the amount of days specified in (shadowInactive). + if($shadowExpire != null && $shadowExpire >= $current){ + + // The account seems to be expired, but we've to check 'shadowInactive' additionally. + // ShadowInactive specifies an amount of days we've to reprieve the user. + // It some kind of x days' grace. + if($shadowInactive == null || $current > $shadowExpire + $shadowInactive){ + + // Finally we've detect that the account is deactivated. + return(POSIX_ACCOUNT_EXPIRED); } - } - - /* the user should be warned to change is password */ - if((($sExpire >0) && ($sWarning >0)) && ($sExpire >= $current)){ - if (($sExpire - $current) < $sWarning){ - return(2); + } + + // The users password is going to expire. + // -------------------------------------- + // We've to warn the user in the case of an expiring account. + // An account is going to expire when it reaches its expiration date (shadowExpire). + // The user has to be warned, if the days left till expiration, match the + // configured warning period (shadowWarning) + // --> shadowWarning: Warn x days before account expiration. + if($shadowExpire != null && $shadowWarning != null){ + + // Check if the account is still active and not already expired. + if($shadowExpire >= $current){ + + // Check if we've to warn the user by comparing the remaining + // number of days till expiration with the configured amount + // of days in shadowWarning. + if(($shadowExpire - $current) <= $shadowWarning){ + return(POSIX_WARN_ABOUT_EXPIRATION); + } } - } - - /* force user to change password */ - if(($sLastChange >0) && ($sMax) >0){ - if($current >= ($sLastChange+$sMax)){ - return(3); + } + + // -- I guess this is the correct detection, isn't it? + if($shadowLastChange != null && $shadowWarning != null && $shadowMax != null){ + $daysRemaining = ($shadowLastChange + $shadowMax) - $current ; + if($daysRemaining > 0 && $daysRemaining <= $shadowWarning){ + return(POSIX_WARN_ABOUT_EXPIRATION); } - } - - /* the user should not be able to change is password */ - if(($sLastChange >0) && ($sMin >0)){ - if (($sLastChange + $sMin) >= $current){ - return(4); + } + + + + // Check if we've to force the user to change his password. + // -------------------------------------------------------- + // A password change is enforced when the password is older than + // the configured amount of days (shadowMax). + // The age of the current password (shadowLastChange) plus the maximum + // amount amount of days (shadowMax) has to be smaller than the + // current timestamp. + if($shadowLastChange != null && $shadowMax != null){ + + // Check if we've an outdated password. + if($current >= ($shadowLastChange + $shadowMax)){ + return(POSIX_FORCE_PASSWORD_CHANGE); } - } } - return($expired); + + + // Check if we've to freeze the users password. + // -------------------------------------------- + // Once a user has changed his password, he cannot change it again + // for a given amount of days (shadowMin). + // We should not allow to change the password within GOsa too. + if($shadowLastChange != null && $shadowMin != null){ + + // Check if we've an outdated password. + if(($shadowLastChange + $shadowMin) >= $current){ + return(POSIX_DISALLOW_PASSWORD_CHANGE); + } + } + + return(0); } @@ -2077,6 +2103,13 @@ function gen_uids($rule, $attributes) { global $config; + // Strip out non ascii chars + foreach($attributes as $name => $value){ + $value = iconv('UTF-8', 'US-ASCII//TRANSLIT', $value); + $value = preg_replace('/[^(\x20-\x7F)]*/','',$value); + $attributes[$name] = $value; + } + /* Search for keys and fill the variables array with all possible values for that key. */ $part= ""; @@ -2262,18 +2295,37 @@ function validate($string) /*! \brief Evaluate the current GOsa version from the build in revision string */ function get_gosa_version() { - global $svn_revision, $svn_path; + global $svn_revision, $svn_path; - /* Extract informations */ - $revision= preg_replace('/^[^0-9]*([0-9]+)[^0-9]*$/', '\1', $svn_revision); + /* Extract informations */ + $revision= preg_replace('/^[^0-9]*([0-9]+)[^0-9]*$/', '\1', $svn_revision); + + // Extract the relevant part out of the svn url + $release= preg_replace('%^.*/gosa/(.*)/include/functions.inc.*$%', '\1', $svn_path); + + // Remove stuff which is not interesting + if(preg_match("/gosa-core/i", $release)) $release = preg_replace("/[\/]gosa-core/i","",$release); + + // A Tagged Version + if(preg_match("#/tags/#i", $svn_path)){ + $release = preg_replace("/tags[\/]*/i","",$release); + $release = preg_replace("/\//","",$release) ; + return (sprintf(_("GOsa %s"),$release)); + } + + // A Branched Version + if(preg_match("#/branches/#i", $svn_path)){ + $release = preg_replace("/branches[\/]*/i","",$release); + $release = preg_replace("/\//","",$release) ; + return (sprintf(_("GOsa %s snapshot (Rev %s)"),$release , $revision)); + } + + // The trunk version + if(preg_match("#/trunk/#i", $svn_path)){ + return (sprintf(_("GOsa development snapshot (Rev %s)"), $revision)); + } - /* Release or development? */ - if (preg_match('%/gosa/trunk/%', $svn_path)){ - return (sprintf(_("GOsa development snapshot (Rev %s)"), $revision)); - } else { - $release= preg_replace('%^.*/([^/]+)/include/functions.inc.*$%', '\1', $svn_path); return (sprintf(_("GOsa $release"), $revision)); - } } @@ -2369,10 +2421,6 @@ function clean_smarty_compile_dir($directory) msg_dialog::display(_("Internal error"), sprintf(_("File '%s' could not be deleted."), $directory."/".$file), ERROR_DIALOG); // This should never be reached } - } elseif(is_dir($directory."/".$file) && - is_writable($directory."/".$file)) { - // Just recursively delete it - rmdirRecursive($directory."/".$file); } } // We should now create a fresh revision file @@ -2631,7 +2679,7 @@ function get_base_from_hook($dn, $attrib) $command= $config->get_cfg_value("baseIdHook"); if ($command != ""){ - $command.= " '".LDAP::fix($dn)."' $attrib"; + $command.= " ".escapeshellarg(LDAP::fix($dn))." ".escapeshellarg($attrib); if (check_command($command)){ @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); exec($command, $output); @@ -2922,7 +2970,7 @@ function change_password ($dn, $password, $mode=0, $hash= "") // Get all available encryption Methods // NON STATIC CALL :) - $methods = new passwordMethod(session::get('config')); + $methods = new passwordMethod(session::get('config'),$dn); $available = $methods->get_available_methods(); // read current password entry for $dn, to detect the encryption Method @@ -2952,7 +3000,7 @@ function change_password ($dn, $password, $mode=0, $hash= "") } else { // User MD5 by default $hash= "md5"; - $test = new $available['md5']($config); + $test = new $available['md5']($config, $dn); } if($test instanceOf passwordMethod){ @@ -2977,12 +3025,15 @@ function change_password ($dn, $password, $mode=0, $hash= "") // Not for groups if ($mode == 0){ - // Create SMB Password - $attrs= generate_smb_nt_hash($password); - if ($shadow != 0){ - $attrs['shadowLastChange']= $shadow; - } + // Create SMB Password + if ($config->get_cfg_value('sambaHashHook', NULL)) { + $attrs= generate_smb_nt_hash($password); + + if ($shadow != 0){ + $attrs['shadowLastChange']= $shadow; + } + } } $attrs['userPassword']= array(); @@ -3011,8 +3062,8 @@ function change_password ($dn, $password, $mode=0, $hash= "") if ($command != ""){ /* Walk through attribute list */ - $command= preg_replace("/%userPassword/", $password, $command); - $command= preg_replace("/%dn/", $dn, $command); + $command= preg_replace("/%userPassword/", escapeshellarg($password), $command); + $command= preg_replace("/%dn/", escapeshellarg($dn), $command); if (check_command($command)){ @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); @@ -3503,5 +3554,18 @@ function get_next_id_traditional($attrib, $dn) } +/* Mark the occurance of a string with a span */ +function mark($needle, $haystack, $ignorecase= true) +{ + $result= ""; + + while (preg_match('/^(.*)('.preg_quote($needle).')(.*)$/i', $haystack, $matches)) { + $result.= $matches[1]."".$matches[2].""; + $haystack= $matches[3]; + } + + return $result.$haystack; +} + // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: ?>