Generate one time passwords for scp only accounts


Content Contributer
I wanted to generate some one time passwords to allow a friend to login 10 times via scp to download some stuff. Sounds strange but I wanted to ensure that he is not using the account for anything else.

So there are two things todo:

  1. Generate one time passwords
  2. Lock a user to scp only
Let's start with 1.:

  • Install otpw

    sudo apt-get install otpw-bin libpam-otpw

  • Configure common-auth
    nano /etc/pam.d/common-auth
    Find the line:
    auth    [success=1 default=ignore] nullok_secure
    and add these lines above:
    auth       sufficient
    session    optional
    So every login will first try optw and afterwards try the common auth methods.
  • Configure sshd
    Add a otpw config file:
    nano /etc/pam.d/otpw
    With content:

    auth sufficient
    session optional

    Include otpw config to sshd auth config:

    nano /etc/pam.d/sshd

    Search for:

    @include common-auth

    And add this line above:

    @include otpw

    Afterwards modify sshd config:
    Ensure that this three parameters are set to "yes":

    UsePrivilegeSeparation yes
    ChallengeResponseAuthentication yes
    UsePAM yes

  • Restart sshd
    service ssh restart

This is a basic configuration of otpw. It ensures that otpw is only used for users which do have a otpw config file (~/.otpw) in their home directory. All other users will not notice that otpw is active.

Following command will generate 4 one time passwords:

otpw-gen -h 5 -w 64

Following command will generate 10 one time passwords:

otpw-gen -h 6 -w 79

Output would look like this (called with context of user):

otpw-gen -h 6 -w 79
Generating random seed ...

If your paper password list is stolen, the thief should not gain
access to your account with this information alone. Therefore, you
need to memorize and enter below a prefix password. You will have to
enter that each time directly before entering the one-time password
(on the same line).

When you log in, a 3-digit password number will be displayed. It
identifies the one-time password on your list that you have to append
to the prefix password. If another login to your account is in progress
at the same time, several password numbers may be shown and all
corresponding passwords have to be appended after the prefix
password. Best generate a new password list when you have used up half
of the old one.

Enter new prefix password:
Reenter prefix password:

Creating '~/.otpw'.
Generating new one-time passwords ...

OTPW list generated 2013-07-09 20:02 on debian

000 AN2: 3:GL 002 gz7C wMeR 004 BQZs BLns 006 u9AQ 8GfI 008 G:Ui C+jo
001 ZiAZ qeDV 003 cQQr v8O4 005 O/fD 3koN 007 JrLO ROZr 009 wZAT 7zrf

!!! REMEMBER: Enter the PREFIX PASSWORD first !!!

SSH login:

login as: test
Using keyboard-interactive authentication.
Password 003:
Linux debian 3.2.0-4-686-pae #1 SMP Debian 3.2.46-1 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Jul 9 20:03:23 2013 from
[email protected]:~$

If you entered the prefix password "pass" the real password for 003 is:

passcQQr v8O4

Just append it without any space.

Now create a group for all optw users and add the users:

addgroup optw
adduser test optw

And change file permissions:

chown root:eek:ptw /home/test/.otpw
chmod 640 /home/test/.otpw

And to ensure that noone can reset the passwords:

chmod 750 /usr/bin/otpw-gen

Now start with point 2. - limit shell to scp:

apt-get install rssh
apt-get install scponly

There are two shells doing that:

  • rssh is a configurable shell that limits the actions of a user
  • scponly is a shell that ... well ... only has scp commands.
Now you have to add the shell to a user:

usermod -s /usr/sbin/scponly test
usermod -s /usr/sbin/rssh test

And you can confiure rssh quite descent:

nano /etc/rssh.conf


# Leave these all commented out to make the default action for rssh to lock
# users out completely...


# if your chroot_path contains spaces, it must be quoted...
# In the following examples, the chroot_path is "/usr/local/my chroot"
user=test:011:000010:"/opt/scpspace/test chroot" # scp with chroot


I don't like the otpw-gen handling because even if you chown the file to root:root the .otpw file is recreated when the user is calling otpw-gen. So everytime I have to add a user I have to chmod /usr/bin/otpw-gen.

So I am still searching for a better solution for one time passwords.

How do you lock users and the number of logins?
Last edited by a moderator:


New Member
Thank you for the one time passwords configuration. I can use this if I have to connect to my server from a workstation I don't own.
  • Like
Reactions: acd


New Member

%otpw ALL= (root) NOPASSWD: /usr/local/bin/
#set -x
set -o nounset

OTPWOPTS="-h 6 -w 79"


umask 0037

if [ "$(id -u)" != "0" ]; then
  echo "This script must be run from sudo" 1>&2
  exit 1

if [ "$SUDO_USER" = "" ]; then
  echo "Please run from sudo and not directly as root" 1>&2
  exit 2;

export SUDO_HOME=$( bash -c "echo ~$SUDO_USER" )

if [ ! -d "$SUDO_HOME" ]; then
  echo "Could not determine user's shell" 1>&2
  exit 3;

export OTPWFILE="$SUDO_HOME/.otpw"

passwd -S "$SUDO_USER" | awk '{ng=0; if ($2 == "NP") {print "Password is unset";ng=ng+1;} else if ($2 == "L") {print "User is locked";ng=ng+2;}; if ($5 == 0) {print "User is disabled";ng=ng+4}; if (ng != 0) {exit ng+8};}' 1>&2
if [ $? != 0 ] ; then
  exit $?

if ! id "$SUDO_USER" | cut -d' ' -f 3 | grep $OTPWGROUP >/dev/null; then
  echo "User is not in $OTPWGROUP group" 1>&2
  exit 4

# if we got this far, we can go ahead and change the pw
cleancontrol() {
  if [ $OKEXIT != 1 ]; then
    if [ $RMONABORT != 0 ]; then
      rm -rf $OTPWFILE
      echo "OTP file removed, run again to set it." 1>&2
    stty sane
    exit 4;

trap cleancontrol EXIT


# verify with new versions that otpw-gen correctly removes files owned by the user
# (inc symlinks) before executing and doesn't just blindly write to -f, otherwise uncomment.
#rm -rf "$OTPWFILE"

otpw-gen $OTPWOPTS
if [ $? != 0 ]; then
  exit $?

if [ -x `which setfacl`"" ] && setfacl -bm u:"$SUDO_USER":r "$OTPWFILE" 2> /dev/null ; then
  chmod 640 "$OTPWFILE"

exit 0


New Member
I am using rssh for a lot of things now because it is easy to create users and to limit them to one action and to one folder without using different tools.