X-Git-Url: https://the.earth.li/gitweb/?a=blobdiff_plain;f=autodns.pl;h=edaf5fbd62feb5a5c5079fe9eeb302c84bb3e54d;hb=aa0756276993cffe800205a321baa6b145082a8a;hp=d017e600f23695d0a3af9209e015939632dbf2dd;hpb=8ecbe90f448e63afd96cd1654bf5a5ba84e1f805;p=autodns.git diff --git a/autodns.pl b/autodns.pl index d017e60..edaf5fb 100755 --- a/autodns.pl +++ b/autodns.pl @@ -5,11 +5,13 @@ # http://www.earth.li/projectpurple/progs/autodns.html # Released under the GPL. # -# $Id: autodns.pl,v 1.13 2005/05/31 17:17:46 noodles Exp $ +# $Id: autodns.pl,v 1.15 2005/06/15 10:26:25 noodles Exp $ # use strict; +use Date::Parse; use Fcntl qw(:flock); +use File::Path; use File::Temp qw(tempfile); use IPC::Open3; use MIME::Parser; @@ -21,7 +23,7 @@ my ($user, $server, $inprocess, $delcount, $addcount); my ($domain, @MAIL, @GPGERROR, @COMMANDS, %zones, $VERSION); use vars qw($me $ccreply $conffile $domainlistroot @cfgfiles $usersfile - $lockfile $reload_command); + $lockfile $reload_command $expiry $zonefiledir); $VERSION="0.0.8"; @@ -73,7 +75,7 @@ sub valid_domain($) { my $domain = shift; $domain = lc $domain; - if ($domain =~ /^(?:[a-z0-9-]+\.)+[a-z]{2,4}$/) { + if ($domain =~ /^(?:[a-z0-9-]+\.)+[a-z]{2,6}$/) { return 1; } elsif ($domain =~ /^(?:[0-9\/-]+\.)+in-addr.arpa$/) { return 1; @@ -107,7 +109,7 @@ sub fatalerror($) { # # A users entry looks like: # -# ::: +# ::: # # Priviledge level is not currently used. # @@ -115,7 +117,7 @@ sub fatalerror($) { # sub getuserinfo($) { my $gpguser = shift; - my ($user, $priviledge, $server); + my ($user, $privilege, $server); open (CONFIGFILE, "< $usersfile") or fatalerror("Couldn't open user configuration file."); @@ -123,10 +125,10 @@ sub getuserinfo($) { foreach () { if (/^([^#.]+):$gpguser:(\d+):(.+)$/) { $user=$1; - $priviledge=$2; + $privilege=$2; $server=$3; chomp $user; - chomp $priviledge; + chomp $privilege; chomp $server; if ($user !~ /^.+$/) { @@ -148,7 +150,36 @@ sub getuserinfo($) { fatalerror("User not found.\n"); } - return ($user, $priviledge, $server); + return ($user, $privilege, $server); +} + +# +# Add a new AutoDNS user. +# +# addautodnsuser($username, $keyid, $priv, $masterip); +# ::: +# +sub addautodnsuser($$$$) { + my $username = shift; + my $keyid = shift; + my $priv = shift; + my $masterip = shift; + + # Create domains file for the user. + open (DOMAINLIST, ">>$domainlistroot$username") or + fatalerror("Couldn't create domains file.\n"); + close DOMAINLIST; + + # Make the directory for the zone files. + my @dirs = mkpath("$zonefiledir/$username", 0, 0775); + fatalerror("Couldn't create zone file directory.\n") + if scalar(@dirs) == 0; + + # Actually add them to the users file. + open(USERFILE, ">> $usersfile") or + fatalerror("Couldn't open user configuration file."); + print USERFILE "$username:$keyid:$priv:$masterip\n"; + close(USERFILE); } $delcount=$addcount=$inprocess=0; @@ -229,6 +260,23 @@ if ($entity->parts) { print $sig_fh $subent->as_string; close($sig_fh); $got_sig++; + } elsif ($subent->effective_type eq "multipart/mixed") { + my $str = $subent->as_string; + print $text_fh $str; + close($text_fh); + $got_text++; + + foreach my $mixent ($subent->parts) { + if ($mixent->effective_type eq "text/plain") { + push @COMMANDS, (split /\n/, + $mixent->bodyhandle->as_string); + } + if ($mixent->effective_type eq + "application/pgp-keys") { + push @COMMANDS, (split /\n/, + $mixent->bodyhandle->as_string); + } + } } } @@ -251,7 +299,7 @@ if ($entity->parts) { } else { # Clear text. - my $pid = open3(\*GPGIN, \*GPGOUT, \*GPGERR, "gpg --batch"); + my $pid = open3(\*GPGIN, \*GPGOUT, \*GPGERR, "gpg --batch --verify"); # Feed it the mail. print GPGIN $entity->bodyhandle->as_string; @@ -260,6 +308,7 @@ if ($entity->parts) { # And grab what it has to say. @GPGERROR=; @COMMANDS=; + @COMMANDS = split /\n/,$entity->bodyhandle->as_string; close GPGERR; close GPGOUT; waitpid $pid, 0; @@ -267,10 +316,12 @@ if ($entity->parts) { # Check who it's from and if the signature was a good one. $gpggood=1; +my $sigtime = 0; foreach (@GPGERROR) { chomp; - if (/Signature made.* (.*)$/) { - $gpguser=$1; + if (/Signature made (.*) using.*ID (.*)$/) { + $sigtime = str2time($1); + $gpguser=$2; } elsif (/error/) { $gpggood = 0; print REPLY "Some errors ocurred\n"; @@ -299,6 +350,21 @@ if ($gpggood) { exit; } +# Check if the signature is outside our acceptable range. +if (!defined($sigtime)) { + print REPLY "Couldn't parse signature time.\n"; + close REPLY; + exit; +} elsif ($sigtime > (time + $expiry)) { + print REPLY "Signature too far into the future.\n"; + close REPLY; + exit; +} elsif ($sigtime < (time - $expiry)) { + print REPLY "Signature too far into the past.\n"; + close REPLY; + exit; +} + # Now let's check if we know this person. ($user, $priv, $server) = getuserinfo($gpguser); @@ -470,6 +536,35 @@ zone \"$domain\" { print REPLY "$1 doesn't look like a valid IPv4 ", "address to me.\n"; } + } elsif ($inprocess && /^ADDUSER\s(.*)$/) { + if (($priv & 2) != 2) { + print REPLY "You're not authorised to use the ", + "ADDUSER command.\n"; + } elsif ($1 =~ /^([a-z0-9]+) ([A-Fa-f0-9]{8}) (\d+) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) { + addautodnsuser($1, $2, $3, $4); + + print REPLY "Attempting to import new key:\n"; + + # Feed our command mail to GPG so we can pull the + # (hopefully included) new GPG key out from it. + my $pid = open3(\*GPGIN, \*GPGOUT, \*GPGERR, + "gpg --batch --import"); + + # Feed it the mail. + print GPGIN join("\n", @COMMANDS); + close GPGIN; + + # And grab what it has to say. + @GPGERROR=; + my @GPGOUTPUT=; + close GPGERR; + close GPGOUT; + waitpid $pid, 0; + + print REPLY @GPGERROR; + } else { + print REPLY "ADDUSER parameter error.\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"; @@ -483,6 +578,15 @@ zone \"$domain\" { 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"; + if (($priv & 1) == 1) { + print REPLY "MASTER - set the nameserver". + " we should slave off for subsequent ADD\ncommands.\n"; + } + if (($priv & 2) == 2) { + print REPLY "ADDUSER ", + " - add a new user. Imports any key", + "\nattached to the message into the keyring.\n"; + } } elsif ($inprocess) { print REPLY "Unknown command!\n"; }