#! /usr/bin/expect -f
#*********************************************************************
#   Copyright (c) International Business Machines  Corp., 2003, 2004, 2007
#
#   This program is free software;  you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY;  without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
#   the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program;  if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
#  FILE   : su
#
#  PURPOSE: Tests the basic functionality of `su`.
#
#  SETUP: The program `/usr/bin/expect' MUST be installed.
#         The user invoking this test script must NOT be "root".
#     	  The PASSWD variable should be set prior to execution
#
#  HISTORY:
#     03/03     Dustin Kirkland (dkirklan@us.ibm.com)
#     03/03     Jerone Young    (jeroney@us.ibm.com)
#     10/01/04  Kris Wilson     Skip test 7 if RedHat; no -e option.
#     05/23/07  Kris Wilson     Make test 7 work for SLES.
########################################################################

# The root user cannot succesfully execute su test because the root user
# is able to become anyone without entering passwords
set whoami [ exec whoami ]
if { $whoami=="root" } {
  send_user "ERROR: You must execute the 'su' tests as a non-root user\n"
  exit 1
}

#Grab input from enviroment
if [info exists env(PASSWD)] {
  	set PASSWD $env(PASSWD)
} else {
	send_user "YOU NEED TO SET ENVIROMENT VARIABLE PASSWD. \n"
	exit 1
}

if [info exists env(TEST_USER2)] {
  set USER1 $env(TEST_USER2)
} else {
  	send_user "YOU MUST SET ENVIRONMENT VARIABLE TEST_USER2"
  	exit 1
}

# Need the release type from su01
if [info exists env(tvar)] {
  set distro $env(tvar)
} else {
        send_user "YOU MUST SET ENVIORMENT VARIABLE tvar"
        exit 1
}

if [info exists env(TEST_USER2_PASSWD)] {
  set USER1_PASSWORD $env(TEST_USER2_PASSWD)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_USER2_PASSWD"
  exit 1
}

if [info exists env(TEST_LINE)] {
  set TEST_LINE_ENV $env(TEST_LINE)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_LINE"
  exit 1
}


if [info exists env(TEST_ENV_FILE)] {
  set TEST_ENV_FILE $env(TEST_ENV_FILE)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_ENV_FILE_USER"
  exit 1
}

if [info exists env(TEST_ENV_FILE2)] {
  set TEST_ENV_FILE2 $env(TEST_ENV_FILE2)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_ENV_FILE2"
  exit 1
}


if [info exists env(TEST_ENV_FILE_USER)] {
  set TEST_ENV_FILE_USER1 $env(TEST_ENV_FILE_USER)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_ENV_FILE_USER"
  exit 1
}

if [info exists env(TEST_USER1_NEW_PASSWD)] {
  set USER1_NEW_PASSWORD $env(TEST_USER1_NEW_PASSWD)
} else {
  send_user "YOU MUST SET ENVIROMENT VARIABLE TEST_USER1_NEW_PASSWD"
  exit 1
}


set script_exit_code 0
set i_can_root 0

send_user "Starting 'su' Testing\n"

# 1) su with no parameters and correct password.
#    - The su command should return a result code of 0
#    - The user ID should be root
#    - The user environment should be that of the invoking process
#    - The command should create a new shell with a new process ID

send_user "\nTEST: su with no parameters and correct password\n"

