1*0Sstevel@tonic-gate#!/usr/bin/ksh 2*0Sstevel@tonic-gate# 3*0Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 4*0Sstevel@tonic-gate# 5*0Sstevel@tonic-gate# Copyright (c) 1997-2001 by Sun Microsystems, Inc. 6*0Sstevel@tonic-gate# All rights reserved. 7*0Sstevel@tonic-gate# 8*0Sstevel@tonic-gate# 9*0Sstevel@tonic-gate# This script sets up a virtual FTP host. 10*0Sstevel@tonic-gate# 11*0Sstevel@tonic-gate# Usage: 12*0Sstevel@tonic-gate# ftpaddhost -c|-l [-b] [ -x xferlog ] hostname root_dir 13*0Sstevel@tonic-gate# 14*0Sstevel@tonic-gate# ftpaddhost configures virtual host hostname under directory root_dir. 15*0Sstevel@tonic-gate# An IP address can be used for hostname. 16*0Sstevel@tonic-gate# 17*0Sstevel@tonic-gate# The -c (complete) option configures complete virtual hosting, which allows 18*0Sstevel@tonic-gate# each virtual host to have its own version of the ftpaccess, ftpconversions, 19*0Sstevel@tonic-gate# ftpgroups, ftphosts and ftpusers files. The master version of each of these 20*0Sstevel@tonic-gate# configuration files is copied from the /etc/ftpd directory and placed in 21*0Sstevel@tonic-gate# the /etc/ftpd/virtual-ftpd/hostname directory. If the /etc/ftpusers file 22*0Sstevel@tonic-gate# exists it is appended to the virtual ftpusers file. If a virtual host lacks 23*0Sstevel@tonic-gate# its own version of a configuration file, the master version is used. 24*0Sstevel@tonic-gate# 25*0Sstevel@tonic-gate# The -l (limited) option configures limited virtual hosting, which only 26*0Sstevel@tonic-gate# allows a small number of parameters to be configured differently for a 27*0Sstevel@tonic-gate# virtual host (see the virtual keyword on the ftpaccess(4) manual page). 28*0Sstevel@tonic-gate# 29*0Sstevel@tonic-gate# When the -b (banner) option is supplied, ftpaddhost creates a banner for 30*0Sstevel@tonic-gate# the virtual host, useful to see that the virtual host is working. 31*0Sstevel@tonic-gate# 32*0Sstevel@tonic-gate# When the -x xferlog option is supplied, ftpaddhost creates a logfile entry 33*0Sstevel@tonic-gate# which causes the transfer logs for the virtual host to be written to the 34*0Sstevel@tonic-gate# specified file. 35*0Sstevel@tonic-gate# 36*0Sstevel@tonic-gate# Exit codes: 0 - success 37*0Sstevel@tonic-gate# 1 - usage 38*0Sstevel@tonic-gate# 2 - command failure 39*0Sstevel@tonic-gate# 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gateusage() 42*0Sstevel@tonic-gate{ 43*0Sstevel@tonic-gate fmt=`gettext "Usage: %s -c|-l [-b] [ -x xferlog ] hostname root_dir"` 44*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" >&2 45*0Sstevel@tonic-gate exit 1 46*0Sstevel@tonic-gate} 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gateverify_root() 49*0Sstevel@tonic-gate{ 50*0Sstevel@tonic-gate # Verify caller has a real user ID of 0. 51*0Sstevel@tonic-gate set `id` 52*0Sstevel@tonic-gate if [ "$1" != "uid=0(root)" ] 53*0Sstevel@tonic-gate then 54*0Sstevel@tonic-gate fmt=`gettext "%s: Error: Only root can run %s"` 55*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" "$cmd" >&2 56*0Sstevel@tonic-gate exit 1 57*0Sstevel@tonic-gate fi 58*0Sstevel@tonic-gate} 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate# Make directory $1 with mode $2 and ownership $3. 61*0Sstevel@tonic-gatemake_dir() 62*0Sstevel@tonic-gate{ 63*0Sstevel@tonic-gate if [ ! -d "$1" ] 64*0Sstevel@tonic-gate then 65*0Sstevel@tonic-gate mkdir "$1" || exit 2 66*0Sstevel@tonic-gate fi 67*0Sstevel@tonic-gate chmod "$2" "$1" 68*0Sstevel@tonic-gate chown "$3" "$1" 69*0Sstevel@tonic-gate} 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gatesetup_complete_vhost() 72*0Sstevel@tonic-gate{ 73*0Sstevel@tonic-gate fmt=`gettext "Setting up complete virtual host %s"` 74*0Sstevel@tonic-gate printf "$fmt\n" "$hostname" 75*0Sstevel@tonic-gate make_dir /etc/ftpd/virtual-ftpd 755 root:sys 76*0Sstevel@tonic-gate make_dir "/etc/ftpd/virtual-ftpd/$hostname" 755 root:sys 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate fmt=`gettext "Configuration directory is %s"` 79*0Sstevel@tonic-gate printf "$fmt\n" "/etc/ftpd/virtual-ftpd/$hostname" 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate # Update the virtual host configuration file. 82*0Sstevel@tonic-gate vhconfig=/etc/ftpd/ftpservers 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate fmt=`gettext "Updating virtual hosting configuration file %s"` 85*0Sstevel@tonic-gate printf "$fmt\n" $vhconfig 86*0Sstevel@tonic-gate if [ -f $vhconfig ] 87*0Sstevel@tonic-gate then 88*0Sstevel@tonic-gate # Remove any existing entries for the virtual host. 89*0Sstevel@tonic-gate sed "/^[ ]*$hostname[ ]/d" $vhconfig >$vhconfig.tmp.$$ 90*0Sstevel@tonic-gate mv -f $vhconfig.tmp.$$ $vhconfig || exit 2 91*0Sstevel@tonic-gate fi 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate echo "$hostname /etc/ftpd/virtual-ftpd/$hostname" >>$vhconfig 94*0Sstevel@tonic-gate chmod 644 $vhconfig 95*0Sstevel@tonic-gate chown root:sys $vhconfig 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate # Make copies of the master configuration files. 98*0Sstevel@tonic-gate for file in ftpconversions ftpgroups ftphosts ftpusers 99*0Sstevel@tonic-gate do 100*0Sstevel@tonic-gate target="/etc/ftpd/virtual-ftpd/$hostname/$file" 101*0Sstevel@tonic-gate rm -f "$target" 102*0Sstevel@tonic-gate if [ -f /etc/ftpd/$file ] 103*0Sstevel@tonic-gate then 104*0Sstevel@tonic-gate cp /etc/ftpd/$file "$target" || exit 2 105*0Sstevel@tonic-gate chmod 644 "$target" 106*0Sstevel@tonic-gate chown root:sys "$target" 107*0Sstevel@tonic-gate fi 108*0Sstevel@tonic-gate done 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate # Append /etc/ftpusers to the virtual hosts ftpusers. 111*0Sstevel@tonic-gate if [ -f /etc/ftpusers ] 112*0Sstevel@tonic-gate then 113*0Sstevel@tonic-gate target="/etc/ftpd/virtual-ftpd/$hostname/ftpusers" 114*0Sstevel@tonic-gate cat /etc/ftpusers >>"$target" 115*0Sstevel@tonic-gate chmod 644 "$target" 116*0Sstevel@tonic-gate chown root:sys "$target" 117*0Sstevel@tonic-gate fi 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate vhftpaccess="/etc/ftpd/virtual-ftpd/$hostname/ftpaccess" 120*0Sstevel@tonic-gate rm -f "$vhftpaccess" 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate # Remove any existing root or logfile entries. 123*0Sstevel@tonic-gate sed "/^[ ]*root[ ]/d 124*0Sstevel@tonic-gate /^[ ]*logfile[ ]/d" $ftpaccess >"$vhftpaccess" 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate # Add the virtual host root. 127*0Sstevel@tonic-gate echo "root $vhroot" >>"$vhftpaccess" 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate # Add a banner to show the virtual host configuration worked. 130*0Sstevel@tonic-gate if [ -n "$banner" ] 131*0Sstevel@tonic-gate then 132*0Sstevel@tonic-gate # Add a banner entry if there isn't already one. 133*0Sstevel@tonic-gate grep "^[ ]*banner[ ]" "$vhftpaccess" >/dev/null 2>&1 134*0Sstevel@tonic-gate if [ $? -eq 0 ] 135*0Sstevel@tonic-gate then 136*0Sstevel@tonic-gate fmt=`gettext "Existing banner entry not changed in %s"` 137*0Sstevel@tonic-gate printf "$fmt\n" "$vhftpaccess" 138*0Sstevel@tonic-gate else 139*0Sstevel@tonic-gate bannerf="/etc/ftpd/virtual-ftpd/$hostname/cbanner.msg" 140*0Sstevel@tonic-gate if [ -f "$bannerf" ] 141*0Sstevel@tonic-gate then 142*0Sstevel@tonic-gate fmt=`gettext "Using existing banner file %s"` 143*0Sstevel@tonic-gate printf "$fmt\n" "$bannerf" 144*0Sstevel@tonic-gate else 145*0Sstevel@tonic-gate fmt=`gettext "Creating banner file %s"` 146*0Sstevel@tonic-gate printf "$fmt\n" "$bannerf" 147*0Sstevel@tonic-gate fmt=`gettext "Complete virtual host %%L test banner"` 148*0Sstevel@tonic-gate printf "$fmt\n" >"$bannerf" 149*0Sstevel@tonic-gate chmod 644 "$bannerf" 150*0Sstevel@tonic-gate chown root:sys "$bannerf" 151*0Sstevel@tonic-gate fi 152*0Sstevel@tonic-gate echo "banner $bannerf" >>"$vhftpaccess" 153*0Sstevel@tonic-gate fi 154*0Sstevel@tonic-gate fi 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate # Add the transfer logfile. 157*0Sstevel@tonic-gate if [ -n "$logfile" ] 158*0Sstevel@tonic-gate then 159*0Sstevel@tonic-gate echo "logfile $logfile" >>"$vhftpaccess" 160*0Sstevel@tonic-gate fi 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate chmod 644 "$vhftpaccess" 163*0Sstevel@tonic-gate chown root:sys "$vhftpaccess" 164*0Sstevel@tonic-gate} 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gatesetup_limited_vhost() 167*0Sstevel@tonic-gate{ 168*0Sstevel@tonic-gate # Check complete virtual hosting is not configured for the host. 169*0Sstevel@tonic-gate grep "^[ ]*$hostname[ ]" /etc/ftpd/ftpservers >/dev/null 2>&1 170*0Sstevel@tonic-gate if [ $? -eq 0 ] 171*0Sstevel@tonic-gate then 172*0Sstevel@tonic-gate fmt=`gettext "%s: Error: Complete virtual hosting already configured for %s"` 173*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" "$hostname" >&2 174*0Sstevel@tonic-gate exit 1 175*0Sstevel@tonic-gate fi 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate fmt=`gettext "Setting up limited virtual host %s"` 178*0Sstevel@tonic-gate printf "$fmt\n" "$hostname" 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate # Update the ftpaccess file. 181*0Sstevel@tonic-gate fmt=`gettext "Updating FTP server configuration file %s"` 182*0Sstevel@tonic-gate printf "$fmt\n" $ftpaccess 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate # Remove any existing entries for the virtual host. 185*0Sstevel@tonic-gate sed "/^[ ]*virtual[ ][ ]*$hostname[ ]/d" $ftpaccess >$ftpaccess.tmp.$$ 186*0Sstevel@tonic-gate mv -f $ftpaccess.tmp.$$ $ftpaccess || exit 2 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate # Add a limited virtual hosting entry for the virtual host. 189*0Sstevel@tonic-gate echo "virtual $hostname root $vhroot" >>$ftpaccess 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate # Add a banner to show the virtual host configuration worked. 192*0Sstevel@tonic-gate if [ -n "$banner" ] 193*0Sstevel@tonic-gate then 194*0Sstevel@tonic-gate bannerf="/etc/ftpd/virtual-ftpd/$hostname/lbanner.msg" 195*0Sstevel@tonic-gate if [ -f "$bannerf" ] 196*0Sstevel@tonic-gate then 197*0Sstevel@tonic-gate fmt=`gettext "Using existing banner file %s"` 198*0Sstevel@tonic-gate printf "$fmt\n" "$bannerf" 199*0Sstevel@tonic-gate else 200*0Sstevel@tonic-gate fmt=`gettext "Creating banner file %s"` 201*0Sstevel@tonic-gate printf "$fmt\n" "$bannerf" 202*0Sstevel@tonic-gate make_dir /etc/ftpd/virtual-ftpd 755 root:sys 203*0Sstevel@tonic-gate make_dir "/etc/ftpd/virtual-ftpd/$hostname" 755 root:sys 204*0Sstevel@tonic-gate fmt=`gettext "Limited virtual host %%L test banner"` 205*0Sstevel@tonic-gate printf "$fmt\n" >"$bannerf" 206*0Sstevel@tonic-gate chmod 644 "$bannerf" 207*0Sstevel@tonic-gate chown root:sys "$bannerf" 208*0Sstevel@tonic-gate fi 209*0Sstevel@tonic-gate echo "virtual $hostname banner $bannerf" >>$ftpaccess 210*0Sstevel@tonic-gate fi 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate # Add the transfer logfile. 213*0Sstevel@tonic-gate if [ -n "$logfile" ] 214*0Sstevel@tonic-gate then 215*0Sstevel@tonic-gate echo "virtual $hostname logfile $logfile" >>$ftpaccess 216*0Sstevel@tonic-gate fi 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate chmod 644 $ftpaccess 219*0Sstevel@tonic-gate chown root:sys $ftpaccess 220*0Sstevel@tonic-gate} 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate# Execution starts here. 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gateIFS=" 225*0Sstevel@tonic-gate" 226*0Sstevel@tonic-gateSHELL=/usr/bin/ksh 227*0Sstevel@tonic-gatePATH=/usr/bin 228*0Sstevel@tonic-gateTEXTDOMAIN=SUNW_OST_OSCMD 229*0Sstevel@tonic-gateexport SHELL PATH IFS TEXTDOMAIN 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gatecmd=`basename "$0"` 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gateverify_root 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gatewhile getopts bclx: arg 236*0Sstevel@tonic-gatedo 237*0Sstevel@tonic-gate case $arg in 238*0Sstevel@tonic-gate b) banner=1;; 239*0Sstevel@tonic-gate c) complete=1;; 240*0Sstevel@tonic-gate l) limited=1;; 241*0Sstevel@tonic-gate x) logfile="$OPTARG";; 242*0Sstevel@tonic-gate \?) usage;; 243*0Sstevel@tonic-gate esac 244*0Sstevel@tonic-gatedone 245*0Sstevel@tonic-gateshift `expr $OPTIND - 1` 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate# Check arguments. 248*0Sstevel@tonic-gate[ -z "$complete" -a -z "$limited" ] && usage 249*0Sstevel@tonic-gate[ -n "$complete" -a -n "$limited" ] && usage 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate[ $# -ne 2 ] && usage 252*0Sstevel@tonic-gatehostname="$1" 253*0Sstevel@tonic-gatevhroot="$2" 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate[ -z "$hostname" -o -z "$vhroot" ] && usage 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gateecho "$hostname" | grep / >/dev/null 2>&1 258*0Sstevel@tonic-gateif [ $? -eq 0 ] 259*0Sstevel@tonic-gatethen 260*0Sstevel@tonic-gate fmt=`gettext "%s: Error: hostname must not contain a /"` 261*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" >&2 262*0Sstevel@tonic-gate usage 263*0Sstevel@tonic-gatefi 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gateecho "$vhroot" | grep "^/" >/dev/null 2>&1 266*0Sstevel@tonic-gateif [ $? -ne 0 ] 267*0Sstevel@tonic-gatethen 268*0Sstevel@tonic-gate fmt=`gettext "%s: Error: root_dir must be an absolute pathname"` 269*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" >&2 270*0Sstevel@tonic-gate usage 271*0Sstevel@tonic-gatefi 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gateif [ -n "$logfile" ] 274*0Sstevel@tonic-gatethen 275*0Sstevel@tonic-gate echo "$logfile" | grep "^/" >/dev/null 2>&1 276*0Sstevel@tonic-gate if [ $? -ne 0 ] 277*0Sstevel@tonic-gate then 278*0Sstevel@tonic-gate fmt=`gettext "%s: Error: xferlog must be an absolute pathname"` 279*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" >&2 280*0Sstevel@tonic-gate usage 281*0Sstevel@tonic-gate fi 282*0Sstevel@tonic-gatefi 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gateftpaccess=/etc/ftpd/ftpaccess 285*0Sstevel@tonic-gateif [ ! -f $ftpaccess ] 286*0Sstevel@tonic-gatethen 287*0Sstevel@tonic-gate fmt=`gettext "%s: Error: FTP server configuration file %s missing"` 288*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" $ftpaccess >&2 289*0Sstevel@tonic-gate exit 2 290*0Sstevel@tonic-gatefi 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gategrep "^ftp:" /etc/passwd >/dev/null 2>&1 293*0Sstevel@tonic-gateif [ $? -ne 0 ] 294*0Sstevel@tonic-gatethen 295*0Sstevel@tonic-gate fmt=`gettext "Warning: Must create ftp user account before virtual hosts will work"` 296*0Sstevel@tonic-gate printf "$fmt\n" 297*0Sstevel@tonic-gatefi 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate# Ignore certain signals. 300*0Sstevel@tonic-gatetrap '' 1 2 3 15 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gateumask 022 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gateif [ -n "$complete" ] 305*0Sstevel@tonic-gatethen 306*0Sstevel@tonic-gate setup_complete_vhost 307*0Sstevel@tonic-gateelse 308*0Sstevel@tonic-gate setup_limited_vhost 309*0Sstevel@tonic-gatefi 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate/usr/sbin/ftpconfig -d "$vhroot" >/dev/null 312*0Sstevel@tonic-gateif [ $? -ne 0 ] 313*0Sstevel@tonic-gatethen 314*0Sstevel@tonic-gate fmt=`gettext "%s: Error: ftpconfig -d %s failed"` 315*0Sstevel@tonic-gate printf "$fmt\n" "$cmd" "$vhroot" >&2 316*0Sstevel@tonic-gate exit 2 317*0Sstevel@tonic-gatefi 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gateexit 0 320