Sunday, February 24, 2013

bypass password prompt in shell



This blog will help you in bypassing or ignoring the password prompt in shell along with a sample script to test direct login to remote servers without any interruption due to password prompt

Using ssh –o & trap signals it is possible to skip password prompt & move ahead in the script

Although remote server direct login is enabled using public key sometimes it does not work either due to password policy expiring the password or server un-reachability. In both situation password will be prompted like below

$ssh oracrmdev2lvsb hostname
ajay@oracrmdev2lvsb's password:





Script:
Sample script has been written to provide report of the failure direct remote login from jump server for a particular osuser.



#!/bin/sh
set -x
BASE="/export/home/ajay/direct_login"
SCP_USER=`who -m | awk '{ print $1}'`
DT=`date '+%b_%d_%Y_%HH_%MM'`
DAT=`date '+%b_%Y'`
MAIL="ajay.more@tatacommunications.com"
TODAY=`/bin/date +%d | cut -d"0" -f2` ; export TODAY

> $BASE/direct_login_check.log
> $BASE/direct_login_check_failed.log
> $BASE/direct_login_check_success.log

echo " Verifying Direct Login for osuser $SCP_USER "

for i in `cat $BASE/host_list.lst`;
do
echo $i
trap `ssh -o PreferredAuthentications=publickey $SCP_USER@$i hostname >> $BASE/direct_login_check.log 2>&1; exit` 0
chkconn=`cat $BASE/direct_login_check.log | grep -i $i | wc -l | awk '{ print $1 }'`;export chkconn
if [ $chkconn -ge 1 ];then
echo "Direct Logging Succeded for osuser $SCP_USER on $i " >> $BASE/direct_login_check_success.log
else
echo "Direct Logging Failed for osuser $SCP_USER on $i " >> $BASE/direct_login_check_failed.log
fi
done

echo "=======================" > $BASE/direct_login_failed.log
echo "Direct Login Failed Log" >> $BASE/direct_login_failed.log
echo "=======================" >> $BASE/direct_login_failed.log
echo "                       " >> $BASE/direct_login_failed.log
cat $BASE/direct_login_check_failed.log >>  $BASE/direct_login_failed.log
echo "                       " >> $BASE/direct_login_failed.log

if [ `cat $BASE/direct_login_failed.log | wc -l | awk '{ print $1 }'` -ge 1 ];then
cd $BASE
uuencode direct_login_failed.log direct_login_failed.log | mailx -s "Direct Login Failure Report for $SCP_USER " $MAIL
fi


Explanation:
Script will...
1. Read the list of hostnames
2. Connect to each server as a password less login
3. Pull the hostname command output from remote host
4. Prepare the failure direct login report & mail

ssh –o PreferredAuthentications=publickey allows to specify preferable public keys based authentication method which suppresses the password prompt event after failure

trap allows to send the interrupt signal within script in-case login (or any command) halts , saving from complete script going in hang state & keeping loop in progress
 

As per snap asap-db2 has got connected successfully using public key & returned the hostname setting flag 1 as a success



As per snap ace-lvsb-db2 unable to connect using public key hence did not returned the hostname causing flag 0 as a failure

Email Report file shows failure log



Friday, February 22, 2013

password reset in shell script using passwd



Resetting Password is a tedious job of the sys admin’s or DBA’s while managing over 100’s of servers.
Automatic password reset could make your job easier , What if your OS password gets reset automatically before expiry & reaches to your mailbox ? yes this is what came in my mind before I started hunting for the
Question How to reset password using passwd command in shell script?

While executing passwd command it takes three input i.e. Old password , New Password , New Password (confirmation)
It would have been difficult to pass these inputs to passwd prompts whithin shell without “expect” command
read –p command asks value by prompting for manual input but expect prompts as well as accepts input values in one go

expect can be configured to send the requested input value to desired command

expect is present in Linux by default but need to install it in rest of the Unix environment 


Script: expect.sh

#!/usr/bin/expect
set pwd [lindex $argv 0]
set pwd1 [lindex $argv 1]
set pwd2 [lindex $argv 2]
spawn /usr/bin/passwd
sleep 5
expect "UNIX password:"
sleep 5
send "$pwd\r"
sleep 5
expect "New password:"
sleep 5
send "$pwd1\r"
sleep 5
expect "Retype new password:"
sleep 5
send "$pwd2\r"
sleep 5
expect eof exit

Explanation:
expect utility path should be defined at the start of the script as like other shells
pwd, pwd1,pwd2 are three arguments that are defined to process three inputs old , new , new passwords
$argv defines position of the values to be passed
spawn should be followed by a command to be executed , here passwd being used without any username specified as in linux passwd should be supplied with username only when root executes it else username is assumed to be current username
expect “” is nothing but the prompt that you will receive if you would have executed the command defined by spawn manually on command prompt
send will pass input values to input prompt
Sleep is embedded to add some delay before passing values to input prompt, it helps in avoiding errors


Working:

$ expect expect.sh MEta12#$ KKll12#$ KKll12#$
spawn /usr/bin/passwd
Changing password for user ora11g.
Changing password for ora11g.
(current) UNIX password:
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

 

Possible errors: In case password supplied is incorrect or sleep time is less between the two inputs below error can be seen

$ expect expect.sh 4KRuOwfM12#$ MEta12#$ MEta12#$
spawn /usr/bin/passwd
Changing password for user ora11g.
Changing password for ora11g.
(current) UNIX password:
passwd: Authentication token manipulation error
send: spawn id exp4 not open
    while executing
"send "$pwd1\r""
    (file "expect.sh" line 14)


 Error because old password was incorrect



Automation:
Now moving one step ahead lets setup auto password reset in shell script

To identify individual user id below command can be used as “who am I” gives the initial user name & not the current/switched username. In non-linux it is necessary to pass username to passwd command

USR=`id | /usr/bin/cut -d" " -f1 | sed 's/^........//' | sed 's/)//g' `;
export USR
echo $USR


Script: pwd_reset.sh


$ cat pwd_reset.sh
#!/bin/bash
MAIL="ajay.more@abc.com"
set -x
PATH=$PATH:/usr/bin
export PATH
BASE=`pwd`; export BASE
echo $BASE
OLDPSWD=`cat $BASE/oldpswd.lst`; export OLDPSWD
echo $OLDPSWD
USR=`id | /usr/bin/cut -d" " -f1 | sed 's/^........//' | sed 's/)//g' `;
export USR
echo $USR
#PSWD=`head /dev/urandom | tr -dc 'a-zA-Z0-9~!@#$%^&*-_' | fold -w 12 | head -n 1`;
#export PSWD
PSWD=`openssl rand -base64 6`;
export PSWD
PSWDNEW=`echo -n "$PSWD"; echo "12#e0"`;
export PSWDNEW
echo $PSWDNEW > $BASE/oldpswd.lst
expect expect.sh $OLDPSWD $PSWDNEW $PSWDNEW
mailx -s "$ORACLE_SID `hostname` $USR $PSWDNEW" $MAIL < /dev/null
chmod 600 $BASE/oldpswd.lst

Explanation: 
Above script makes use of expect.sh to which three input password values being passed
Script generates the random password using
openssl rand -base64 6
Old password is preserved on successful password reset of previous run

So, three inputs being passed to expect.sh in the form of old , new , new passwords
Password gets reset & email is sent with new password, hostname and username to intended recipient
  

pwd_reset.sh can be scheduled in crontab to run every month once if password policy has been set to expire password every 30+ day