Cover v07 i13
Article
Listing 1
Listing 2
Listing 3
Listing 4
Listing 5
Listing 6
Listing 7


Listing 2

#! /bin/bash -
# FILENAME: mkhtaccess
# DESCRIPTION: Creates htaccess files to protect an httpd directory tree.
# Protection may be specified through an input file or, for single directory,
# on the command line. Input file format is:
#
# dir USER=user[,user,...] GROUP=group[,group,...] ALLOW=net[,net,...] 	
#        DENY=net[,net,...]
#
# Comments are allowed on whole lines or part preceded by "#".
#
# Usernames and groups must be recognized by httpd, i.e. included in global or
# local htpasswd and htgroup files.
#
# USAGE: mkhtaccess [-H] [-f file] [-d network[,network,...]]
#	[-a net[,net,...]] [-t template] [-h file] [-v]
#	[-D dir] [-g group[,group,...]] [-u user[,user,...]]
# OPTIONS:
#	-H - Prints help message
#	-f file - Uses "file" for protection assignments
#	-d network - Denies access from "network"
#	-a network - Allows access from "network"
#	-t template - Uses htaccess file template
#	-h file - Name of htaccess files created
#	-D dir - Works on this directory's protections
#	-g group - Grants access to specified group(s)
#	-u user - Grants access to specified user(s)
#	-v - Produces verbose output
#
# LABEN S.p.A. - 23-dec-1997
#
# HISTORY:
# 0.0	Luca Salvadori <lsalvadori.laben.it> - 23-dec-1997
# 	- Functions and behaviour
# 0.1	Luca Salvadori <lsalvadori.laben.it> - 28-dec-1997
# 	- New options added
#
#
########################## S U B R O U T I N E S ##########################

# Program information
AUTHOR="Luca Salvadori <salvadori.l@laben.it>"
VERSION="0.1"
DATE="28-dec-1997"
# Initializing global variables
# Default networks to grant access to
DEF_ALLOW=laben.it,193.42.128.,193.42.129.,193.42.130.,193.42.131.
# Default networks to deny access to
DEF_DENY=all
DEF_TEMPLATE=htaccess.template        # Default template for htaccess
DEF_GROUP=sysadm                      # Default group to grant access to
DEF_USER=root                         # Default user to grant access to
DEF_FILE=mkhtaccess.dat               # Default input file
DEF_HTACCESS=.htaccess                # Default output file(s)
DEF_DIR=~/public_html/                # Default directory to protect
DIR_SELECTED=0                        # Initialize index to false (0)
FILE_SELECTED=0                       # Initialize index to false (0)
VERBOSE=0                             # Brief output is default
TEMP=/tmp                             # Scratch directory
TMPFILE=$TEMP/`basename $0`.$$        # Temporary file
CMDFILE=$TEMP/`basename $0`.ed.$$     # Temporary command file
# Options string
OPTS=":-H -t: -a: -d: -g: -u: -f: -h: -D: -v"
# Default options
DEFOPT="-D $DEF_DIR -a $DEF_ALLOW -d $DEF_DENY -h $DEF_HTACCESS -t $DEF_TEMPLATE"
# End of global variables initialization

function helpmsg() {
	echo "" 1>&2
	echo " `basename $0` Version $VERSION - $DATE" 1>&2
	echo " Author: $AUTHOR" 1>&2
	echo "" 1>&2
	echo " USAGE: `basename $0` [-H] [-f file] [-d network[,network,...]]" 1>&2
	echo "	[-a net[,net,...]] [-t template] [-h file] [-v]" 1>&2
	echo "	[-D dir] [-g group[,group,...]] [-u user[,user,...]]" 1>&2
	echo " OPTIONS:" 1>&2
	echo "	-H - Prints help message" 1>&2
	echo "	-f file - Uses "file" for protection assignments" 1>&2
	echo "	-d network - Denies access from "network"" 1>&2
	echo "	-a network - Allows access from "network"" 1>&2
	echo "	-t template - Uses htaccess file template" 1>&2
	echo "	-h file - Name of htaccess files created" 1>&2
	echo "	-D dir - Works on this directory's protections" 1>&2
	echo "	-g group - Grants access to specified group(s)" 1>&2
	echo "	-u user - Grants access to specified user(s)" 1>&2
	echo "	-v - Produces verbose output" 1>&2
	echo "" 1>&2
}

