update-zone
changeset 38 d50f6874b7ab
parent 37 d3158de72598
child 39 8b46e7c48995
child 43 7e472c559b36
child 45 5dc44dc86f61
equal deleted inserted replaced
37:d3158de72598 38:d50f6874b7ab
     1 #! /usr/bin/perl
       
     2 # (c) 1998 Heiko Schlittermann <heiko@datom.de>
       
     3 #
       
     4 # … work in progress do integrate dnssec (branch suess)
       
     5 #
       
     6 # Update the serial numbers in zone files
       
     7 # The serial number needs to match a specified pattern (see
       
     8 # the line marked w/ PATTERN.
       
     9 #
       
    10 # ToDo:
       
    11 # . test against an md5 sum, not just the date of the stamp file
       
    12 # . FIXME: handle `/' in file names (currently only working in
       
    13 #   the current directory)
       
    14 # . optionally reload the named
       
    15 
       
    16 use strict;
       
    17 use warnings;
       
    18 
       
    19 use File::Basename;
       
    20 use File::Copy;
       
    21 use FindBin;
       
    22 
       
    23 my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
       
    24 my @dnssec_killkeys
       
    25     = ( "$FindBin::Bin/dnssec-killkey", "/usr/bin/dnstools/dnssec-killkey" );
       
    26 my $dnssec_killkey;
       
    27 my @dnssec_creatkeys
       
    28     = ( "$FindBin::Bin/dnssec-creatkey", "/usr/bin/dnstools/dnssec-creatkey" );
       
    29 my $dnssec_creatkey;
       
    30 my @dnssec_signs
       
    31     = ( "$FindBin::Bin/dnssec-sign", "/usr/bin/dnstools/dnssec-sign" );
       
    32 my %config;
       
    33 my $dnssec_sign;
       
    34 my @change_names = ();
       
    35 
       
    36 foreach ( grep {-f} @configs ) {
       
    37     open( CONFIG, $_ ) or die "Can't open $_: $!\n";
       
    38 }
       
    39 
       
    40 unless ( seek( CONFIG, 0, 0 ) ) {
       
    41     die "Can't open config (searched: @configs)\n";
       
    42 }
       
    43 foreach ( grep {-f} @dnssec_killkeys ) {
       
    44     if ( -x $_ ) {
       
    45         $dnssec_killkey = $_;
       
    46     }
       
    47     else {
       
    48         die "Can't run $_\n";
       
    49     }
       
    50 }
       
    51 foreach ( grep {-f} @dnssec_creatkeys ) {
       
    52     if ( -x $_ ) {
       
    53         $dnssec_creatkey = $_;
       
    54     }
       
    55     else {
       
    56         die "Can't run $_\n";
       
    57     }
       
    58 }
       
    59 foreach ( grep {-f} @dnssec_signs ) {
       
    60     if ( -x $_ ) {
       
    61         $dnssec_sign = $_;
       
    62     }
       
    63     else {
       
    64         die "Can't run $_\n";
       
    65     }
       
    66 }
       
    67 
       
    68 while (<CONFIG>) {
       
    69     chomp;
       
    70     s/#.*//;
       
    71     s/\t//g;
       
    72     s/\s//g;
       
    73     next unless length;
       
    74     my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
       
    75     $config{$cname} = $ccont;
       
    76 }
       
    77 close(CONFIG);
       
    78 
       
    79 my $bind_dir   = $config{bind_dir};
       
    80 my $conf_dir   = $config{zone_conf_dir};
       
    81 my $master_dir = $config{master_dir};
       
    82 
       
    83 my $ME = basename $0;
       
    84 my @tmpfiles;
       
    85 my $verbose = 0;
       
    86 my $opt_yes = 0;
       
    87 my @Zones;
       
    88 my $file;
       
    89 
       
    90 
       
    91 sub cleanup() { unlink @tmpfiles; }
       
    92 END { cleanup(); }
       
    93 
       
    94 for (@ARGV) {
       
    95     if ( $_ eq "-y" ) {
       
    96         $opt_yes = 1;
       
    97         shift @ARGV;
       
    98     }
       
    99 }
       
   100 
       
   101 @Zones = @ARGV ? @ARGV : glob("$master_dir/*");
       
   102 
       
   103 MAIN: {
       
   104     my $changed = 0;
       
   105     my ( $dd, $mm, $yy ) = ( localtime() )[ 3 .. 5 ];
       
   106     my $date;
       
   107     $mm++;
       
   108 
       
   109     # prueft jede domain, die ein verzeichnis in $master_dir hat, ob sie
       
   110     # dnssec nutzt.
       
   111     # passt die eintraege in $config_file falls noetig an.
       
   112     while (<$master_dir/*>) {
       
   113         s#($master_dir/)(.*)#$2#;
       
   114         my $zone = $_;
       
   115 
       
   116         my $zone_file = "$master_dir/$zone/$zone";
       
   117         my $conf_file = "$conf_dir/$zone";
       
   118         my @c_content;
       
   119 
       
   120         unless ( -f "$conf_file" ) {
       
   121             die "$conf_file: $! \n";
       
   122         }
       
   123 
       
   124         if ( -e "$master_dir/$zone/.keycounter" ) {
       
   125 
       
   126             open( FILE, "<$conf_file" ) or die "$conf_file: $!\n";
       
   127             @c_content = <FILE>;
       
   128             close(FILE);
       
   129 
       
   130             for (@c_content) {
       
   131                 if (m{(.*)($zone_file)(";)}) {
       
   132                     print "$2 ==> $2.signed\n";
       
   133                     $_ = "$1$2.signed$3\n";
       
   134                 }
       
   135             }
       
   136 
       
   137             open( FILE, ">$conf_file" ) or die "$conf_file: $!\n";
       
   138             print FILE @c_content;
       
   139             close(FILE);
       
   140             
       
   141         }
       
   142         else {
       
   143 
       
   144             open( FILE, "<$conf_file" ) or die "$conf_file: $!\n";
       
   145             @c_content = <FILE>;
       
   146             close(FILE);
       
   147 
       
   148             for (@c_content) {
       
   149                 if (m{(.*)($zone_file)\.signed(.*)}) {
       
   150                     print "$2.signed ==> $2\n";
       
   151                     $_ = "$1$2$3\n";
       
   152                 }
       
   153             }
       
   154     
       
   155             open( FILE, ">$conf_file" ) or die "$conf_file: $!\n";
       
   156             print FILE @c_content;
       
   157             close(FILE);
       
   158         }
       
   159     }
       
   160 
       
   161     # erzeugt eine named.conf-datei aus den entsprechenden vorlagen.
       
   162     print "** creat named.conf.zones **\n";
       
   163     open( TO, ">$bind_dir/named.conf.zones" )
       
   164         or die "$bind_dir/named.conf.zones: $!\n";
       
   165     while (<$conf_dir/*>) {
       
   166         open( FROM, "$_" ) or die "$_: $! \n";
       
   167         print TO <FROM>;
       
   168         close(FROM);
       
   169     }
       
   170     close(TO);
       
   171 
       
   172     # aufruf von dnssec-killkey
       
   173     print "** execute dnssec-killkey for keyrollover **\n";
       
   174     system "$dnssec_killkey";
       
   175     die "$dnssec_killkey not found ($!)" if $? == -1;
       
   176     exit 1 if $?;
       
   177     
       
   178     # aufruf von dnssec-creatkey
       
   179     print "** execute dnssec-creatkey for keyrollover **\n";
       
   180     system "$dnssec_creatkey";
       
   181     die "$dnssec_creatkey not found ($!)" if $? == -1;
       
   182     exit 1 if $?;
       
   183 
       
   184     # aufruf von dnssec-sign
       
   185     print "** execute dnssec-sign for sign-update **\n";
       
   186     system "$dnssec_sign";
       
   187     die "$dnssec_sign not found ($!)" if $? == -1;
       
   188     exit 1 if $?;
       
   189 
       
   190     # update-serial
       
   191     print "** update serial **\n";
       
   192     foreach ( $dd, $mm ) { s/^\d$/0$&/; }
       
   193     $yy += 1900;
       
   194     $date = "$yy$mm$dd";
       
   195 
       
   196     while ( my $file = shift @Zones ) {
       
   197 
       
   198         my $file_basename = basename($file);
       
   199 
       
   200         $file =~ s#($master_dir)(/.*)#$1$2$2#;
       
   201         local ( *I, *O );
       
   202         my $done = 0;
       
   203 
       
   204         my $new   = "$file.$$.tmp";
       
   205         my $bak   = "$file.bak";
       
   206         my $stamp = $master_dir . "/.stamp/" . basename($file);
       
   207 
       
   208         $file =~ /(\.bak|~)$/ and next;
       
   209         $file !~ /\./ and next;
       
   210 
       
   211         $verbose && print "$file:";
       
   212 
       
   213         if ( -f $stamp && ( ( stat($stamp) )[9] >= ( stat($file) )[9] ) ) {
       
   214             $verbose && print " fresh, skipping.\n";
       
   215             next;
       
   216         }
       
   217 
       
   218         $done = 0;
       
   219         push @tmpfiles, $new;
       
   220         open( *I, "<$file" ) or die("Can't open < $file: $!\n");
       
   221         open( *O, ">$new" )  or die("Can't open > $new: $!\n");
       
   222 
       
   223         while (<I>) {
       
   224             /^\s+((\d+)(\d{2}))\s*;\s*serial/i and do {    # PATTERN
       
   225                 my ( $sdate, $scount, $serial ) = ( $2, $3, $1 );
       
   226                 $done = 1;
       
   227                 print " [$file] serial $sdate$scount";
       
   228 
       
   229                 if   ( $date eq $sdate ) { $scount++; }
       
   230                 else                     { $sdate = $date; $scount = "00"; }
       
   231 
       
   232                 print " bumping to $sdate$scount";
       
   233                 s/$serial/$sdate$scount/;
       
   234 
       
   235             };
       
   236             print O;
       
   237         }
       
   238 
       
   239         close(O);
       
   240         close(I);
       
   241 
       
   242         if ($done) {
       
   243 
       
   244             open( I, "<$new" )  or die("Can't open <$new: $!\n");
       
   245             open( O, ">$file" ) or die("Can't open >$file: $!\n");
       
   246             while (<I>) { print O or die("Can't write to $file: $!\n"); }
       
   247             close(I) or die("Can't close $new: $!\n");
       
   248             close(O) or die("Can't close $file: $!\n");
       
   249 
       
   250             unlink $new;
       
   251 
       
   252             open( O, ">$stamp" ) or die("Can't open >$stamp: $!\n");
       
   253             close(O);
       
   254             $changed++;
       
   255 
       
   256             push @change_names, $file_basename;
       
   257 
       
   258         }
       
   259         else {
       
   260             print " $file: no serial number found: no zone file?";
       
   261         }
       
   262         print "\n";
       
   263     }
       
   264 
       
   265     my $pidfile;
       
   266 
       
   267     unless ($changed == 0) {
       
   268         print "Changed $changed files.\n";
       
   269     }
       
   270 
       
   271     foreach (
       
   272         qw(/var/run/bind/run/named.pid /var/run/named.pid /etc/named.pid))
       
   273     {
       
   274         -f $_ and $pidfile = $_ and last;
       
   275     }
       
   276 
       
   277     # dnssec-sign aufruf fuer geanderten domains
       
   278     print "** execute dnssec-sign **\n";
       
   279     system "$dnssec_sign @change_names";
       
   280     die "$dnssec_sign not found ($!)" if $? == -1;
       
   281     exit 1 if $?;
       
   282 
       
   283     if ($pidfile) {
       
   284         if ($opt_yes) {
       
   285             $_ = "y";
       
   286             print "** Nameserver will be reloaded\n";
       
   287         }
       
   288         else { print "** Reload now? [Y/n]: "; $_ = <STDIN>; }
       
   289         /^y|^$/i and system "rndc reload";
       
   290     }
       
   291     else {
       
   292         print
       
   293             "** No PID of a running named found.  Please reload manually.\n";
       
   294 
       
   295     }
       
   296 
       
   297 }
       
   298