From: Kathy Ange (kathyange@yahoo.com)
Date: Thu Aug 04 2005 - 15:39:57 EDT
I want to say thanks to John F Wall, Kalyan Manchikanti, Aaron
Lineberger, C. G. Sellers, Brad_Morrison, Crist J. Clark and Rob
Thompson, for the great answers and quick response.
They had some excellent ideas, I knew someone already had this figured
out. Thanks it has helped me a lot.
Below are there e-mails
===============================================================
Hi,
I use PHP at the command line to do lots of these types of things, it
has a great function for dealing w/ UNIX Epoch time (seconds since Jan
1st, 1970) as well as an easy mail() function.
<?
// Current Time
$now = time();
// Time in the password file as $passexpire
$difference = $now - $passexpire;
// Now you have the number of seconds ($difference) between now and
the expiration.. you // can easily fill the code to divide by this
into hours, seconds, whatever..
?>
-Rob
===============================================================
Kathy,
Here are some ksh functions which might help.
# Define the functions we will use.
function isLeap {
# isLeap(Year)
if (( ((($1 % 4) == 0) && (($1 % 100) != 0)) ||
((($1 % 400) == 0) && ( ($1 % 4000) != 0)) ))
then
return 0
else
return 1
fi
}
function dayOfYear {
# dayOfYear (Month, Day, Year)
integer Count
integer Day
integer Month
integer Year
integer TotalDays
Month=$1
Day=$2
Year=$3
set -A DaysInMonth 0 31 28 31 30 31 30 31 31 30 31 30 31
if isLeap ${Year}
then
DaysInMonth[2]=29
fi
Count=1
TotalDays=0
while
(( Count < Month ))
do
(( TotalDays += DaysInMonth[$Count] ))
(( Count += 1 ))
done
(( TotalDays += Day ))
print "${TotalDays}"
return
}
function daysSinceEpoch {
# daysSinceEpoch (Month, Day, Year)
integer Count
integer Day
integer Month
integer Year
integer DSE
integer numLeaps
Month=$1
Day=$2
Year=$3
(( DSE = (Year - 1970) * 365 - 1 )) # DSE for 1/1/1970 is
0.
Count=1970
numLeaps=0
while
(( Count < Year ))
do
if isLeap ${Count}
then
(( numLeaps += 1 ))
fi
(( Count += 1 ))
done
(( DSE += numLeaps ))
(( DSE += $(dayOfYear ${Month} ${Day} ${Year}) ))
print "${DSE}"
return
}
John
===============================================================
Kathy,
And here is an nawk script which processes the output of the "passwd
-sa" command as you theorized.
#!/usr/bin/nawk -f
BEGIN {
FMT1 = "%-12s\t%-9s\t%-10s\t%s.\n"
FMT2 = "%-12s\t%-9s\t%-10s\t"
"date '+%m %d %Y'" | getline
ThisMonth = $1 + 0
ThisDay = $2 + 0
ThisYear = $3 + 0
Today = daysSinceEpoc(ThisMonth, ThisDay, ThisYear)
}
$4 == "LK" { printf FMT1, $1, $2, $3, "Password is locked" }
$4 == "NP" { printf FMT1, $1, $2, $3, "NO PASSWORD" }
$4 == "PS" { Host = $1
Category = $2
UserID = $3
LastDate = $5
if ( length(LastDate) == 0 ) {
printf FMT2, Host, "CustApp", UserID
printf "NON-EXPIRING PASSWORD.\n"
next
}
DaysValid = $7
split(LastDate, MDY, "/")
MDY[1] += 0
MDY[2] += 0
if (MDY[3] < 70)
MDY[3] += 2000
else
MDY[3] += 1900
PasswordReset = daysSinceEpoc(MDY[1], MDY[2], MDY[3])
PasswordValid = PasswordReset + DaysValid
DaysToExpire = PasswordValid - Today
printf FMT2, Host, Category, UserID
Plural="s"
if (DaysToExpire == 1)
Plural=""
if (DaysToExpire > 0)
printf "Password expires in %d day%s.\n",
DaysToExpire,
Plural
else
printf "ALREADY EXPIRED.\n"
}
function isLeap(Year) {
return (((Year % 4) == 0) && ((Year % 100) != 0)) ||
(((Year % 400) == 0) && ((Year % 4000) !=0))
}
function daysSinceEpoc(Month, Day, Year) {
# Compute number of days since 1/1/1970.
DSE = (Year - 1970) * 365 - 1 # DSE for 1/1/1970 is
0.
numLeaps = 0
for (i=1970; i<Year; i++)
if (isLeap(i))
numLeaps++
DSE += numLeaps
DSE += dayOfYear(Month, Day, Year)
return (DSE)
}
function dayOfYear(Month, Day, Year) {
# Compute the day of the year for this date.
TotalDays = 0
DaysInMonth[1] = 31
DaysInMonth[2] = 28
DaysInMonth[3] = 31
DaysInMonth[4] = 30
DaysInMonth[5] = 31
DaysInMonth[6] = 30
DaysInMonth[7] = 31
DaysInMonth[8] = 31
DaysInMonth[9] = 30
DaysInMonth[10] = 31
DaysInMonth[11] = 30
DaysInMonth[12] = 31
if (isLeap(Year))
DaysInMonth[2] = 29
for (i=1; i<Month; i++) {
TotalDays += DaysInMonth[i]
}
TotalDays += Day
return (TotalDays)
}
John
===============================================================
Attached are two scripts that will help you in what you want to do. You
will have to tweak them to suit your environment. Remember that
passwd_expiry.ksh script needs the second script epoch.pl to exist.
It's
better if you keep them in the same directory. Also include your email
addresses in the ADMINS variable..
hth,
Kalyan Manchikanti
===============================================================
This isn't exactly what you asked for but it is something similar that
I
did on an AIX box. It basically calculates time in seconds since the
last password change and if that time is greater than 9 (5443200) or 12
(7257600) weeks it tells you. This should be easily modifiable to place
in cron and change the execution of echo to mail. AIX doesn't use an
/etc/shadow file explicitly (/etc/security/passwd), but you should be
able to modify the for loop to look at the /etc/shadow file as opposed
to the /etc/passwd file. If I had time I'd port it for you, but I'm
kind
of swamped and what fun would that be for you? ;)
Questions, let me know.
#!/usr/bin/ksh
if [[ `whoami` != root ]]
then
print "You must be root to run this script."
exit
fi
USRCHG=`perl -e "use Time::Local; print time-5443200;"`
ADMCHG=`perl -e "use Time::Local; print time-7257600;"`
DATE=`perl -e "use Time::Local; print time;"`
USRDAT=`perl -e "use Time::Local; print scalar
localtime(time-5443200);"`
ADMDAT=`perl -e "use Time::Local; print scalar
localtime(time-7257600);"`
if [ "$1" = "" ]
then
for user in `cat /etc/passwd | egrep -v
"^root:|^daemon:|^bin:|^sys:|^adm:|^uucp:|^nobo
dy:|^lpd:|^invscout:|^imnadm:|^nuucp:|^ipsec:|^kmem:" | awk -F: '{print
$1}'`
do
grep -p lastupdate /etc/security/passwd | grep -p ^$user: >
/dev/null
if [ $? -eq 0 ]
then
LAST=`pwdadm -q $user | grep last | awk '{print $3}'`
LSTDAT=`perl -e "use Time::Local; print scalar
localtime($LAST);"`
if (( $LAST < $USRCHG ))
then
if (( $LAST < $ADMCHG ))
then
echo "$user: \tRequires Admin To Change."
echo "Last Change:\t$LSTDAT"
echo "12 Weeks: \t$ADMDAT\n"
else
echo "$user: \tRequires User To Change."
echo "Last Change:\t$LSTDAT"
echo "9 Weeks: \t$USRDAT\n"
fi
else
echo "$user: \tNo Change Required."
echo "Last Change:\t$LSTDAT\n"
fi
else
echo "$user: \tDoes not have a \"lastupdate\" entry!\n"
fi
done
else
user="$1"
grep -p lastupdate /etc/security/passwd | grep -p ^$user: >
/dev/null
if [ $? -eq 0 ]
then
LAST=`pwdadm -q $user | grep last | awk '{print $3}'`
LSTDAT=`perl -e "use Time::Local; print scalar
localtime($LAST);"`
if (( $LAST < $USRCHG ))
then
if (( $LAST < $ADMCHG ))
then
echo "$user: \tRequires Admin To Change."
echo "Last Change:\t$LSTDAT"
echo "12 Weeks: \t$ADMDAT\n"
else
echo "$user: \tRequires User To Change."
echo "Last Change:\t$LSTDAT"
echo "9 Weeks: \t$USRDAT\n"
fi
else
echo "$user: \tNo Change Required."
echo "Last Change:\t$LSTDAT\n"
fi
else
echo "$user: \tDoes not have a \"lastupdate\" entry!\n"
fi
fi
Aaron Lineberger
===============================================================
epoch to local should do it
for example, perl has a good way to do this
::::::::::::::
epoch2local.pl
::::::::::::::
#!/usr/bin/perl
#
# $1 = epoch time in format of shadowExpireA
$input = $ARGV[0];
$e = ($input*24*60*60);
print scalar localtime ($e) ;
print "\n\n ";
Google converting epoch to local time and you will get more help...
Sellers
===============================================================
You have the right idea, what you need is a tool that provides a
library for conversion to/from UNIX "epoch time".
I don't think any of the shells will do it. Perl might, and it's
probably already on your system. You may need to get/install a date
conversion library.
I'm surprised that there's no built-in mechanism to notify users.
Brad Morrison - CONBRAM
===============================================================
It's probably easier to get the UNIX epoch time, seconds since January
1, 1970, which is what the computer counts internally anyway, and
convert
that to days. An easy Perl script,
open(SHADOW, '/etc/shadow') || die("failed to open /etc/shadow\n");
$today = time() / 86400; # Today's date.
while (<SHADOW>) {
@pw = split(/:/);
$lastchg = $pw[2]; # Date of last change.
$max = $pw[4]; # Expiration timer.
$warn = $pw[5]; # Warning period.
# Calculate days until expiration.
$expire = $max - ($today - $lastchg);
# Check if we are in the warning period. If so, mail user.
if ($expire < $warn) {
# Insert code for message to user here.
}
# If less than three days, warn the administrator.
if ($expire < 3) {
# Insert code for message to admin here.
}
}
-- Crist J. Clark Below is my original question =============================================================== I feel like this is probably an easy question, so I have been searching the internet for an answer, but just can t figure this out myself. My question simply stated is, I want to be able to e-mail a person outside of the unix server, when a unix id is about to expire. Also if the password will expire within 3 days I want to e-mail the system administrator. Yes if the user is logged on the person will see the warning message, but some IDs aren't logged on daily In the /etc/shadow file the 3rd field is the number of days (since January 1, 1970) since the password was last changed. I am looking for a way to take today date and display as the number of days since January 1, 1970 and then compare to two numbers. If the numbers are within the password warning time frame then send the appropriate e-mail Another thought was to use the date from passwd s where the date is displayed as mm/dd/yy, convert to a Julian date do the calculations then convert back to gregorian corn: root: #passwd -s rnott rnott PS 07/27/05 7 63 7 I am on Sun Solaris 9, Kathy Ange Virginia Department of Agriculture & Consumer Services Information Systems (804) 371-5793 Voice Mail (804) 371-5282 FAX Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com #!/bin/ksh #Author:Kalyan Manchikanti #C:Date:02/08/2005 #Check the Shadow table for the epoch value and warn the users of password expiry #This script needs the epoch.pl script to exist ID=`/usr/bin/id | /usr/bin/cut -d" " -f1` if [[ "${ID}" != "uid=0(root)" ]] then echo "You should run as root" exit 1 fi SHADOW=/etc/shadow #Location of the epoch.pl script. Change it to wherever you are going to keep the epoch.pl script.. ESCPT=/home/kmanchi/bin/epoch.pl HOSTNAME=`hostname` #Email addresses of the admins / users needing the notification #ADMINS="" for i in `cat $SHADOW` do LGN=`echo $i |awk -F: '{print \$1}'` MAXDAYS=`echo $i | awk -F: '{print \$5}'` echo "$MAXDAYS" EPOCH=`echo $i |awk -F: '{print \$3}'` EVAL=`$ESCPT $EPOCH | awk '{print \$2}'` #echo "$EVAL" if [[ $EVAL == `expr $MAXDAYS - 7` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in a week. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 6` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 6 days. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 5` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 5 days. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 4` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 4 days. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 3` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 3 days. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 2` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 2 days. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == `expr $MAXDAYS - 1` ]] then echo "Password for unix user $LGN on `hostname` is going to expire in 1 day. Please change it ASAP" | mailx -s 'password expiry' $ADMINS elif [[ $EVAL == "$MAXDAYS" ]] then echo "PASSWORD FOR USER $LGN HAS EXPIRED.PLEASE CHANGE IT ASAP TO AVOID JOBS FAILING" fi done #!/bin/perl -w use integer; if ($#ARGV != 0) { print "Usage: epoch.pl <number>\n"; exit 1; } $input_day=$ARGV[0]; if ($input_day =~ /(\D+)/) { print "ERROR: Please enter a number!!!\n"; exit 1; } $clktime=time; $curr_day=$clktime/86400; $diff=$curr_day - $input_day; if ($diff < 0) { $diff=-1*$diff; print "$input_day: $diff days from current day\n"; } else { print "$input_day: $diff days to current day\n"; } _______________________________________________ sunmanagers mailing list sunmanagers@sunmanagers.org http://www.sunmanagers.org/mailman/listinfo/sunmanagers
This archive was generated by hypermail 2.1.7 : Wed Apr 09 2008 - 23:31:15 EDT