##################### E N D  O F  S U B R O U T I N E S ####################


########################## M A I N  P R O G R A M ##########################

# Parsing input parameters and assigning default if needed
options=`echo $*`
[ "$options" = "" ] && { $0 $DEFOPT ; exit }

# Parsing options and setting defaults if needed
while [ $OPTIND -le $# ]
do
	getopts "$OPTS" option
	case $option in
		t)
			TEMPLATE=$OPTARG
			;;
		a)
			ALLOW=$OPTARG
			;;
		d)
			DENY=$OPTARG
			;;
		h)
			HTACCESS=$OPTARG
			;;
		H)
			helpmsg
			exit 0
			;;
		g)
			GROUP=$OPTARG
			;;
		u)
			USER=$OPTARG
			;;
		f)
			FILE=$OPTARG
			FILE_SELECTED=1
			;;
		D)
			DIR=$OPTARG
			DIR_SELECTED=1
			;;
		v)
			VERBOSE=1
			;;
		"?")
			echo "`basename $0` - ERROR: Option -$OPTARG requires an argument or is unknown." 1>&2
			echo "Run `basename $0` -H for help." 1>&2
			exit 3
			;;
		*)
			echo "`basename $0` - ERROR: Unknown option -$OPTARG." 1>&2
			echo "Run `basename $0` -H for help." 1>&2
			exit 2
			;;
	esac
	case $OPTARG in
		-*)
			echo "`basename $0` - ERROR: Option -$option requires an argument." 1>&2
			echo "Invalid argument $OPTARG." 1>&2
			echo "Run `basename $0` -H for help." 1>&2
			exit 3
			;;
	esac
done
# Setting defaults for unselected options
TEMPLATE=${TEMPLATE:-$DEF_TEMPLATE}
ALLOW=${ALLOW:-$DEF_ALLOW}
DENY=${DENY:-$DEF_DENY}
HTACCESS=${HTACCESS:-$DEF_HTACCESS}
GROUP=${GROUP:-$DEF_GROUP}
USER=${USER:-$DEF_USER}
FILE=${FILE:-$DEF_FILE}
DIR=${DIR:-$DEF_DIR}
# Perform sanity checks, just in case
[ $FILE_SELECTED -eq 1 -a $DIR_SELECTED -eq 1 ] && { echo "`basename $0` - ERROR: Options -D and -f are mutually exclusive. Select only one." 1>&2 ; echo "Run `basename $0` -H for help." 1>&2 ; exit 4 }
[ -f $TEMPLATE ] || { echo "`basename $0` - ERROR: Template file $TEMPLATE does not exist." 1>&2 ; echo "Run `basename $0` -H for help." 1>&2 ; exit 5 }
[ $FILE_SELECTED -eq 1 -a ! -f $FILE ] && { echo "`basename $0` - ERROR: Data file $FILE does not exist." 1>&2 ; echo "Run `basename $0` -H for help." 1>&2 ; exit 6 }
[ $DIR_SELECTED -eq 1 -a ! -d $DIR ] && { echo "`basename $0` - ERROR: Directory $DIR does not exist." 1>&2 ; echo "Run `basename $0` -H for help." 1>&2 ; exit 7 }

# Here begins the real stuff

# Some nice output for verbose mode
[ $VERBOSE -eq 1 ] && echo "`basename $0` - Verbose output
-------------------------------------------------------------
Invoked with following defaults:
- Allowed user(s): $USER
- Allowed group(s): $GROUP
- Allowed network(s): $ALLOW
- Denied network(s): $DENY
- Output file: $HTACCESS
- Template file: $TEMPLATE
-------------------------------------------------------------"

