2005-12-02 04:09:15 +00:00
#!/usr/bin/perl
# Script to import data from DNS into LDAP
# Copyright 2000, Jacob Rief
# $Id: import.pl,v 1.24 2000/12/14 12:44:29 jrief Exp $
###### configure this ######
# remember to allow zone transfers from Your nameserver
$ LDAPHOST = "ldap.myorg.com" ;
$ LDAPBINDDN = "ou=dns,o=myorg" ;
$ LDAPPASSWD = "secret" ;
$ NAMESERVER = "ns1.myorg.com" ;
$ BASEDN = "ou=dns,o=myorg" ;
$ FULL_QUALIFIED_NAME = 0 ;
###### don't edit below this line ######
use Net::DNS ;
use Net::LDAP ;
$ ldap = Net::LDAP - > new ( $ LDAPHOST ) or die "Can't connect to LDAP server" ;
$ mesg = $ ldap - > bind ( dn = > $ LDAPBINDDN , password = > $ LDAPPASSWD ) ;
die "Unable to bind to LDAP " , $ mesg - > error if ( $ mesg - > code ) ;
@ domains ;
while ( < > ) {
chomp ;
$ _ = lc ;
if ( /primary\s+([0-9A-Za-z._+-]+)\s+/ ) {
push ( @ domains , $ 1 ) ;
}
}
if ( $# domains >= 0 ) {
@ domains = sort ( @ domains ) ;
for ( $ i = 1 ; $ i <= $# domains ; $ i + + ) {
if ( $ domains [ $ i - 1 ] eq $ domains [ $ i ] ) {
print "Warning: removing double entry for zone: $domains[$i]\n" ;
splice ( @ domains , $ i , 1 ) ;
}
}
print "Adding " . ( $# domains + 1 ) . " zones to LDAP server\n" ;
foreach ( @ domains ) {
read_zone ( $ _ ) ;
}
} else {
print "No domain added to LDAP server\n" ;
}
sub add_attrs
{
my ( $ attr , $ zonename ) = @ _ ;
# correct DNScname
if ( defined $$ attr { 'DNScname' } ) {
# check if DNScname is a real name
if ( $$ attr { 'DNScname' } =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
$$ attr { 'DNSipaddr' } = "$1.$2.$3.$4" ;
undef $$ attr { 'DNScname' } ;
}
}
my ( $ tail ) ;
if ( $$ attr { 'DNSdomainname' } eq $ zonename ) {
$ tail = "" ;
} else {
split /\.$zonename/ , $$ attr { 'DNSdomainname' } ;
die "Corrupt DNSdomainname" unless ( defined @ _ [ 0 ] ) ;
$ tail = @ _ [ 0 ] ;
}
if ( $ FULL_QUALIFIED_NAME ) {
$$ attr { 'DNSdomainname' } = "$zonename." if ( $ tail eq "" ) ;
$$ attr { 'DNSdomainname' } = "$tail.$zonename." unless ( $ tail eq "" ) ;
$$ attr { 'DNScname' } . = "." if ( defined $$ attr { 'DNScname' } ) ;
} else {
$$ attr { 'DNSdomainname' } = "$tail" ;
if ( defined $$ attr { 'DNScname' } ) {
split /\.$zonename/ , $$ attr { 'DNScname' } ;
$$ attr { 'DNScname' } = @ _ [ 0 ] if ( defined @ _ [ 0 ] ) ;
}
}
my $ rrdn ;
if ( $$ attr { 'DNStype' } eq "A" ) {
# A records are multivalued, use one rrset for all ipaddresses
$$ attr { 'cn' } = "A:$tail" ;
$ rrdn = "cn=$$attr{'cn'},cn=$zonename,$BASEDN" ;
$ mesg = $ ldap - > search ( base = > $ rrdn , scope = > "base" , filter = > "(objectclass=DNSrrset)" ) ;
if ( $ mesg - > count == 0 ) {
$ mesg = $ ldap - > add ( dn = > $ rrdn , attr = > list_attrs ( $ attr ) ) ;
die "Failed to add entry:" , $ rrdn , " " , $ mesg - > error if ( $ mesg - > code ) ;
} else {
$ mesg = $ ldap - > modify ( dn = > $ rrdn , add = > { 'DNSipaddr' = > $$ attr { 'DNSipaddr' } } ) ;
die "Failed to modify entry:" , $ rrdn , " " , $ mesg - > error if ( $ mesg - > code ) ;
}
} else {
# All other records are siglevalued, use one rrset for each entry
my $ i = 0 ;
do {
$ i + + ;
$$ attr { 'cn' } = "$$attr{'DNStype'}$i:$tail" ;
$ rrdn = "cn=$$attr{'cn'},cn=$zonename,$BASEDN" ;
$ mesg = $ ldap - > search ( base = > $ rrdn , scope = > "base" , filter = > "(objectclass=DNSrrset)" ) ;
} while ( $ mesg - > count > 0 ) ;
if ( $ FULL_QUALIFIED_NAME ) {
$$ attr { 'DNScname' } = "$$attr{'DNStype'}$i.$zonename." unless defined $$ attr { 'DNScname' } ;
} else {
$$ attr { 'DNScname' } = "$$attr{'DNStype'}$i" unless defined $$ attr { 'DNScname' } ;
}
$ mesg = $ ldap - > add ( dn = > $ rrdn , attr = > list_attrs ( $ attr ) ) ;
die "Failed to add entry:" , $ rrdn , " " , $ mesg - > error if ( $ mesg - > code ) ;
}
}
sub list_attrs
{
my $ attr = shift ;
my ( @ list , $ key , $ value ) ;
while ( ( $ key , $ value ) = each %$ attr ) {
push ( @ list , $ key = > $ value ) ;
}
return \ @ list ;
}
sub read_zone
{
my $ zonename = shift ;
$ res = new Net::DNS:: Resolver ;
$ res - > nameservers ( $ NAMESERVER ) ;
@ zone = $ res - > axfr ( $ zonename ) ;
while ( ! @ zone ) {
print "Query failed for $zonename: " , $ res - > errorstring , ".\n" ;
if ( $ res - > errorstring eq "couldn't connect" ) {
print "Trying to reconnect\n" ;
sleep ( 10 ) ;
@ zone = $ res - > axfr ( $ zonename ) ;
} else {
return ;
}
}
print "---------- reading zone $zonename ----------\n" ;
foreach $ rr ( @ zone ) {
$ rr - > print ;
if ( $ rr - > type eq "SOA" ) {
die "Invalid SOA record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)\s+([0-9a-zA-Z_.+-]+)\s+\((.*)\)/s ) ;
die "Corrupt SOA record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type ) ;
my % attr ;
$ attr { 'objectclass' } = "DNSzone" ;
$ attr { 'DNSzonename' } = lc $ 1 ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
$ attr { 'DNSzonemaster' } = lc $ 5 ;
$ attr { 'DNSadminmailbox' } = lc $ 6 ;
my $ soa = $ 7 ;
die "Invalid SOA fields for " , $ zonename , " " unless ( $ soa =~ /\s*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\s*/s ) ;
$ attr { 'DNSserial' } = $ 1 ;
$ attr { 'DNSrefresh' } = $ 2 ;
$ attr { 'DNSretry' } = $ 3 ;
$ attr { 'DNSexpire' } = $ 4 ;
$ attr { 'DNSminimum' } = $ 5 ;
$ attr { 'cn' } = $ zonename ;
$ mesg = $ ldap - > add ( dn = > "cn=$zonename,$BASEDN" , attr = > list_attrs ( \ % attr ) ) ;
die "Failed to add entry:" , $ zonename , " " , $ mesg - > error if ( $ mesg - > code ) ;
} elsif ( $ rr - > type eq "A" ) {
die "Invalid A record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9.]+)/ ) ;
die "Corrupt A record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type && $ 5 eq $ rr - > address ) ;
next if $ 1 eq "localhost.$zonename" ;
my % attr ;
$ attr { 'objectclass' } = "DNSrrset" ;
$ attr { 'DNSdomainname' } = lc $ 1 ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
$ attr { 'DNSipaddr' } = $ 5 ;
add_attrs ( \ % attr , $ zonename ) ;
} elsif ( $ rr - > type eq "MX" ) {
die "Invalid MX record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+([0-9a-zA-Z_.+-]+)/ ) ;
die "Corrupt MX record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type ) ;
my % attr ;
$ attr { 'objectclass' } = "DNSrrset" ;
$ attr { 'DNSdomainname' } = lc $ 1 ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
$ attr { 'DNSpreference' } = $ 5 ;
$ attr { 'DNScname' } = lc $ 6 ;
add_attrs ( \ % attr , $ zonename ) ;
} elsif ( $ rr - > type eq "NS" ) {
die "Invalid NS record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/ ) ;
die "Corrupt NS record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type ) ;
my % attr ;
$ attr { 'objectclass' } = "DNSrrset" ;
$ attr { 'DNSdomainname' } = lc $ 1 ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
$ attr { 'DNScname' } = lc $ 5 ;
add_attrs ( \ % attr , $ zonename ) ;
} elsif ( $ rr - > type eq "CNAME" || $ rr - > type eq "TXT" ) {
2006-03-20 02:03:28 +00:00
die "Invalid " , $ rr - > type , " record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-\s\"=:]+)/ ) ;
2005-12-02 04:09:15 +00:00
die "Corrupt " , $ rr - > type , " record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type ) ;
my % attr ;
$ attr { 'objectclass' } = "DNSrrset" ;
$ attr { 'DNSdomainname' } = $ 1 ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
2008-07-24 18:16:47 +00:00
if ( $ rr - > type eq "CNAME" ) {
$ attr { 'DNScname' } = $ 5 ;
} elsif ( $ rr - > type eq "TXT" ) {
$ attr { 'DNStxt' } = $ 5 ;
}
2005-12-02 04:09:15 +00:00
add_attrs ( \ % attr , $ zonename ) ;
} elsif ( $ rr - > type eq "PTR" ) {
die "Invalid PTR record for " , $ rr - > name , " " unless ( $ rr - > string =~ /^([0-9.]+\.in-addr\.arpa)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/ ) ;
die "Corrupt PTR record for " , $ rr - > name , " " unless ( $ 1 eq $ rr - > name && $ 2 eq $ rr - > ttl && $ 3 eq $ rr - > class && $ 4 eq $ rr - > type ) ;
my % attr ;
$ attr { 'objectclass' } = "DNSrrset" ;
$ attr { 'DNSdomainname' } = "$1." ;
$ attr { 'DNSttl' } = $ 2 ;
$ attr { 'DNSclass' } = $ 3 ;
$ attr { 'DNStype' } = $ 4 ;
$ attr { 'DNScname' } = $ 5 ;
if ( $ attr { 'DNSdomainname' } =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
$ attr { 'DNSipaddr' } = "$4.$3.$2.$1" ;
$ attr { 'cn' } = "PTR:$1" ; # Only for C-level domains yet
} else { die "Corrupt IP address for" , $ rr - > name ; }
my $ rrdn = "cn=$attr{'cn'},cn=$zonename,$BASEDN" ;
$ mesg = $ ldap - > add ( dn = > $ rrdn , attr = > list_attrs ( \ % attr ) ) ;
die "Failed to add entry:" , $ rrdn , " " , $ mesg - > error if ( $ mesg - > code ) ;
}
}
}