#!/bin/sh # Copyright (c) 2003 Andy Barclay (Unixpeople) # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # This cgi script will allow the user to update dns zone(s) # ensure that /usr/local/bin is first on the path so we get the # good version of nsupdate (sun machines....) PATH=/usr/local/bin:$PATH ZONES="unixpeople.internal vmprivate.com 254.168.192.in-addr.arpa 253.168.192.in-addr.arpa 37.168.192.in-addr.arpa." RRTYPES="A CNAME PTR NS MX TXT" DEFTTL=86400 NEWAWK=/usr/xpg4/bin/awk # choose format based on version of nsupdate # this is an invalid option nsupdate --version 2>/tmp/nsupdate.$$ if grep -- "-y" /tmp/nsupdate.$$ >/dev/null then # its the newer version DNSKEY=dnskeys/dynupdates else # its the old (sun stock) version DNSKEY=dnskeys:dynupdates fi rm /tmp/nsupdate.$$ # Need the new awk if [ "`uname -s`" = "SunOS" ] && [ -x $NEWAWK ] then AWK=$NEWAWK else AWK=awk fi # this is used to build dynamic variables selecteditems=1 exec 2>/tmp/errors # source the parse function . ./parse.sh reverseIP() { echo $1 |$AWK 'split($1,ip,".") {print ip[4] "." ip[3] "." ip[2] "." ip[1]}' } footer() { echo "" echo "" } displayzone() { if [ -z "$1" ] then echo "You didn't select a zone to view
" echo "Go back and select an zone first" footer exit 1 fi zone=$1 rrtype=$2 # print the top of the table cat < EOT nameserver=`dig +short "$zone" in soa | cut -d " " -f 1` dig @"$nameserver" "$zone" in axfr |egrep -v "^;|^$" | sort -u >/tmp/zone.$$ if [ -n "$rrtype" ] then cat /tmp/zone.$$ | $AWK -v rrtype=$rrtype ' {if ($4==rrtype) {print}}' >/tmp/zone2.$$ mv /tmp/zone2.$$ /tmp/zone.$$ fi cat /tmp/zone.$$ |while read rrname ttl class rrtype rrdata do echo $rrdata >/tmp/rrdata$selecteditems.$$ cat < EOT selecteditems=`expr $selecteditems + 1` done cat <
Select Domain Name TTL Type Data
$rrname $ttl $rrtype $rrdata

EOT rm /tmp/zone.$$ } echo "Content-type: text/html" echo "" echo "" echo "" #create all all the params as variables parse case "$action" in "View Zone") # query the zone and display it in a table [ "$rrtype" = "ALL" ] && rrtype="" displayzone $zone $rrtype ;; "Add This Record"|"Update This Record") #loop through all the records, adding them eval rrname=\$rrname$selecteditems eval rrtype=\$rrtype$selecteditems eval ttl=\$ttl$selecteditems eval class=\$class$selecteditems # AWB - because of the problems with data containing quotes # check to see if rdata was passed or not. if not, then a filename # was passed eval rrdata=\"\$rrdata$selecteditems\" if [ -z "$rrdata" ] then eval rrdatafile=\$rrdatafile$selecteditems rrdata=`cat $rrdatafile` fi # the file will exist whether its selected or not rm $rrdatafile 2>/dev/null eval pref=\$pref$selecteditems eval addptr=\$addptr$selecteditems eval existing=\"\$existing$selecteditems\" eval zone=\$zone$selecteditems # shit. its possible that the rrname is null # its not possible for rrtype to be null while [ -n "$rrtype" ] do #if there is an existing record, delete it if [ -n "$existing" ] then echo "update delete $existing" >/tmp/dnsdel.$$ echo "" >>/tmp/dnsdel.$$ nsupdate -k $DNSKEY /tmp/dnsdel.$$ rm /tmp/dnsdel.$$ fi #add the record if [ -z "$rrname" ] then rr="$zone $ttl $class $rrtype $pref $rrdata" else rr="$rrname.$zone $ttl $class $rrtype $pref $rrdata" fi echo "update add $rr" >/tmp/dnsadd.$$ echo "" >>/tmp/dnsadd.$$ nsupdate -k $DNSKEY /tmp/dnsadd.$$ rm /tmp/dnsadd.$$ # add the PTR if requested if [ "$addptr" = "True" ] then #if there is an existing record, delete it revip=`reverseIP $rrdata` if [ -n "$existing" ] then # its an edit, so the name will be fqdn oldrevip=`echo $existing |$AWK '{print $NF}'` oldrevip=`reverseIP $oldrevip`.in-addr.arpa. oldrrname=`echo $existing |$AWK '{print $1}'` rr="$oldrevip $class PTR $oldrrname" echo "update delete $rr" >/tmp/dnsadd.$$ echo "" >>/tmp/dnsadd.$$ nsupdate -k $DNSKEY /tmp/dnsadd.$$ rm /tmp/dnsadd.$$ fi echo "update add $revip.in-addr.arpa. $ttl $class PTR $rrname.$zone." >/tmp/dnsadd.$$ echo "" >>/tmp/dnsadd.$$ nsupdate -k $DNSKEY /tmp/dnsadd.$$ rm /tmp/dnsadd.$$ fi selecteditems=`expr $selecteditems + 1` eval rrname=\$rrname$selecteditems eval rrtype=\$rrtype$selecteditems eval ttl=\$ttl$selecteditems eval class=\$class$selecteditems eval rrdata=\"\$rrdata$selecteditems\" eval zone=\$zone$selecteditems if [ -z "$rrdata" ] then eval rrdatafile=\$rrdatafile$selecteditems rrdata=`cat $rrdatafile` fi # the file will exist regardless of whether its selected rm $rrdatafile 2>/dev/null eval pref=\$pref$selecteditems eval addptr=\$addptr$selecteditems eval existing=\"\$existing$selecteditems\" done echo "done!" echo '