set i_am_root 0
# run "whoami" to test user ID inside su shell
spawn /bin/su -c whoami
set i_am_root 0
expect {
  "Password:" {
  	send "$PASSWD\r"
    expect {
      "root" { set i_am_root 1
		set i_can_root 1
	 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]

#Check that su user has same enviroment as current user
set i_have_env 0
set test_env_var " "
if { $i_am_root==1 } {
	spawn su -c "/bin/su root -c \"echo \\\$TEST_LINE > $TEST_ENV_FILE\""
	expect {
		 "Password:" {
			send "$PASSWD\r"
		}
	}
	expect eof
	wait

	set test_env_var [exec cat $TEST_ENV_FILE]

	if  { $test_env_var==$TEST_LINE_ENV } {
		set i_have_env 1
	} else {
		send_user "/bin/su with correct password (FAILED), the enviroment was not kept after su.\n"
	}
}


#this variable is for any test, it can't run correctly if this test fails
set test_one_passed 0

if { ($i_am_root==1) && ($exit_code==0) && ($pid>0) && ($i_have_env==1) } {
	send_user "/bin/su with correct password & enviroment check ( PASSED )\n"
	set test_one_passed 1
} else {
  	send_user "/bin/su with correct password ( FAILED )\n"
    set script_exit_code 1
}


# 2) su with no parameters and incorrect password.
# 	  - The su command should return a result code of non-0
#     - The user should be returned to the invoking shell
#     - An appropriate failure message should be displayed

send_user "\nTEST: su with no parameters and incorrect password \n"

set displayed_error 0
# run "whoami" to test user ID inside su shell
spawn /bin/su -c whoami
set displayed_error 0
expect {
  "Password:" {
    send "wrong_$PASSWD\r"
    expect {
				"su: incorrect password" { set displayed_error 1 }
				"su: Authentication failure" { set displayed_error 1 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]

#Added for arm architecture

send_user "\ndisplayed_error=$displayed_error"
send_user "\nexit_code=$exit_code"
send_user "\npid=$pid\n"

if { ($displayed_error==1) && ($exit_code!=0) && ($pid>0) } {
  send_user "/bin/su with incorrect password ( PASSED )\n"
} else {
  send_user "/bin/su with incorrect password ( FAILED )\n"
  set script_exit_code 1
}

# 3) su to root using name parameter and correct password.
# - The su command should return a result code of 0
# - The user ID should be root
# - The user environment should be that of the invoking process
# - The command should create a new shell with a new process ID

send_user "\nTEST: su to root using name parameter and correct password. \n"

set i_am_root 0
# run "whoami" to test user ID inside su shell
spawn /bin/su -l root -c whoami
expect {
  "Password:" {
    send "$PASSWD\r"
    expect {
				"root" { set i_am_root 1 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]


#Check that su user does not have the same enviroment as current user
set i_have_env 0
set test_env " "
if { $i_am_root==1 } {
     	spawn /bin/sh -c "/bin/su -l root -c \"echo \"\\\$TEST_LINE > $TEST_ENV_FILE2\"\""
        expect {
                 "Password:" {
			send "$PASSWD\r"
                }
        }

	set test_env [exec cat $TEST_ENV_FILE2]

	if  { $test_env==$TEST_LINE_ENV } {
        	set i_have_env 1
 		send_user "/bin/su -l root with correct password (FAILED), because it did not change enviroment\n"
	}
}


if { ($i_am_root==1) && ($exit_code==0) && ($pid>0) && ($i_have_env==0) } {
  send_user "/bin/su -l root with correct password & enviroment check ( PASSED )\n"
} else {
  send_user "/bin/su -l root with correct password ( FAILED )\n"
  set script_exit_code 1
}


# 4) su to root with name parameter and incorrect password.
#    - The su command should return a result code of non-0
#    - The user should be returned to the invoking shell
#    - An appropriate failure message should be displayed

send_user "\nTEST: su to root with name parameter and incorrect password. \n"

set displayed_error 0
# run "whoami" to test user ID inside su shell
spawn /bin/su -l root -c whoami
expect {
  "Password:" {
    send "wrong_$PASSWD\r"
    expect {
				"su: incorrect password" { set displayed_error 1 }
				"su: Authentication failure" { set displayed_error 1 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]
if { ($displayed_error==1) && ($exit_code!=0) && ($pid>0) } {
  send_user "/bin/su -l root with incorrect password ( PASSED )\n"
} else {
  send_user "/bin/su -l root with incorrect password ( FAILED )\n"
  set script_exit_code 1
}


# 5) su to user1 with name parameter and correct password.
#    - The su command should return a result code of 0
#    - The user ID should be user1
#    - The user environment should be that of the invoking process, in this case,that of user1
#    - The command should create a new shell with a new process ID
#    - Run "whoami" to test user ID inside su shell

send_user "TEST: su to user1 with name parameter and correct password.\n"

set i_am_correct 0
spawn /bin/su -l $USER1 -c whoami
expect {
  "Password:" {
    send "$USER1_PASSWORD\r"
    expect {
				"$USER1\r" { set i_am_correct 1 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]

set i_have_env 0
set test_env_var 0
#Check to see that su user does not have the same enviroment
if { $i_am_correct==1 } {
        spawn /bin/sh -c "/bin/su -l $USER1 -c \"echo \"\\\$TEST_LINE > $TEST_ENV_FILE_USER1\"\""
        expect {
                 "Password:" {
                                send "$USER1_PASSWORD\r"
                }
        }

}

set test_env_var [exec cat $TEST_ENV_FILE_USER1]

set i_have_env 0
if  { $test_env_var==$TEST_LINE_ENV } {
        set i_have_env 1
        send_user "/bin/su -l $USER1 with correct password (FAILED), because it did not change enviroment\n"
	set i_have_env 0
	if  { $test_env_var==$TEST_LINE_ENV } {
        	set i_have_env 1
        	send_user "su -l $USER1 with correct password (FAILED), because it did not change enviroment\n"
	}
}

if { ($i_am_correct==1) && ($exit_code==0) && ($pid>0) && ($i_have_env==0) } {
  send_user "/bin/su -l $USER1 with correct password & enviroment check ( PASSED )\n"
} else {
  send_user "/bin/su -l $USER1 with correct password ( FAILED )\n"
  set script_exit_code 1
}



# 6)su to user1 with name parameter and incorrect password.
#    - The su command should return a result code of non-0
#    - The user should be returned to the invoking shell
#    - An appropriate failure message should be displayed.

send_user "TEST: su to user1 with name parameter and incorrect password.\n"
spawn /bin/su -l $USER1 -c whoami
set displayed_error 0
expect {
  "Password:" {
    send "wrong_$USER1_PASSWORD\r"
    expect {
				"su: incorrect password" { set displayed_error 1 }
				"su: Authentication failure" { set displayed_error 1 }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]
if { ($displayed_error==1) && ($exit_code!=0) && ($pid>0) } {
  	send_user "/bin/su -l $USER1 with incorrect password ( PASSED )\n"
} else {
  	send_user "/bin/su -l $USER1 with incorrect password ( FAILED )\n"
	set script_exit_code 1
}


# 7) su to user1 with the user1 password expired
#    - user1 should not be allowed to log in
#    - The su command should return a result code of non-0
#    - The user should be returned to the invoking shell
#    - An appropriate failure message should be displayed.

# Become root and expire $USER1 password

#  Skip this if Red Hat; -e option not supported.
if { $distro != "redhat" && $distro != "redhat-linux" } {

if { $test_one_passed==1} {
send_user "TEST:  su to user1 with the user1 password expired.\n"

spawn /bin/su -l root -c "passwd -e $USER1"
expect {
  "Password:" {
    send "$PASSWD\r"
    expect {
				"Password expiry information changed."
    }
  }
}

set i_am_correct 0
spawn /bin/su -l $USER1 -c whoami
expect {
  "Password:" {
    send "$USER1_PASSWORD\r"
    expect {
        -re "current.*password|Old Password" {
        send "wrong_$USER1_PASSWORD\r"
        expect {
       	  -re "current.*password|Old Password" {
          send "wrong_$USER1_PASSWORD\r"
            expect {
								"su: incorrect password" { set i_am_correct 1 }
								"su: Authentication failure" { set i_am_correct 1 }
								"su: Authentication token manipulation error" { set i_am_correct 1 }
            }
          }
					"su: incorrect password" { set i_am_correct 1 }
					"su: Authentication failure" { set i_am_correct 1 }
					"su: Authentication token manipulation error" { set i_am_correct 1 }
        }
      }
    }
  }
}

# capture result code
set codes [wait]
set pid [lindex $codes 0]
set exit_code [lindex $codes 3]
if { ($i_am_correct==1) && ($exit_code!=0) && ($pid>0) } {
  	send_user "/bin/su -l $USER1 with expired correct password ( PASSED )\n"
} else {
  	send_user "/bin/su -l $USER1 with expired correct password ( FAILED )\n"
	set script_exit_code 1
}


#Become root and set $USER1 password back to previous value
spawn /bin/su -l root -c "passwd $USER1"
expect {
  "Password: " {
    send "$PASSWD\r"
    expect {
     "Enter new password: " {
        send "$USER1_NEW_PASSWORD\r"
        expect {
          "Re-type new password: " {
            send "$USER1_NEW_PASSWORD\r"
            expect {
              "Password changed" {}
            }
          }
        }
      }
    }
  }
}

} else {

	send_user "TEST:  su to user1 with the user1 password expired. (FAILED),see more next line.\n"
	send_user "This test cannot be run because the first test to su as root failed\n"

}
# If RH let the tester know why only 6 tests were run.
} else {
  send_user "TEST 7 skipped if running on Red Hat; -e not supported \n"
}
exit  $script_exit_code