[sork] Re: [dev] Password expiry

j.huinink at wanadoo.nl j.huinink at wanadoo.nl
Wed Feb 5 18:02:33 PST 2003


Citeren Eric Rostetter <eric.rostetter at physics.utexas.edu>:

> Agreed.  If you send me your php cron-job, with documentation, I'll see
> what I can do with it.

Here is the php script for use in cron. Of course you can also run it from the 
command line. The script assumes that it is stored in horde/scripts. 
Documentation is included in the source code.

Regards,
Jeroen 

PS I actually called my version reminder.php. Reminder.dist.php is what I am 
willing to share with you guys. ;-)


__________________________________________________________


http://www.wanadoo.nl/
-------------- next part --------------
#!/usr/bin/php -q
<?php
/*
 * PHP Shell script to send password expiry reminders based on information
 * returned by the chage command.
 *
 * Go to the Configuration section and set the variables to the correct 
 * values for your setup. 
 * In my actual setup I have changed some more configuration options,
 * such as $conf['log']['type'] and $conf['log']['name'] so that
 * everything is logged to a file.
 *
 * Run this script as root. You can add it to your crontab if you want
 * to run it daily.
 *
 * This script will go through the /etc/passwd file and for every user 
 * verify whether the registered shell is in the list of allowed shells
 * and whether it is not on the refused list from horde/passwd/config/conf.php
 * If the user checks out we verify when his password expires. If the
 * number of days is smaller or equal than the warning period and is
 * an even number of days, we will send him an e-mail. We also send on 
 * e-mail on the last day.
 * If a password is expired $conf['problems']['email'] is notified
 * of this. If the users have problems they are urged to contact 
 * $conf['problems']['email'].
 * 
 * Jeroen Huinink, j.huinink at wanadoo.nl
 */

// Find the base file path of Horde
@define('HORDE_BASE',  __FILE__ . '/../..');

// Registry
require_once HORDE_BASE . '/lib/Registry.php';
$registry = &Registry::singleton();
$registry->pushApp('horde');
$conf = &$GLOBALS['conf'];

// Set the error reporting level in accordance with the config settings.
error_reporting($conf['debug_level']);

// Set the maximum execution time in accordance with the config settings.
set_time_limit($conf['max_exec_time']);

// set the umask according to config settings
if (isset($conf['umask'])) {
    umask($conf['umask']);
}

// Horde base libraries
require_once HORDE_BASE . '/lib/Horde.php';
require_once HORDE_BASE . '/lib/Text.php';
require_once HORDE_BASE . '/lib/base.php';
require_once HORDE_BASE . '/lib/MIME.php';
require_once HORDE_BASE . '/lib/MIME/Message.php';

include_once 'Log.php';

/* 
 * Configuration
 */
//The e-mail domain doesn't seem to be available in some other configuration file.
$conf['reminder']['domain'] = "example.com"; 

//This is the list of shells that signal it is a proper user. Any other values 
//means that this is a special user of some sort that doesn't get an e-mail 
//reminder. A lot of the users that are caught this way will coincide with 
//users in the $conf['user']['refused'] list.
$conf['reminder']['allowed_shells'] = array(
    '/bin/bash', 
    '/usr/bin/passwd', 
    '/usr/bin/password');

//Change this to whatever your path to the chage executable is.
$conf['utils']['chage'] = "/usr/bin/chage";

//Maybe this could be solved better, but it is required because the _SERVER 
//variables that are used in horde/config/registry.php do not work since we 
//do not run this in a server context.
$conf['reminder']['url_prefix'] = "https://horde.example.com";

/* End of configuration */

if (file_exists($conf['log']['name']) && !is_writable($conf['log']['name'])){ 
    die("Log not writeable.\n");
}

$reminderlog = &Log::singleton($conf['log']['type'],$conf['log']['name'], $conf['log']['ident'], $conf['log']['params'], $conf[ 'log']['priority']); 

if (!$reminderlog || !is_object($reminderlog) || !is_subclass_of($reminderlog, 'log')) {
    if (PEAR::isError($reminderlog)) {
        print_r($reminderlog, __FILE__, __LINE__, false);
	die("Could not start logging.");
    } else {
        print_r(new PEAR_Error('An error has occurred. Furthermore, Horde encountered an error attempting to log this error.'), __FILE__, __LINE__, false);
	die("Could not start logging.");
    }
}

$reminderlog->log('Reminder script started', LOG_NOTICE);

include $registry->getParam('fileroot','passwd' ) . '/config/conf.php';

