From: Jonathan McDowell Date: Wed, 15 Jun 2005 10:41:41 +0000 (+0000) Subject: cscvs to tla changeset 1 X-Git-Url: http://the.earth.li/gitweb/?a=commitdiff_plain;h=69f62eb3272157eca2f045f051c44a95efca1279;p=autodns.git cscvs to tla changeset 1 Author: noodles Date: 2003/06/04 17:21:57 Initial revision git-archimport-id: noodles@earth.li--pie/autodns--mainline--1.0--base-0 --- 69f62eb3272157eca2f045f051c44a95efca1279 diff --git a/ACKNOWLEDGEMENTS b/ACKNOWLEDGEMENTS new file mode 100644 index 0000000..022deb2 --- /dev/null +++ b/ACKNOWLEDGEMENTS @@ -0,0 +1,28 @@ +Stephen White + +Provided much testing and suggestions for improvement. + + +Simon Huggins + +Answered annoying Perl questions when I was too lazy to RTFM. Fixed +various bugs (including locale stuff, deletion of domains, stricter +checking of domain validity). + + +Peter Warasin + +Provided patches to improve functionality (users file, better GPG error +checking etc). + + +Matthew Byng-Maddick + +Provided patches to improve functionality (locking, help, tidier command +processing). + + +Dominic Hargreaves + +Provided add-dns.pl, the beginning (and possibly end) of the contrib +directory. diff --git a/HISTORY b/HISTORY new file mode 100644 index 0000000..f847116 --- /dev/null +++ b/HISTORY @@ -0,0 +1,35 @@ +0.0.1 - 11th December 1999 + +* First release. + +0.0.2 - 22nd December 1999 + +* Added check to make sure there are no illegal characters in the + domain name we are adding. +* Added checking of existing zones so that it's not possible to add the + same zone twice. + +0.0.3 - 17th February 2000 + +* Added check for mail from mailer-daemon, so we don't try to parse + bounces. +* Fixed to work with use strict. +* Wrote a README. +* Forced domains into all lower case. + +0.0.4 - 12th July 2001 + +* Fixed stupid bug that meant we could add zones that already existed. +* Added HELP command. +* Added DEL command. +* Added better checking of domain syntax. +* Fixed gpg locale error (we assumed English messages for parsing). +* Added user configuration file. +* Added locking. +* Don't reply to the same address twice (cc & to). +* Better GPG error checking. +* Added contrib directory (currently with just add-dns.pl in it) + +0.0.5 - 10th November 2002 + +* Changed valid domain regex to allow 4 character TLDs (triggered by .info). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b2852a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,280 @@ +GNU GENERAL PUBLIC LICENSE + + Version 2, June 1991 +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + + The licenses for most software are designed to take away your freedom + to share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Library General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if + you distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, + we want its recipients to know that what they have is not the + original, so that any problems introduced by others will not reflect + on the original authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at + all. + + The precise terms and conditions for copying, distribution and + modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the Program + (independent of having been made by running the Program). Whether that + is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the + Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a + fee. + + 2. You may modify your copy or copies of the Program or any portion of + it, thus forming a work based on the Program, and copy and distribute + such modifications or work under the terms of Section 1 above, + provided that you also meet all of these conditions: + + * a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + * b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + * c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the + Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote + it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + * a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange; or, + * b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + * c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt otherwise + to copy, modify, sublicense or distribute the Program is void, and + will automatically terminate your rights under this License. However, + parties who have received copies, or rights, from you under this + License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and + "any later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Program does not specify a + version number of this License, you may choose any version ever + published by the Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE + PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU + FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE + PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING + RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A + FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF + SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..e87cba5 --- /dev/null +++ b/README @@ -0,0 +1,78 @@ +autodns 0.0.4 - A program to aid auto addition of secondary DNS. +Copyright 1999-2001 Jonathan McDowell for Project Purple. +http://www.earth.li/projectpurple/progs/autodns.html + + +Introduction: + +AutoDNS is a simple Perl script designed to allow the easy addition of +secondary DNS zones controlled via email. + +The principle is simple. AutoDNS accepts a GPG clear signed email on +stdin, so can simply be added to a .forward file or whatever. You +configure it to know about the key IDs of all the people you wish to be +able to setup secondaries on your server and add their keys to the GPG +keyring for the user it runs under. + +Most of the configuration options are at the top of autodns.pl, just +after where VERSION is defined. The other bit of config that's needed is +a users file. + +You'll also need a way for the script to be able to do a "ndc reconfig" +to load the info about the new secondary domains - I do this using sudo. + +The format of commands to AutoDNS is very simple. It current accepts 5 +commands: + +BEGIN + Indicate the beginning of a block of commands. +END + Indicate the end of a block of commands. +ADD + Add to the list of secondaried domains. +DEL + Delete from the list of secondaried domains, assuming + it's owned by the current user and is being secondaried + currently. +LIST + List secondaried domains. +HELP + Show basic help. + +So a typical email would contain: + +BEGIN +ADD foo.bar +END + +as the body, which would then be signed with gpg --clearsign and sent. +AutoDNS will reply with the results of the commands sent to it. + + +Users file + +The users file is of a very simple format. It contains one user per +line like so: + +::: + +So an example would be: + +noodles:5B430367:0:212.135.138.190 + +Lines beginning with a '#' are treated as comments. See autodns.users in +the tarball for an example. + + +Contacting the author: + +I can be reached as noodles@earth.li or on Fidonet as Jonathan McDowell +@ 2:443/21 + +All constructive criticism about autodns is welcome. + + +License: + +autodns is distributed under the GNU Public License, a copy of which +should have been provided with this archive as LICENSE. diff --git a/TODO b/TODO new file mode 100644 index 0000000..65cae4a --- /dev/null +++ b/TODO @@ -0,0 +1,16 @@ +* MIME PGP support (so it'll work nicely with mutt). + +* man page. + +* Check nameserver is alive afterwards. + +* Different priviledge levels (users allowed to change master server IP, + allowed to list/delete any domain etc) + +* Restructure to be more modular and cleaner code. + +* Configuration file. + +* Web interface? + +* More (better) documentation? diff --git a/autodns.pl b/autodns.pl new file mode 100755 index 0000000..9a739d0 --- /dev/null +++ b/autodns.pl @@ -0,0 +1,438 @@ +#!/usr/bin/perl -Tw +# autodns 0.0.5 +# Copyright 1999-2001 Project Purple. Written by Jonathan McDowell +# See ACKNOWLEDGEMENTS file for full details of contributors. +# http://www.earth.li/projectpurple/progs/autodns.html +# Released under the GPL. + +use strict; +use IPC::Open3; +use Fcntl qw(:flock); + +$ENV{'PATH'}="/usr/local/bin:/usr/bin:/bin:/usr/sbin"; + +my ($from, $subject, $gpguser, $gpggood, $usersfile, $lockfile, $priv); +my ($user, $server, $inprocess, $delcount, $addcount, $reload_command); +my ($domain, @MAIL, @GPGERROR, @COMMANDS, %zones); +my ($me, $ccreply, $conffile, $domainlistroot, @cfgfiles, $VERSION); + +$VERSION="0.0.5"; + +# +# Local configuration here (until it gets moved to a config file). +# +# These are sort of suitable for a Debian setup. +# + +# Who I should reply as. +$me="autodns\@earth.li"; + +# Who replies should be CCed to. +$ccreply="noodles\@earth.li"; + +# Where to look for zones we're already hosting. +@cfgfiles=("/etc/bind/named.conf", + "/etc/bind/named.secondary.conf"); + +# The file we should add/delete domains from. +$conffile="/etc/bind/named.secondary.conf"; + +# The file that contains details of the authorized users. +$usersfile="/etc/bind/autodns.users"; + +# Base file name to for list of users domains. +$domainlistroot="/etc/bind/domains."; + +# The lockfile we use to ensure we have exclusive access to the +# $domainlistroot$user files and $conffile. +$lockfile="/etc/bind/autodns.lck"; + +# The command to reload the nameserver domains list. +$reload_command="sudo ndc reconfig 2>&1"; + +### +### There should be no need to edit anything below (unless you're not +### using BIND). This statement might even be true now - let me know if not. +### + +# +# Try to figure out what zones we currently know about by parsing config +# files. Sets the item in %zones to 1 for each zone it finds. +# +# Call with the name of a config file to read: +# +# &getzones("/etc/named.conf"); +# +sub getzones { + my ($namedfile) = @_; + + open (NAMEDCONF, "< $namedfile") or + &fatalerror("Can't open $namedfile"); + + while () { + if (/^\s*zone\s*"([^"]+)"/) { + $zones{$1}=1; + } + } + + close NAMEDCONF; +} + +# +# Check that a domain is only made up of valid characters. +# +# These are: a-z, 0-9, - or . +# +sub valid_domain { + my $domain = shift; + $domain = lc $domain; + if ($domain =~ /^(?:[a-z0-9-]+\.)+[a-z]{2,4}$/) { + return 1; + } else { + return 0; + } +} + +# +# Deal with a fatal error by printing an error message, closing the pipe to +# sendmail and exiting. +# +# fatalerror("I'm melting!"); +# +sub fatalerror { + my $message = shift; + + print REPLY $message; + close(REPLY); + + flock(LOCKFILE, LOCK_UN); + close(LOCKFILE); + unlink($lockfile); + +# die $message; + exit; +} + +# +# Get user details from usersfile based on a PGP ID. +# +# A users entry looks like: +# +# ::: +# +# Priviledge level is not currently used. +# +# ($user, $priv, $server) = &getuserinfo("5B430367"); +# +sub getuserinfo { + my $gpguser = shift; + my ($user, $priviledge, $server); + + open (CONFIGFILE, "< $usersfile") or + &fatalerror("Couldn't open user configuration file."); + + foreach () { + if (/^([^#.]+):$gpguser:(\d+):(.+)$/) { + $user=$1; + $priviledge=$2; + $server=$3; + chomp $user; + chomp $priviledge; + chomp $server; + + if ($user !~ /^.+$/) { + close(CONFIGFILE); + &fatalerror("Error in user configuration file: Can't get username.\n"); + } + + if ($server !~ /^(\d{1,3}\.){3}\d{1,3}$/) { + $server =~ s/\d\.]//g; + close(CONFIGFILE); + &fatalerror("Error in user configuration file: Invalid primary server IP address ($server)\n"); + exit; + } + } + } + close(CONFIGFILE); + + if ($user =~ /^$/) { + &fatalerror("User not found.\n"); + } + + return ($user, $priviledge, $server); +} + +$delcount=$addcount=$inprocess=0; + +# Read in the mail from stdin. +@MAIL=<>; + +$subject = "Reply from AutoDNS"; +# Now lets try to find out who it's from. +foreach (@MAIL) { + if (/^$/) { last; } + if (/^From: (.*)/i) { $from=$1; chomp $from;} + if (/^Subject:\s+(re:)?(.*)$/i) { $subject="Re: ".$2 if ($2);} +} + +if ((! defined($from)) || $from =~ /^$/ ) { + die "Couldn't find a from address."; +} elsif ($from =~ /mailer-daemon@/i) { + die "From address is mailer-daemon, ignoring."; +} + +if (! defined($subject)) { $subject="Reply from AutoDNS"; }; + +# We've got a from address. Start a reply. + +open(REPLY, "|sendmail -t -oem -oi") or die "Couldn't spawn sendmail"; + +print REPLY "From: $me\n"; +print REPLY "To: $from\n"; +# +# Check to see if our CC address is the same as the from address and if so +# don't CC. +# +if ($from ne $ccreply) { + print REPLY "Cc: $ccreply\n"; +} +print REPLY <; +@COMMANDS=; +close GPGERR; +close GPGOUT; + +# Check who it's from and if the signature was a good one. +$gpggood=1; +foreach (@GPGERROR) { + chomp; + if (/Signature made.* (.*)$/) { + $gpguser=$1; + } elsif (/error/) { + $gpggood = 0; + print REPLY "Some errors ocurred\n"; + } elsif (/BAD signature/) { + $gpggood = 0; + print REPLY "BAD signature!\n"; + } elsif (/public key not found/) { + $gpggood = 0; + print REPLY "Public Key not found\n"; + } +} + +# If we have an empty user it probably wasn't signed. +if (! $gpguser) { + print REPLY "Message appears not to be GPG signed.\n"; + close REPLY; + exit; +} + +# Check the signature we got was ok. +if ($gpggood) { + print REPLY "Good GPG signature found. ($gpguser)\n"; +} else { + print REPLY "Bad GPG signature!\n"; + close REPLY; + exit; +} + +# Now let's check if we know this person. +($user, $priv, $server) = &getuserinfo($gpguser); + +if (! defined($user) || ! $user) { + print REPLY "Unknown user.\n"; + close REPLY; + exit; +} + +print REPLY "Got user '$user'\n"; + +# Right. We know this is a valid user. Get a lock to ensure we have exclusive +# access to the configs from here on in. +open (LOCKFILE,">$lockfile") || + &fatalerror("Couldn't open lock file\n"); +&fatalerror("Couldn't get lock\n") unless(flock(LOCKFILE,LOCK_EX)); + +# Ok, now we should figure out what domains we already know about. +foreach my $cfgfile (@cfgfiles) { + getzones($cfgfile); +} + +foreach (@COMMANDS) { + # Remove trailing CRs and leading/trailing whitespace + chomp; + s/\r//; + s/^\s*//; + s/\s*$//; + + if ($inprocess) { + print REPLY ">>>$_\n"; + } + + if (/^$/) { + # + # Empty line, so ignore it. + # + } elsif (/^END$/) { + $inprocess=0; + } elsif (/^BEGIN$/) { + $inprocess=1; + } elsif ($inprocess && /^ADD\s+(.*)$/) { + $domain = $1; + + # Convert domain to lower case. + $domain =~ tr/[A-Z]/[a-z]/; + if (! valid_domain($domain)) { + $domain =~ s/[-a-z0-9.]//g; + print REPLY "Invalid character(s) in domain name: $domain\n"; + } elsif (defined($zones{$domain}) && $zones{$domain}) { + print REPLY "We already secondary $domain\n"; + } else { + print REPLY "Adding domain $domain\n"; + $zones{$domain}=1; + + open (DOMAINSFILE, ">>$conffile"); + print DOMAINSFILE " +### Domain added for '$user' + +zone \"$domain\" { + type slave; + masters { $server; }; + file \"secondary/$user/$domain\"; + allow-transfer { none; }; + allow-query { any; }; +};\n"; + close DOMAINSFILE; + + open (DOMAINLIST, ">>$domainlistroot$user") or + &fatalerror("Couldn't open file.\n"); + print DOMAINLIST "$domain\n"; + close DOMAINLIST; + $addcount++; + } + } elsif ($inprocess && /^DEL\s(.*)$/) { + $domain = $1; + + # Convert domain to lower case. + $domain =~ tr/[A-Z]/[a-z]/; + if (!valid_domain($domain)) { + $domain =~ s/[-a-z0-9.]//g; + print REPLY "Invalid character(s) in domain name: $domain\n"; + } elsif (!defined($zones{$domain}) || !$zones{$domain}) { + print REPLY "$domain does not exist!\n"; + } else { + print REPLY "Deleting domain $domain\n"; + my (@newcfg,$found); + + open (DOMAINLIST, "<$domainlistroot$user") or + &fatalerror("Couldn't open file $domainlistroot$user for reading: $!.\n"); + my @cfg = ; + close(DOMAINLIST); + @newcfg = grep { ! /^$domain$/ } @cfg; + if (scalar @cfg == scalar @newcfg) { + print REPLY "Didn't find $domain in $domainlistroot$user!\n"; + print REPLY "You are only allowed to delete your own domains that exist.\n"; + next; + } + + open (DOMAINLIST, ">$domainlistroot$user") or + &fatalerror("Couldn't open file $domainlistroot$user for writing: $!.\n"); + print DOMAINLIST @newcfg; + close DOMAINLIST; + + $found=0; + @newcfg=(); + open (DOMAINSFILE, "<$conffile") or + &fatalerror("Couldn't open file $conffile for reading: $!\n"); + { + local $/ = ''; # eat whole paragraphs + while () { + unless (/^\s*zone\s+"$domain"/) { + push @newcfg, $_; + } else { + $found=1; + if ($newcfg[-1] =~ /^###/) { + # remove comment and \n + pop @newcfg; + } + } + } + } # end of paragraph eating + + if (!$found) { + print REPLY "Didn't find $domain in $conffile!\n"; + next; + } + + open (DOMAINSFILE, ">$conffile") or + &fatalerror("Couldn't open $conffile for writing: $!\n"); + print DOMAINSFILE @newcfg; + close DOMAINSFILE; + $delcount++; + $zones{$domain} = 0; + } + } elsif ($inprocess && /^LIST$/) { + print REPLY "Listing domains for user $user\n"; + print REPLY "------\n"; + if (open (DOMAINLIST, "<$domainlistroot$user")) { + my $count = 0; + while () { + $count++; + print REPLY; + } + close (DOMAINLIST); + print REPLY "------\n"; + print REPLY "Total of $count domains.\n"; + } else { + print REPLY "Couldn't open $domainlistroot$user: $!\n"; + } + } elsif ($inprocess && /^HELP$/) { + print REPLY "In order to use the service, you will need to send GPG signed\n"; + print REPLY "messages.\n\n"; + print REPLY "The format of the text in these messages is important, as they represent\n"; + print REPLY "commands to autodns. Commands are formatted one per line, and enclosed\n"; + print REPLY "by \"BEGIN\" and \"END\" commands (without the quotes).\n"; + print REPLY "Current valid commands are:\n"; + print REPLY "BEGIN - begin processing.\n"; + print REPLY "END - end processing.\n"; + print REPLY "HELP - display this message.\n"; + print REPLY "LIST - show all the zones currently held by you.\n"; + print REPLY "ADD - adds the domain for processing.\n"; + print REPLY "DEL - removes the domain if you own it.\n"; + } elsif ($inprocess) { + print REPLY "Unknown command!\n"; + } +} +flock(LOCKFILE, LOCK_UN); +close(LOCKFILE); +unlink($lockfile); + +print REPLY "Added $addcount domains.\n" if $addcount; +print REPLY "Removed $delcount domains.\n" if $delcount; +if ($addcount || $delcount) { + print REPLY "Reloading nameserver config.\n"; + print REPLY `$reload_command`; +} +close REPLY; + +exit 0; diff --git a/autodns.users b/autodns.users new file mode 100644 index 0000000..56a6979 --- /dev/null +++ b/autodns.users @@ -0,0 +1,3 @@ +# ::: +noodles:5B430367:0:212.135.138.190 +testuser:12345678:0:0.0.0.0 diff --git a/contrib/add-dns.pl b/contrib/add-dns.pl new file mode 100644 index 0000000..53a0e3a --- /dev/null +++ b/contrib/add-dns.pl @@ -0,0 +1,148 @@ +#!/usr/bin/perl -w +# +# add-dns.pl version 0.0.4alpha +# Dominic Hargreaves +# +# Use this to tell nameservers supporting AutoDNS +# (http://www.earth.li/projectpurple/progs/autodns.html) to slave for you. +# +# Changelog: +# +# 03/07/01 dom: Added remotehelp and remove command for AutoDNS 0.0.4alpha +# Changed to header to ns1 (from terry) +# 22/05/01 dom: Initial code completed for AutoDNS 0.0.3 + +use strict; +use IPC::Open3; + +sub usage; + +my $sendmail = "/usr/sbin/sendmail"; +my $gpg = "/usr/bin/gpg"; + +my $to = 'dns-auto@tuschin.blackcatnetworks.co.uk, + dns-auto@ns1.blackcatnetworks.co.uk'; +#my $to = 'dom'; +my $from = 'Urchin Hostmaster '; +my $cc = $from; +#my $cc = ""; +my $keyid = "25B2616D"; +my $command; +my @validcommands = qw(add remove list remotehelp); + +# Only proceed if we have been given a valid command + +die usage unless $ARGV[0]; + +my $ok = 0; +for (@validcommands) { + if ($ARGV[0] eq $_) { + $ok = 1; + } +} + +die usage unless ($ok == 1); + +# Open gpg filehandle + +open3(\*GPGIN, \*GPGOUT, \*GPGERR, "$gpg --default-key $keyid --clearsign"); + +# Generate AutoDNS commands + +print GPGIN "BEGIN\n"; + +$command = shift(@ARGV); + +if ($command eq "list") { + print GPGIN "LIST\n"; +} elsif ($command eq "remotehelp") { + print GPGIN "HELP\n"; +} elsif ($command eq "add") { + for (@ARGV) { + print GPGIN "ADD $_\n"; + } +} elsif ($command eq "remove") { + for (@ARGV) { + print GPGIN "DEL $_\n"; + } +} else { + die usage; +} + +print GPGIN "END\n"; + +close GPGIN; + +my @gpgerror=; +my @gpgout=; +close GPGERR; +close GPGOUT; + +# Show user any error output from gpg... + +for (@gpgerror) { + print STDERR $_; +} + +# ...and what we intend to send + +for (@gpgout) { + print $_; +} + +# Ask user whether this is ok + +print "Send this mail to:\n"; +print $to; +print "\nand\n"; +print $cc; +print "\n? (y/n): "; + +my $mark = "0"; +while () { + if (/^y/i) { + $mark = "1"; + last; + } + /^n/i and last; +} + +if (!($mark eq "1")) { + print "Mail NOT sent.\n"; + exit 1; +} + +# Compose email + +open MAIL, "|$sendmail -t -oi" or die $!; +print MAIL "From: $from\n" or die "Configuration error: $!"; +print MAIL "To: $to\n" or die "Configuration error: $!"; +print MAIL "Cc: $cc\n" if $cc; +print MAIL "Subject: AutoDNS commands\n"; +print MAIL "X-Mailer: add-dns.pl 0.0.4alpha\n\n"; + +for (@gpgout) { + print MAIL $_; +} + +print MAIL "\n"; + +# Send email + +close MAIL; + +sub usage { + print< [list of domains] + +Possible commands: add: Adds domains + remove: Removes domains + list: Lists current domains + remotehelp: Requests help from remote end + +(You must have the private key $keyid in your gpg keyring +for this to work) +EOF + +} +