This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
ildus/lib/ildus/server/domain_backends/ldap.rb

134 lines
4.2 KiB
Ruby

# = ildus/server/backend - ldap domain backend library
#
# Copyright (C) 2005 Paul van Tilburg <paul@luon.net>
#
# Ildus is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
require 'ldap'
module Ildus::Server::DomainBackend
# = LDAP domain backend
#
# The domain backend class that uses an LDAP database. It uses the LDAP
# record format used by the PowerDNS backend. (see:
# http://www.linuxnetworks.de/pdnsldap/dnsdomain2.schema) Next to that it
# uses an extra ildusOwner field to couple LDAP dNSdomain records to
# users.
class Ldap < Basic
# Sets up the LDAP backend by switching to LDAPv3 protocol
# and binding to the server.
def initialize(*args)
super
@ldap = LDAP::Conn.new(config['host'])
@ldap.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
@ldap.simple_bind(config['user'], config['pass'])
end
# Updates the serial on the SOA record and calls the inherited
# commit (invoking the hook).
def commit
update_serial
super
end
# Returns the list (a Hash actually) of hosts for the selected user.
# It looks for A, AAAA and CNAME records.
def hosts
entries = Hash.new { |h, k| h[k] = [[], []] }
all_entries.each do |entry|
assoc_dom, a_rr, aaaa_rr, cname_rr =
["associatedDomain", "aRecord",
"aAAArecord", "cNAMErecord"].map { |attr| entry[attr] }
host = assoc_dom.first.gsub(/\.#{config['domain']}$/, '')
entries[host].first.push(*a_rr) if a_rr
entries[host].first.push(*aaaa_rr) if aaaa_rr
if cname_rr
cname = cname_rr.first.gsub(/\.#{config['domain']}$/, '')
entries[cname].last << host
end
end # search
return entries
end # def hosts
# Updates the address of _host_ to _addr_ providing that _addr_ is in a
# correct IPv4 or IPv6 address format.
def update_host(host, addr)
entry = all_entries.find do |entry|
entry['associatedDomain'][0] == host + "." + config['domain']
end
raise Handler::HostNotFoundError if entry.nil?
if addr.ipv4?
@ldap.modify(entry['dn'][0], {"aRecord" => [addr.to_s]})
elsif addr.ipv6?
@ldap.modify(entry['dn'][0], {"aAAARecord" => [addr.to_s]})
else
return false
end
true
end
#########
private
#########
# Returns a list of all LDAP IldusRecord entries for the selected
# user.
def all_entries
@ldap.search2(config['base'], LDAP::LDAP_SCOPE_SUBTREE,
"(&(objectClass=ildusRecord)(ildusOwner=#{user}))")
end
# Returns the LDAP sOARecord for the configured domain.
def soa_record
@ldap.search2(config['base'], LDAP::LDAP_SCOPE_BASE,
"(&(associatedDomain=#{config['domain'].downcase})" \
" (sOARecord=*))").first
end
# Updates the serial of the SOA record of the configured domain.
# The serial consists of two parts, the date (yyyymmdd) and
# counter (nn) part. On every update the date is set to the current
# date, it will increase the counter.
#
# Note that the counter may overflow so that actually the day is
# incremented. This is no problem unless there is an almost infinite
# sequance of days with more then 100 updates/day.
def update_serial
record = soa_record
soa = record['sOARecord'].first.split
soa[2] = serial_succ(soa[2])
@ldap.modify(record['dn'][0], {"sOARecord" => [soa.join(" ")]})
end
# Determines the successor of the current serial number, see
# also #update_serial().
def serial_succ(serial)
date, num = serial.scan(/\d{8}|\d{2}/)
today = Time.now.strftime("%Y%m%d")
if (date < today)
date, num = today, '00'
elsif (num == '99')
date, num = date.succ, '00'
else
num = num.succ
end
return "%08s%02s" % [date, num]
end
end # class Ldap
end # module Ildus::Server::DomainBackend