When we set up whip, our old workhorse server, a couple years ago, we disabled password based ssh logins, choosing to only allow access via public keys. However, I occasionally needed the ability to access the system when I didn't have ready access to my private key (like when using someone else's / a public computer). I came up with a system that would enable password-based ssh login for a period of time and then re-disable it. This post describes that technique. The system was actuated by a button an internal (private) web page (as described below. On the same page, had a link to the MindTerm applet, also installed on the server. This applet, which provides a terminal-like canvas with an ssh session, allowed me to access the server with only a java-enabled browser.
The system was run by a button press on a page. The page was only accessible via a simple-auth challange (page served over SSL) to prevent shenanigans. The button called a .cgi script that would, in turn, run, via sudo, anotheand r script that updated the sshd config (allowing password-based logins) and then restarted the sshd service. This script also forked, the fork sleeping a set amount of time before restoring the original sshd config and (again) restarting sshd. Note: all paths in these scripts (and related content) are specified with full paths for security. (Additionally, everything is chmodded as unwritable.) It goes without saying that these paths were particular to the setup on whip...
Starting from the beginning, here's the chain. First of all, on the SSL-loaded, simple-auth protected web page offering up the button to temporarily enable password-based ssh logins, I had the following bit of content:
<form action="sshPasswordLogin/enablePasswordSSHLogin.cgi">
<li>SSH password login enable: <input type="submit" value="Go" />
Currently: <font color="red"><!--#exec cmd="/var/www/whipAdmin/localAdmin/sshPasswordLogin/passwordLoginEnabled.sh" --></font>
</li></form>
As you can see, this form button calls the script enablePasswordSSHLogin.cgi (in the directory 'sshPasswordLogin' relative from the current directory.) This script is here: (and attached to this entry -- see below)
#!/bin/sh
# This CGI script calls (via sudo) the script that enables
# password based SSH logins. It then spawns a process which
# sleeps for a set time and calls the same script to
# re-disable password based SSH logins.
#
# This file should be chmod'ed 0555 (for security)
# The full path to the lockfile produced by the enabling program
LOCKFILE=/tmp/enablePasswordSSHLogin.lock
# time to sleep
SLEEP_TIME=6m
/bin/echo "Content-type: text/html"
/bin/echo ""
/bin/echo ""
/bin/echo ""
/bin/echo ""
if [ -e ${LOCKFILE} ]; then
# already enabled
exit 0
fi
# Call enable script to enable password logins.
# (redirect output to avoid cluttering web-page)
/usr/bin/sudo /var/www/whipAdmin/localAdmin/sshPasswordLogin/rootscript/setPasswordLoginEnabledDisabled.sh enable >/dev/null
# Sleep and then re-disable it.
# (we need to use /dev/null as stdin and stdout otherwise the program won't
# return as the original stdin/stdout won't be closed...)
/bin/sh -c "/bin/sleep ${SLEEP_TIME}; /usr/bin/sudo /var/www/whipAdmin/localAdmin/sshPasswordLogin/rootscript/setPasswordLoginEnabledDisabled.sh disable" < /dev/null > /dev/null 2>&1 &
This script checks for the presence of a lock file, and if found, aborts. Otherwise, it outputs a refresh call to the calling page (there's gotta' be a better way to do this) and calls (via sudo) the script 'setPasswordLoginEnabledDisabled.sh' (this script located in its own directory chmodded unwritable by everyone for security). The long line at the end of the script starts up a new shell which sleeps the specified time then makes another call to 'setPasswordLoginEnabledDisabled.sh' to disable the password-based ssh login.
Here's the entry in /etc/sudoers that allows the 'enablePasswordSSHLogin.cgi' script (run by user apache) to call the 'setPasswordLoginEnabledDisabled.sh' script (and only this script) via sudo:
# Allow 'apache' user to run the ssh password login enable/disable script
apache ALL=(root) NOPASSWD: \
/var/www/whipAdmin/localAdmin/sshPasswordLogin/rootscript/setPasswordLoginEnabledDisabled.sh
Additionally, the HTML above makes a call to the 'passwordLoginEnabled.sh' script to determine if password login is currently enabled. This script just checks for the presence of the lockfile in the /tmp directory. Here it is: (it's also attached to this entry -- see below)
#!/bin/sh
# A shell script that returns 'enabled' or 'disabled'
# depending on whether password based SSH logins are enabled.
# The full path to the lockfile produced by the enabling program
LOCKFILE=/tmp/enablePasswordSSHLogin.lock
if [ -e ${LOCKFILE} ]; then
echo "enabled"
else
echo "disabled"
fi
Finally, here's the listing for the 'setPasswordLoginEnabledDisabled.sh': (it too is attached to this entry -- see below)
#!/bin/sh
# A script to enable and disable password based logins
# Takes one parameter, either 'enable' or 'disable'
#
# The sudoers file has been updated to allow the
# apache user to run this script as root. The following lines were placed there:
# # Allow apache to run the ssh password login enable/disable script
# apache ALL=(root) NOPASSWD: \
# /var/www/whipAdmin/localAdmin/sshPasswordLogin/rootscript/setPasswordLoginEnabledDisabled.sh
#
# The script also depends on the creation of additional versions of the file:
# /etc/ssh/sshd_config
# with the suffixes '.passwordsDisable' and '.passwordsEnable'
# The only differences between these two files should be that
# the 'enable' version contains the line
# PasswordAuthentication yes
# and the 'disable' version contains the line
# PasswordAuthentication no
#
# This file should be in it's own directory. Both this file and its directory
# should be chmod'ed 0500 (for security)
# The full path to the lockfile produced by the enabling program
LOCKFILE=/tmp/enablePasswordSSHLogin.lock
# The file locations for the various SSH config files
SSHD_CONFIG=/etc/ssh/sshd_config
SSHD_CONFIG_PW_DISABLED=/etc/ssh/sshd_config.passwordsDisable
SSHD_CONFIG_PW_ENABLED=/etc/ssh/sshd_config.passwordsEnable
# Command to execute to reload the sshd configuration
SSHD_HUP_CMD="/etc/init.d/sshd reload"
# ensure parameter
case $1 in
enable)
if [ -e ${LOCKFILE} ]; then
/bin/echo "Already enabled."
exit 1
fi
/bin/touch ${LOCKFILE}
/bin/cp ${SSHD_CONFIG_PW_ENABLED} ${SSHD_CONFIG}
${SSHD_HUP_CMD}
;;
disable)
if [ ! -e ${LOCKFILE} ]; then
/bin/echo "Already disabled."
exit 1;
fi
/bin/cp ${SSHD_CONFIG_PW_DISABLED} ${SSHD_CONFIG}
${SSHD_HUP_CMD}
/bin/rm ${LOCKFILE}
;;
*)
/bin/echo "Invalid parameter given."
/bin/echo "Must have exactly one parameter, either 'enable' or 'disable'"
exit 1
;;
esac
Much of the header of the script is documentation reiterated here. The script overwrites the /etc/ssh/sshd_config file with a version called sshd_config.passwordEnable or sshd_config.passwordDisable depending on whether password-based ssh login is being enabled or disabled. The only difference between these files is:
# diff sshd_config.passwordsDisable sshd_config.passwordsEnable
65c63
< PasswordAuthentication no
---
> PasswordAuthentication yes
After doing the overwrite, the relevant init.d script is called to reload the sshd configuration. The lockfile is really just used as a control mechanism to prevent the same function from being called multiple times; although, in retrospect, this really wouldn't hurt anything. The lockfile presence/absence is also used by 'passwordLoginEnabled.sh' to determine if password-based ssh login was currently active, altho this could be done by diffing the active sshd_config file to either the sshd_config.passwordsEnable or sshd_config.passwordsDisable version. In addition to all this, we ran a cron job that disabled password-based ssh login out of hand every so often just in case the fork in the .cgi script failed.
| Attachment | Size |
|---|---|
| enablePasswordSSHLogin.cgi.txt | 1.2 KB |
| passwordLoginEnabled.sh | 309 bytes |
| setPasswordLoginEnabledDisabled.sh | 2.14 KB |