# Creating scratch file
[ $FILE_SELECTED -eq 1 ] && cat $FILE | sed -e "s/#.*$//" -e "s/ /;/g" > $TMPFILE
[ $DIR_SELECTED -eq 1 ] && echo "$DIR;USER=$USER;GROUP=$GROUP;ALLOW=$ALLOW;DENY=$DENY" > $TMPFILE

# Now loop over directories
for line in `cat $TMPFILE`
do
	# Cleanup previous command file, if any
	[ -f $CMDFILE ] && rm $CMDFILE
	# Unset local variables
	unset _DIR _USER _GROUP _ALLOW _DENY
	# Parse and evaluate line
	line=`echo $line | sed -e "s/^/_DIR=/" -e "s/USER=/_USER=/g" -e "s/GROUP=/_GROUP=/g" -e "s/ALLOW=/_ALLOW=/g" -e "s/DENY=/_DENY=/g"`
	eval $line
	# Another sanity check
	[ $_DIR ] || { echo "`basename $0` - ERROR: Incorrect record format in file $FILE." 1>&2 ; echo "Run `basename $0` -H for help." 1>&2 ; exit 5 }
	# Output in verbose mode
	[ $VERBOSE -eq 1 ] && echo "Directory: $_DIR"
	# Set allowed networks
	_ALLOW=${_ALLOW:-$ALLOW}
	# Write relevant lines in command file
	if [ $_ALLOW ] 
	then
		[ $VERBOSE -eq 1 ] && echo "Allowed networks: $_ALLOW"
		echo "1
		/^# allow from NETWORK/
		c" >> $CMDFILE
		for net in `echo $_ALLOW | tr -s "," " "`
		do
			echo "allow from $net" >> $CMDFILE
		done
		echo "." >> $CMDFILE
	fi
	# Set denied networks
	_DENY=${_DENY:-$DENY}
	# Write relevant lines in command file
	if [ $_DENY ] 
	then
		[ $VERBOSE -eq 1 ] && echo "Denied networks: $_DENY"
		echo "1
		/^# deny from NETWORK/
		c" >> $CMDFILE
		for net in `echo $_DENY | tr -s "," " "`
		do
			echo "deny from $net" >> $CMDFILE
		done
		echo "." >> $CMDFILE
	fi
	# Set allowed users
	_USER=${_USER:-$USER}
	# Write relevant lines in command file
	if [ $_USER ] 
	then
		[ $VERBOSE -eq 1 ] && echo "Allowed users: $_USER"
		echo "1
		/^# require user USER/
		c" >> $CMDFILE
		echo "require user `echo $_USER | tr -s "," " "`" >> $CMDFILE
		echo "." >> $CMDFILE
	fi
	# Set allowed groups
	_GROUP=${_GROUP:-$GROUP}
	# Write relevant lines in command file
	if [ $_GROUP ] 
	then
		[ $VERBOSE -eq 1 ] && echo "Allowed groups: $_GROUP"
		echo "1
		/^# require group GROUP/
		c" >> $CMDFILE
		echo "require group `echo $_GROUP | tr -s "," " "`" >> $CMDFILE
		echo "." >> $CMDFILE
	fi
	# Close command file
	echo "wq $_DIR/$HTACCESS" >> $CMDFILE
	[ $VERBOSE -eq 1 ] && { 
		echo "Saving to file: $_DIR/$HTACCESS"
		echo "----------------------------------------------------------"
	}
	# Edit template upon command file and save it to final location
	ed -s $TEMPLATE < $CMDFILE 2>&1 > /dev/null
done

# Cleanup and exit
[ -f $TMPFILE ] && rm $TMPFILE
[ -f $CMDFILE ] && rm $CMDFILE
exit 0

#################### E N D  O F  M A I N  P R O G R A M ####################