$users = file("/etc/passwd");
$reminderlog->log('Password file read', LOG_DEBUG);
for($i = 0; $i< count($users); $i++) {
    $u = explode(':' , $users[$i]);
    $url = $conf['reminder']['url_prefix'] . $registry->getParam('webroot','passwd');
    $user = $u[0];
    $shell = substr($u[6],0,-1);
    $reminderlog->log('Checking user: "' . $user . '"', LOG_DEBUG);
    if (in_array($shell, $conf['reminder']['allowed_shells']) && !in_array($user, $conf['user']['refused'])) {
        $res = shell_exec($conf['utils']['chage'] . " -l " . $user);
	if (empty($res)) {
            $reminderlog->log('Chage failed for user: "' . $user . '".', LOG_ERR);
        } else {
            $r = explode( "\n", $res);
            foreach($r as $s) {
                $t = explode(":", $s);
                $r[$t[0]] = trim($t[1]);
	    }
            if ($r['Password Expires'] != 'Never') {
	        $expires_in = floor((strtotime($r['Password Expires']) - time())/(60*60*24)) + 1;
		if ($expires_in <= $r['Warning']) {
                    $reminderlog->log('Password expires on ' . $r['Password Expires'] .  ' in ' . $expires_in  . ' days for user "' . $user . '"', LOG_WARNING);
                    $headers['Date'] = date('r');
                    $headers['To'] = $user . '@' . $conf['reminder']['domain'];
                    $headers['Subject'] =  _("Reminder: E-mail password expires in " . $expires_in . " days.");
                    $headers['User-Agent'] =  'Horde ' . HORDE_VERSION;
                
                    $headers['From'] = "Automatic password reminder <" . $conf['problems']['email'] . ">";
                    $headers['Sender'] = $conf['problems']['email'];
                    $recipients = $user;
                    $message = "";
                    if ($expires_in < 1) {
                        $reminderlog->log('E-mail password is expired for user "' . $user . '".', LOG_WARNING);
			if ($expires_in > -2) {
                            $headers['To'] = $conf['problems']['email'];
                            $recipients = $conf['problems']['email'];
                            $headers['From'] = "Password expired <" . $conf['problems']['email'] . ">";
                            $headers['Subject'] =  _('Password for user "' . $user . '" is expired!');
                            $message = 
"This is an automatic e-mail to inform you that the password for user \"" .
$user . "\" expired " . (0-$expires_in) . " days ago.";
                        }
                    } elseif ($expires_in == 1) {
                        $headers['Subject'] =  _("Reminder: E-mail password expires TODAY!");
                        $headers['X-Priority'] = '1';
                        $reminderlog->log('Password expires today for user "' . $user . '"', LOG_DEBUG);
                        $message = 
"This is an automatic e-mail to remind you that your password expires " . 
"TODAY. Please go to " . $url . " to change your password NOW.\n\n" .
"You will not be able to acces your e-mail or change your password after it " . 
"expires.\n\n";
                    } elseif (fmod($expires_in,2) == 0) {
                        $reminderlog->log('Password expires in even number of days for user "' . $user . '"', LOG_DEBUG);
                        $message = 
"This is an automatic e-mail to remind you that your e-mail password will expire in " .
$expires_in . " days. Please go to " . $url . " to change your " . 
"password.\n\nYou will not be able to use your Outlook e-mail or the webmail " . 
"client after your password expires. Make sure you change it in time, because " . 
"you cannot change your password after it expires.\n\nIn the event that this " . 
"happens send mail to " . $conf['problems']['email'] . "\n\nThis reminder will be sent " . 
"every other day until you change your password starting " . $r['Warning'] . 
" days before expiry. If you want to change this period send mail to " .
$conf['problems']['email'] . " as well.\n";
                    }
                    if ($message != "") { 
                        $mime = &new MIME_Message();
                        $body = &new MIME_Part('text/plain', Text::wrap($message, 80, "\n"));
        
                        $mime->addPart($body);
                        $headers= $mime->header($headers);
                        $msg = $mime->toString();
            
                        include_once 'Mail.php';
                        $mailer = &Mail::factory($conf['mailer']['type'], $conf['mailer']['params']);
                        if (!PEAR::isError($mailer->send($recipients, $headers, $msg))) {
                            $reminderlog->log('Expiry mail sent to user "' . $user . '"', LOG_NOTICE);
                        } else { 
                            $reminderlog->log('Could not send expiry mail to user "' . $user . '"', LOG_ERR);
                        }
                    } else {
                        $reminderlog->log('We do not send a message to user "' . $user . '" because it is an odd day and not the last.', LOG_DEBUG);
                    }
                } else {
                    $reminderlog->log('Password expires on ' . $r['Password Expires'] .  ' in ' . $expires_in  . ' days for user "' . $user . '"', LOG_NOTICE);
                    $reminderlog->log('Before warning period for user "' . $user . '"', LOG_DEBUG);
                }
            } else {
                $reminderlog->log('Password does never expire for user "' . $user . '"', LOG_NOTICE);
            }
        }
    } else {
        if (in_array($shell,$conf['reminder']['allowed_shells'])) {
            if (in_array($user, $conf['user']['refused'])) {
                $reminderlog->log('Skipped user: "' . $user . '". No proper shell and in refused list.', LOG_INFO);
            } else {
                $reminderlog->log('Skipped user: "' . $user . '". No proper shell.', LOG_INFO);
            }
        } else {
            $reminderlog->log('Skipped user: "' . $user . '". In refused list.', LOG_INFO);
        }
    }
}

$reminderlog->log('Reminder script ended', LOG_INFO);

?>


More information about the dev mailing list