|
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
32 |
# <http://www.gnu.org/licenses/>. |
32 |
# <http://www.gnu.org/licenses/>. |
33 |
|
33 |
|
|
|
34 |
from __future__ import absolute_import |
34 |
import ldap, string |
35 |
import ldap, string |
35 |
from ldap.filter import escape_filter_chars, filter_format |
36 |
from ldap.filter import escape_filter_chars, filter_format |
36 |
import univention.debug2 as ud |
37 |
import univention.debug2 as ud |
|
46 |
import time |
47 |
import time |
47 |
import sys |
48 |
import sys |
48 |
|
49 |
|
|
|
50 |
from dns.rdtypes.ANY.TXT import TXT |
51 |
from dns import rdatatype |
52 |
from dns import rdataclass |
53 |
from dns.tokenizer import Tokenizer |
54 |
|
49 |
from samba.provision.sambadns import ARecord |
55 |
from samba.provision.sambadns import ARecord |
50 |
# def __init__(self, ip_addr, serial=1, ttl=3600): |
56 |
# def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
51 |
|
57 |
|
52 |
from samba.provision.sambadns import AAAARecord |
58 |
from samba.provision.sambadns import AAAARecord |
53 |
# def __init__(self, ip6_addr, serial=1, ttl=3600): |
59 |
# def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
54 |
|
60 |
|
55 |
from samba.provision.sambadns import NSRecord |
61 |
from samba.provision.sambadns import NSRecord |
56 |
# def __init__(self, dns_server, serial=1, ttl=3600): |
62 |
# def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
57 |
|
63 |
|
58 |
from samba.provision.sambadns import SOARecord |
64 |
from samba.provision.sambadns import SOARecord |
59 |
# def __init__(self, mname, rname, serial=1, refresh=900, retry=600, expire=86400, minimum=3600, ttl=3600): |
65 |
# def __init__(self, mname, rname, serial=1, refresh=900, retry=600, expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE): |
60 |
|
66 |
|
61 |
from samba.provision.sambadns import SRVRecord |
67 |
from samba.provision.sambadns import SRVRecord |
62 |
# def __init__(self, target, port, priority=0, weight=0, serial=1, ttl=3600): |
68 |
# def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
63 |
|
69 |
|
64 |
class CName(dnsp.DnssrvRpcRecord): |
70 |
from samba.provision.sambadns import CNameRecord |
65 |
def __init__(self, cname, serial=1, ttl=3600): |
71 |
# def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
66 |
super(CName, self).__init__() |
|
|
67 |
self.wType=dnsp.DNS_TYPE_CNAME |
68 |
self.dwSerial=serial |
69 |
self.dwTtlSeconds=ttl |
70 |
self.data=cname |
71 |
|
72 |
|
|
|
73 |
from samba.provision.sambadns import TXTRecord |
74 |
# def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
75 |
|
72 |
class PTRRecord(dnsp.DnssrvRpcRecord): |
76 |
class PTRRecord(dnsp.DnssrvRpcRecord): |
73 |
def __init__(self, ptr, serial=1, ttl=3600): |
77 |
def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
74 |
super(PTRRecord, self).__init__() |
78 |
super(PTRRecord, self).__init__() |
75 |
self.wType=dnsp.DNS_TYPE_PTR |
79 |
self.wType = dnsp.DNS_TYPE_PTR |
76 |
self.dwSerial=serial |
80 |
self.rank = rank |
77 |
self.dwTtlSeconds=ttl |
81 |
self.dwSerial = serial |
78 |
self.data=ptr |
82 |
self.dwTtlSeconds = ttl |
|
|
83 |
self.data = ptr |
79 |
|
84 |
|
80 |
class MXRecord(dnsp.DnssrvRpcRecord): |
85 |
class MXRecord(dnsp.DnssrvRpcRecord): |
81 |
def __init__(self, name, priority, serial=1, ttl=3600): |
86 |
def __init__(self, name, priority, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE): |
82 |
super(MXRecord, self).__init__() |
87 |
super(MXRecord, self).__init__() |
83 |
self.wType=dnsp.DNS_TYPE_MX |
88 |
self.wType = dnsp.DNS_TYPE_MX |
84 |
self.dwSerial=serial |
89 |
self.rank = rank |
85 |
self.dwTtlSeconds=ttl |
90 |
self.dwSerial = serial |
86 |
self.data.wPriority=priority |
91 |
self.dwTtlSeconds = ttl |
87 |
self.data.nameTarget=name |
92 |
self.data.wPriority = priority |
|
|
93 |
self.data.nameTarget = name |
88 |
|
94 |
|
89 |
import univention.admin.handlers |
95 |
import univention.admin.handlers |
90 |
import univention.admin.handlers.dns.forward_zone |
96 |
import univention.admin.handlers.dns.forward_zone |
|
571 |
mx.append( [str(ndrRecord.data.wPriority), __append_dot(ndrRecord.data.nameTarget)] ) |
577 |
mx.append( [str(ndrRecord.data.wPriority), __append_dot(ndrRecord.data.nameTarget)] ) |
572 |
return mx |
578 |
return mx |
573 |
|
579 |
|
|
|
580 |
def __pack_txtRecord(object, dnsRecords): |
581 |
slist=[] |
582 |
for txtRecord in object['attributes'].get('tXTRecord', []): |
583 |
if txtRecord: |
584 |
ud.debug(ud.LDAP, ud.INFO, '__pack_txtRecord: %s' % txtRecord) |
585 |
txtRecord=univention.s4connector.s4.compatible_modstring(txtRecord) |
586 |
token_list = TXT.from_text(rdataclass.IN, rdatatype.TXT, Tokenizer(txtRecord)).strings |
587 |
ndr_txt_record = ndr_pack(TXTRecord(token_list)) |
588 |
dnsRecords.append(ndr_txt_record) |
589 |
ud.debug(ud.LDAP, ud.INFO, '__pack_txtRecord: %s' % ndr_txt_record) |
590 |
|
591 |
def __unpack_txtRecord(object): |
592 |
txt=[] |
593 |
dnsRecords=object['attributes'].get('dnsRecord', []) |
594 |
for dnsRecord in dnsRecords: |
595 |
dnsRecord=dnsRecord.encode('latin1') |
596 |
ndrRecord=ndr_unpack(dnsp.DnssrvRpcRecord, dnsRecord) |
597 |
if ndrRecord.wType == dnsp.DNS_TYPE_TXT: |
598 |
txt.append(str(TXT(rdataclass.IN, rdatatype.TXT, ndrRecord.data.str))) |
599 |
# or: txt.append(' '.join(['"%s"' % token for token in ndrRecord.data.str])) |
600 |
return txt |
601 |
|
574 |
def __pack_cName(object, dnsRecords): |
602 |
def __pack_cName(object, dnsRecords): |
575 |
for c in object['attributes'].get('cNAMERecord', []): |
603 |
for c in object['attributes'].get('cNAMERecord', []): |
576 |
c=univention.s4connector.s4.compatible_modstring(__remove_dot(c)) |
604 |
c=univention.s4connector.s4.compatible_modstring(__remove_dot(c)) |
577 |
c_record=CName(c) |
605 |
c_record=CNameRecord(c) |
578 |
dnsRecords.append(ndr_pack(c_record)) |
606 |
dnsRecords.append(ndr_pack(c_record)) |
579 |
|
607 |
|
580 |
def __unpack_cName(object): |
608 |
def __unpack_cName(object): |
|
717 |
|
745 |
|
718 |
__pack_mxRecord(object, dnsRecords) |
746 |
__pack_mxRecord(object, dnsRecords) |
719 |
|
747 |
|
|
|
748 |
__pack_txtRecord(object, dnsRecords) |
749 |
|
720 |
s4connector.lo_s4.modify(soa_dn, [('dnsRecord', old_dnsRecords, dnsRecords)]) |
750 |
s4connector.lo_s4.modify(soa_dn, [('dnsRecord', old_dnsRecords, dnsRecords)]) |
721 |
|
751 |
|
722 |
return True |
752 |
return True |
|
870 |
else: |
900 |
else: |
871 |
__pack_aRecord(object, dnsRecords) |
901 |
__pack_aRecord(object, dnsRecords) |
872 |
|
902 |
|
|
|
903 |
__pack_mxRecord(object, dnsRecords) |
904 |
__pack_txtRecord(object, dnsRecords) |
905 |
|
873 |
dnsNodeDn=s4_dns_node_base_create(s4connector, object, dnsRecords) |
906 |
dnsNodeDn=s4_dns_node_base_create(s4connector, object, dnsRecords) |
874 |
|
907 |
|
875 |
return True |
908 |
return True |
|
973 |
newRecord['ptr_record']=ptr[0] |
1006 |
newRecord['ptr_record']=ptr[0] |
974 |
newRecord.modify() |
1007 |
newRecord.modify() |
975 |
else: |
1008 |
else: |
976 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_ptr_record_create: do not modify host record') |
1009 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_ptr_record_create: do not modify ptr record') |
977 |
else: |
1010 |
else: |
978 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1011 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
979 |
|
1012 |
|
|
1029 |
newRecord['cname']=c[0] |
1062 |
newRecord['cname']=c[0] |
1030 |
newRecord.modify() |
1063 |
newRecord.modify() |
1031 |
else: |
1064 |
else: |
1032 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_cname_create: do not modify host record') |
1065 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_cname_create: do not modify cname record') |
1033 |
else: |
1066 |
else: |
1034 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1067 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1035 |
|
1068 |
|
|
1108 |
newRecord['location']=srv |
1141 |
newRecord['location']=srv |
1109 |
newRecord.modify() |
1142 |
newRecord.modify() |
1110 |
else: |
1143 |
else: |
1111 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_srv_record_create: do not modify host record') |
1144 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_srv_record_create: do not modify srv record') |
1112 |
else: |
1145 |
else: |
1113 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1146 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1114 |
|
1147 |
|
|
1189 |
dnsNodeDn=s4_dns_node_base_create(s4connector, object, dnsRecords) |
1222 |
dnsNodeDn=s4_dns_node_base_create(s4connector, object, dnsRecords) |
1190 |
|
1223 |
|
1191 |
|
1224 |
|
|
|
1225 |
def ucs_txt_record_create(s4connector, object): |
1226 |
_d=ud.function('ucs_txt_record_create') |
1227 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_txt_record_create: object: %s' % object) |
1228 |
udm_property='txt' |
1229 |
|
1230 |
zoneName = object['attributes']['zoneName'][0] |
1231 |
relativeDomainName = object['attributes']['relativeDomainName'][0] |
1232 |
|
1233 |
# unpack the record |
1234 |
c = __unpack_txtRecord(object) |
1235 |
|
1236 |
# Does a host record for this zone already exist? |
1237 |
ol_filter = filter_format('(&(relativeDomainName=%s)(zoneName=%s))', (relativeDomainName, zoneName)) |
1238 |
searchResult=s4connector.lo.search(filter=ol_filter, unique=1) |
1239 |
if len(searchResult) > 0: |
1240 |
superordinate=s4connector_get_superordinate('dns/txt_record', s4connector.lo, searchResult[0][0]) |
1241 |
foundRecord= univention.admin.handlers.dns.txt_record.object(None, s4connector.lo, position=None, dn=searchResult[0][0], superordinate=superordinate, attributes=[], update_zone=False) |
1242 |
foundRecord.open() |
1243 |
|
1244 |
## use normalized TXT records for comparison |
1245 |
normalized_txtRecord_list = [] |
1246 |
for txtRecord in foundRecord['txt']: |
1247 |
normalized_txtRecord = str(TXT.from_text(rdataclass.IN, rdatatype.TXT, Tokenizer(txtRecord))) |
1248 |
normalized_txtRecord_list.append(normalized_txtRecord) |
1249 |
|
1250 |
if set(normalized_txtRecord_list) != set(c): |
1251 |
foundRecord[udm_property]=c |
1252 |
foundRecord.modify() |
1253 |
else: |
1254 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_txt_record_create: do not modify txt record') |
1255 |
else: |
1256 |
zoneDN='zoneName=%s,%s' % (zoneName, s4connector.property['dns'].ucs_default_dn) |
1257 |
|
1258 |
superordinate=s4connector_get_superordinate('dns/txt_record', s4connector.lo, zoneDN) |
1259 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_txt_record_create: superordinate: %s' % superordinate) |
1260 |
|
1261 |
position=univention.admin.uldap.position(zoneDN) |
1262 |
|
1263 |
newRecord= univention.admin.handlers.dns.txt_record.object(None, s4connector.lo, position, dn=None, superordinate=superordinate, attributes=[], update_zone=False) |
1264 |
newRecord.open() |
1265 |
newRecord['name']=relativeDomainName |
1266 |
newRecord[udm_property]=c |
1267 |
newRecord.create() |
1268 |
|
1269 |
|
1270 |
def ucs_txt_record_delete(s4connector, object): |
1271 |
_d=ud.function('ucs_txt_record_delete') |
1272 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_txt_record_delete: object: %s' % object) |
1273 |
|
1274 |
zoneName = object['attributes']['zoneName'][0] |
1275 |
relativeDomainName = object['attributes']['relativeDomainName'][0] |
1276 |
|
1277 |
ol_filter = filter_format('(&(relativeDomainName=%s)(zoneName=%s))', (relativeDomainName, zoneName)) |
1278 |
searchResult=s4connector.lo.search(filter=ol_filter, unique=1) |
1279 |
if len(searchResult) > 0: |
1280 |
superordinate=s4connector_get_superordinate('dns/txt_record', s4connector.lo, searchResult[0][0]) |
1281 |
newRecord= univention.admin.handlers.dns.txt_record.object(None, s4connector.lo, position=None, dn=searchResult[0][0], superordinate=superordinate, attributes=[], update_zone=False) |
1282 |
newRecord.open() |
1283 |
newRecord.delete() |
1284 |
else: |
1285 |
ud.debug(ud.LDAP, ud.INFO, 'ucs_txt_record_delete: Object was not found, filter was: %s' % ol_filter) |
1286 |
|
1287 |
return True |
1288 |
|
1289 |
def s4_txt_record_create(s4connector, object): |
1290 |
_d=ud.function('s4_txt_record_create') |
1291 |
|
1292 |
dnsRecords=[] |
1293 |
|
1294 |
__pack_txtRecord(object, dnsRecords) |
1295 |
|
1296 |
dnsNodeDn=s4_dns_node_base_create(s4connector, object, dnsRecords) |
1297 |
|
1192 |
def ucs_zone_create(s4connector, object, dns_type): |
1298 |
def ucs_zone_create(s4connector, object, dns_type): |
1193 |
_d=ud.function('ucs_zone_create') |
1299 |
_d=ud.function('ucs_zone_create') |
1194 |
|
1300 |
|
|
1328 |
return 'srv_record' |
1434 |
return 'srv_record' |
1329 |
if univention.admin.handlers.dns.ptr_record.identify(object['dn'], object['attributes']): |
1435 |
if univention.admin.handlers.dns.ptr_record.identify(object['dn'], object['attributes']): |
1330 |
return 'ptr_record' |
1436 |
return 'ptr_record' |
|
|
1437 |
if univention.admin.handlers.dns.txt_record.identify(object['dn'], object['attributes']): |
1438 |
return 'txt_record' |
1331 |
return None |
1439 |
return None |
1332 |
|
1440 |
|
1333 |
def _identify_dns_con_object(s4connector, object): |
1441 |
def _identify_dns_con_object(s4connector, object): |
|
1374 |
return 'srv_record' |
1482 |
return 'srv_record' |
1375 |
elif set((dnsp.DNS_TYPE_A, dnsp.DNS_TYPE_AAAA)) & dns_types: |
1483 |
elif set((dnsp.DNS_TYPE_A, dnsp.DNS_TYPE_AAAA)) & dns_types: |
1376 |
return 'host_record' |
1484 |
return 'host_record' |
|
|
1485 |
elif dnsp.DNS_TYPE_TXT in dns_types: |
1486 |
return 'txt_record' |
1377 |
|
1487 |
|
1378 |
return None |
1488 |
return None |
1379 |
|
1489 |
|
|
1436 |
s4_dns_node_base_delete(s4connector, object) |
1546 |
s4_dns_node_base_delete(s4connector, object) |
1437 |
# ignore move |
1547 |
# ignore move |
1438 |
|
1548 |
|
|
|
1549 |
elif dns_type == 'txt_record': |
1550 |
if object['modtype'] in ['add', 'modify']: |
1551 |
s4_txt_record_create(s4connector, object) |
1552 |
elif object['modtype'] in ['delete']: |
1553 |
s4_dns_node_base_delete(s4connector, object) |
1554 |
# ignore move |
1555 |
|
1439 |
return True |
1556 |
return True |
1440 |
|
1557 |
|
1441 |
def con2ucs (s4connector, key, object): |
1558 |
def con2ucs (s4connector, key, object): |
|
1486 |
elif object['modtype'] in ['delete']: |
1603 |
elif object['modtype'] in ['delete']: |
1487 |
ucs_srv_record_delete(s4connector, object) |
1604 |
ucs_srv_record_delete(s4connector, object) |
1488 |
# ignore move |
1605 |
# ignore move |
|
|
1606 |
elif dns_type == 'txt_record': |
1607 |
if object['modtype'] in ['add', 'modify']: |
1608 |
ucs_txt_record_create(s4connector, object) |
1609 |
elif object['modtype'] in ['delete']: |
1610 |
ucs_txt_record_delete(s4connector, object) |
1611 |
# ignore move |
1489 |
if dns_type in ['forward_zone', 'reverse_zone']: |
1612 |
if dns_type in ['forward_zone', 'reverse_zone']: |
1490 |
if object['modtype'] in ['add', 'modify']: |
1613 |
if object['modtype'] in ['add', 'modify']: |
1491 |
ucs_zone_create(s4connector, object, dns_type) |
1614 |
ucs_zone_create(s4connector, object, dns_type) |
|
1509 |
univention.admin.handlers.dns.alias.identify(dn, attr) or\ |
1632 |
univention.admin.handlers.dns.alias.identify(dn, attr) or\ |
1510 |
univention.admin.handlers.dns.host_record.identify(dn, attr) or\ |
1633 |
univention.admin.handlers.dns.host_record.identify(dn, attr) or\ |
1511 |
univention.admin.handlers.dns.srv_record.identify(dn, attr) or\ |
1634 |
univention.admin.handlers.dns.srv_record.identify(dn, attr) or\ |
1512 |
univention.admin.handlers.dns.ptr_record.identify(dn, attr) |
1635 |
univention.admin.handlers.dns.ptr_record.identify(dn, attr) or\ |
|
|
1636 |
univention.admin.handlers.dns.txt_record.identify(dn, attr) |
1513 |
|
1637 |
|
1514 |
''' |
1638 |
''' |
1515 |
Because the dns/dns.py identify function has been overwritten |
1639 |
Because the dns/dns.py identify function has been overwritten |