Return to zone list' ;; "Add a Resource Record") if [ "$rrtype" = "ALL" ] then echo "You can't add an RR type of ALL
" echo "Go back and choose a valid RR type" footer exit 1 fi cat < EOT case $rrtype in A) echo '' ;; CNAME|PTR) echo '' ;; NS) echo '' ;; MX) echo '' echo '' ;; TXT) echo '' ;; esac cat <' ;; MX) echo '' echo '' ;; *) echo "WARNING: unhandled RR type $rrtype" footer exit 1 ;; esac cat <
Domain Name TTL Class TypeIP AddressCanonical NameName ServerPreferenceMail ServerCharacter String .$zone IN $rrtype EOT case $rrtype in A|CNAME|PTR|NS|TXT) echo '
EOT if [ "$rrtype" = "A" ] then echo '
' echo '' echo 'Select this box to create corresponding PTR Record as well' fi cat < EOT ;; "Edit Selected Resource Record") #loop though the rrs until the end (null) eval rrname=\$rrname$selecteditems while [ -n "$rrname" ] do eval selected=\$select$selecteditems if [ -n "$selected" ] then # found a selected rrname break fi selecteditems=`expr $selecteditems + 1` eval rrname=\$rrname$selecteditems done if [ -z "$selected" ] then echo "You didn't select an RR to edit
" echo "Go back and select an RR first" footer exit 1 fi eval ttl=\$ttl$selecteditems eval class=\$class$selecteditems eval rrtype=\$rrtype$selecteditems eval rrdata=\$rrdata$selecteditems if [ -z "$rrdata" ] then eval rrdatafile=\$rrdatafile$selecteditems rrdata=`cat $rrdatafile` fi # the file will exist rm $rrdatafile 2>/dev/null # if its an MX, then we need to get the $pref if [ "$rrtype" = "MX" ] then pref=`echo $rrdata|$AWK '{print $1}'` rrdata=`echo $rrdata|sed -e "s/^.* //"` fi # display a form # AWB - changed from double quotes to single quotes # Thu Sep 5 11:27:28 PDT 2002 cat < EOT case $rrtype in A) echo '' ;; CNAME|PTR) echo '' ;; NS) echo '' ;; MX) echo '' echo '' ;; TXT) echo '' ;; esac zone=`echo $rrname |sed -e "s/^[^.]*.//"` rrname=`echo $rrname|sed -e "s/.$zone$//"` cat < EOT case $rrtype in A|CNAME|PTR|NS|TXT) # AWB - changed from double to single quotes # Thu Sep 5 11:29:07 PDT 2002 cat < EOT ;; MX) cat < EOT ;; *) echo "WARNING: unhandled RR type $rrtype" footer exit 1 ;; esac cat <
Domain Name TTL Class TypeIP AddressCanonical NameName ServerPreferenceMail ServerCharacter String $zone IN $rrtype
EOT if [ "$rrtype" = "A" ] then cat < Select this box to edit the corresponding PTR Record too EOT fi cat < EOT ;; "Delete Selected Resource Records") #loop though the rrs until the end (null) eval rrname=\$rrname$selecteditems eval class=\$class$selecteditems eval rrtype=\$rrtype$selecteditems eval rrdata=\"\$rrdata$selecteditems\" if [ -z "$rrdata" ] then eval rrdatafile=\$rrdatafile$selecteditems rrdata=`cat $rrdatafile` fi # the file will exist whether its selected or not rm $rrdatafile 2>/dev/null eval selected=\$select$selecteditems while [ -n "$rrname" ] do if [ -n "$selected" ] then #echo select is $selected for item $rrname >>/tmp/foo # found a selected rrname found=true #delete the record #echo "update delete $rrname $class $rrtype $rrdata" >>/tmp/foo echo "update delete $rrname $class $rrtype $rrdata" \ >/tmp/dnsadd.$$ echo "" >>/tmp/dnsadd.$$ nsupdate -k $DNSKEY /tmp/dnsadd.$$ rm /tmp/dnsadd.$$ # if its an A RR, then delete the PTR too if [ "$rrtype" = "A" ] then revip=`reverseIP $rrdata` echo "update delete $revip.in-addr.arpa. $class PTR $rrname" >/tmp/dnsadd.$$ echo "" >>/tmp/dnsadd.$$ nsupdate -k $DNSKEY /tmp/dnsadd.$$ rm /tmp/dnsadd.$$ fi fi selecteditems=`expr $selecteditems + 1` eval rrname=\$rrname$selecteditems eval class=\$class$selecteditems eval rrtype=\$rrtype$selecteditems eval rrdata=\"\$rrdata$selecteditems\" if [ -z "$rrdata" ] then eval rrdatafile=\$rrdatafile$selecteditems rrdata=`cat $rrdatafile` fi # the file will exist whether its selected or not rm $rrdatafile 2>/dev/null eval selected=\$select$selecteditems done if [ -z "$found" ] then echo "You didn't select an RR to delete
" echo "Go back and select an RR first" footer exit 1 fi echo "done!" echo '

Return to zone list' ;; *) # build the zones html for i in $ZONES do zones="$zones

EOT ;; esac footer exit 0