#!/bin/bash
#
# Script to start pppd with one time passwords. In contrast to other program
# the password is not visible in the process table nor in the shell history
# files like .bash_histrory or .sh_history nor in the syslog
#
# Author:  Carsten Grohmann (c) 2004, 2005
#
# Licence: GPL
#
# $Id: startpppd.sh,v 1.2 2005/01/04 15:23:09 carsten Exp $
#
# Todo:
#   - check running pppd instead of using "sleep 120"
#
# History:
#
# $Log: startpppd.sh,v $
# Revision 1.2  2005/01/04 15:23:09  carsten
# - add missing ! in first line
# - add some security settings
#   - set IFS and PATH to own values
#   - remove unused signal handlers
#   - set a restrictive umask
#
# Revision 1.1  2004/12/22 16:55:06  carsten
# - initial import to CVS
# - script to use one time passwords with pppd in a safer way

# ------ configuration -------

# username
USERNAME="MyUserName"

# configurations and authentification methods
# Format of this entries: "PPPConfiguration:[pap|chap]"
# multiple entries can separated by a space character
AUTH_TYPES="MyISP:pap"

# time to wait before reseting the password in the pppd password file
PPPD_WAIT=120

# ---- NO changes below this line ----

# ppp config dir
PPPD_CONFIGDIR="/etc/ppp"

# pppd configuration
PPPD_CONFIG="$1"

# ------ set more secure settings -------

# make shell poor in words :-)
set +x
set +v

# disable core dumps
ulimit -c 0

# set restrictive umask
umask 0077

# remove old signal handlers
trap - SIGKILL SIGINT SIGTERM SIGQUIT

# install own signal handler
trap "trap_signal" SIGTERM SIGINT SIGQUIT

# set own IFS and PATH settings
PATH="/bin:/usr/bin:/sbin:/usr/sbin"
IFS=$' \t\n'
export PATH
export IFS

# ---- functions ----

# change the password in the pppd password files
# Parameters:
#  1. username
#  2. configuration
#  3. password
#  4. secret file
function setpassword {
ex -s $4 <<EOT
%s/^\"$1\".*$2.*\$/\"$1\" $2 \"$3\"/g
w
x
EOT
}

# show usage of this script and exit
function usage {
  echo "Usage: startpppd.sh PPPDConfiguration|--help"
  echo
  echo "Start pppd in a safer way. The script ask the user everytime for"
  echo "the connection password and wrote this to pap-secrets or chat-secrets"
  echo "dependent of the settings in \$AUTH_TYPES"
  echo "After starting the pppd the password will removed from the file after"
  echo "a period of $PPPD_WAIT seconds."
  echo "Thereby the password is not visible in the process table nor the"
  echo "system log files."
  echo
  echo "Options:"
  echo "  --help            Show this message"
  echo " PPPDConfiguration  Configuration read by pppd"
  echo "                    Use pppconfig or other tools to create all needed"
  echo "                    files for this. See also the man page of pppd"
  echo "                    option \"call\" for more informations about this."
  exit $1
}

# signal handler of all signals catches with trag
trap_signal() {
  # reenable showing input characters
  stty echo
  # remove password preventive
  if [ ! -z "$PPPD_PASSFILE" ]; then 
    setpassword $USERNAME $PPPD_CONFIG "" $PPPD_PASSFILE
  fi
}

# --- main stuff ----

# hide input characters
MODE_ECHOOFF="stty -echo"

# show input characters
MODE_ECHOON="stty echo"

# check options
#==============

# check options
[ -z "$1" ] && usage 1
[ "$1" = "--help" -o "$1" = "-h" ] && usage

# pppd exists?
if [ -z "$(which pppd)" ]; then
  echo "ERROR: pppd not found"
  exit 1
fi

# pppd config exists?
if [ ! -e ${PPPD_CONFIGDIR}/peers/$PPPD_CONFIG ]; then
  echo "ERROR: pppd configuration $PPPD_CONFIG does not exists"
  exit 2
fi

# compute all needed informations / settings
#===========================================

# extract auth type
for i in $AUTH_TYPES; do
  _CONFIG=$(echo $i | awk -F: '{ print $1 }')
  _AUTH=$(echo $i | awk -F: '{ print $2 }')
  if [ "$_CONFIG" = "$PPPD_CONFIG" ]; then
    PPPD_AUTH=$_AUTH
    break
  fi
done
unset _CONFIG
unset _AUTH

# check valid auth type
case $PPPD_AUTH in
  pap|chap) 
    PPPD_PASSFILE=${PPPD_CONFIGDIR}/${PPPD_AUTH}-secrets
    ;;
  *)
    echo "ERROR: Unknown authentication type $PPPD_AUTH"
    echo "       Please set \$AUTH_TYPES to correct values"
    exit 3
    ;;
esac    
    
# get password
echo -n "Please insert user password for $USERNAME ($PPPD_CONFIG): "
$MODE_ECHOOFF
read PASSWORD
$MODE_ECHOON
echo " "

# add password to password file (pap-secrects or chap-secrets)
echo "Write password to $PPPD_PASSFILE ..."
setpassword $USERNAME $PPPD_CONFIG $PASSWORD $PPPD_PASSFILE

# start pppd
echo "Start pppd..."
pppd call $PPPD_CONFIG

echo "Wait for connection..."
sleep $PPPD_WAIT

# remove passwords from password file
echo "Remove password from $PPPD_PASSFILE ..."
setpassword $USERNAME $PPPD_CONFIG "" $PPPD_PASSFILE


