#!/bin/sh # # qfirewall_admin # Copyright 2004, Bill Shupp # Version: 0.1 (initial release) # # This is a simple shell script to allow remote addition and deletion of # qmail forward domains, to be run from tcpserver. It supports only a few # commands: # # quit # login # list_routes # add_route # del_route # # NOTES: authentication must succeed before the other commands will # be accepted. quit may be issued at any time. Incorrect number of arguments # to any command other than quit will result in "-ERR syntax error". # # # # Sample run script for tcpserver: # ##!/bin/sh #exec /usr/local/bin/softlimit -m 8000000 \ # /usr/local/bin/tcpserver -v -H -R -l 0 \ # -x /etc/qfrirewall_admin.cdb \ # -u `id -u vpopmail` -g `id -g qmaild` 0 2112 \ # /usr/local/sbin/qfirewall_admin 2>&1 # # # Sample run script for multilog: #!/bin/sh #exec /usr/local/bin/multilog t /var/log/qfirewall_admin # CONFGURATION OPTIONS SMTPROUTES='/var/qmail/control/smtproutes' RCPTHOSTS='/var/qmail/control/rcpthosts' USER='admin' PASS='testpass' DEBUG=0 ################### SHOULD NOT NEED TO EDIT BELOW HERE ######################## # FUNCTIONS strip_return () { echo ${1} | tr -d '\r/' } to_upper () { strip_return ${1} | awk '{ print toupper($1) }' } qmail_hup() { svc -du /service/qmail-send } quit() { echo "+OK" exit } unimplemented () { echo "-ERR unimplemented" continue } syntax_err () { echo "-ERR syntax error" continue } list_routes() { if [ -f ${SMTPROUTES} ] ; then cat ${SMTPROUTES} echo "." else echo "-ERR ${SMTPROUTES} does not exist" continue fi } add_route () { if [ -z "$2" ] ; then syntax_err fi TEST=`valid_ip ${2}` if [ $TEST -ne 1 ] ; then syntax_err fi # check for the domain in rcpthosts TEST=`grep -ie "^$1$" $RCPTHOSTS` if [ ! -z "$TEST" ] ; then echo "-ERR $1 already exists in $RCPTHOSTS" continue fi # check for the domain in smtproutes TEST=`grep -ie "^$1:" $SMTPROUTES` if [ ! -z "$TEST" ] ; then echo "-ERR $1 already exists in $SMTPROUTES" continue fi # Locking?? cp $RCPTHOSTS $RCPTHOSTS.bak cp $SMTPROUTES $SMTPROUTES.bak echo ${1} >> $RCPTHOSTS echo "${1}:${2}" >> $SMTPROUTES echo "+OK" } del_route () { if [ -z "$1" ] ; then syntax_err fi # check for the domain in rcpthosts TEST=`grep -ie "^$1$" $RCPTHOSTS` if [ -z "$TEST" ] ; then echo "-ERR $1 doesn't exist in $RCPTHOSTS" continue fi # check for the domain in smtproutes TEST=`grep -ie "^$1:" $SMTPROUTES` if [ -z "$TEST" ] ; then echo "-ERR $1 doesn't exist in $SMTPROUTES" continue fi # Locking?? cp $RCPTHOSTS $RCPTHOSTS.bak cp $SMTPROUTES $SMTPROUTES.bak grep -v "^$1$" $RCPTHOSTS > $RCPTHOSTS.new mv $RCPTHOSTS.new $RCPTHOSTS grep -v "^$1:" $SMTPROUTES > $SMTPROUTES.new mv $SMTPROUTES.new $SMTPROUTES echo "+OK" } valid_ip () { echo ${1} | egrep -q -v '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' echo $? } # AUTHENTICATION LOGINOK=0 echo "+OK" while [ $LOGINOK != 1 ] ; do # GET LOGIN read COMMANDFROMSHELL ARGUMENT1 ARGUMENT2 COMMAND=`to_upper $COMMANDFROMSHELL` USERGIVEN=`strip_return ${ARGUMENT1}` PASSGIVEN=`strip_return ${ARGUMENT2}` if [ "$DEBUG" -eq 1 ] ; then echo "COMMAND: $COMMAND" > /dev/stderr echo "USERGIVEN: $USERGIVEN" > /dev/stderr echo "PASSGIVEN: $PASSGIVEN" > /dev/stderr fi if [ ${COMMAND} = "QUIT" ] ; then quit fi if [ "$COMMAND" != "LOGIN" ] ; then echo "-ERR authentication first" continue fi if [ ! "$ARGUMENT2" ] ; then echo "-ERR syntax error" continue fi if [ "${USERGIVEN}" != "${USER}" ] || [ "${PASSGIVEN}" != "${PASS}" ] ; then echo "-ERR authentication failed" if [ "$DEBUG" -eq 1 ] ; then echo "USER: $USER" > /dev/stderr echo "PASS: $PASS" > /dev/stderr echo "USERGIVEN: $USERGIVEN" > /dev/stderr echo "PASSGIVEN: $PASSGIVEN" > /dev/stderr fi exit else LOGINOK=1 echo "+OK" fi done # AUTHENTICATION COMPLETE # GET COMMAND HAVECOMMAND=0 while [ $HAVECOMMAND != 1 ] ; do # GET COMMAND read COMMANDFROMSHELL ARG1 ARG2 COMMAND=`to_upper ${COMMANDFROMSHELL}` ARGUMENT1=`strip_return ${ARG1}` ARGUMENT2=`strip_return ${ARG2}` case $COMMAND in QUIT) quit ;; LIST_ROUTES) list_routes ;; ADD_ROUTE) add_route ${ARGUMENT1} ${ARGUMENT2} ;; DEL_ROUTE) del_route ${ARGUMENT1} ;; *) unimplemented ;; esac done