diff options
Diffstat (limited to 'source4/scripting/python')
| -rw-r--r-- | source4/scripting/python/samba/netcmd/dns.py | 859 | ||||
| -rw-r--r-- | source4/scripting/python/samba/netcmd/main.py | 2 | 
2 files changed, 861 insertions, 0 deletions
diff --git a/source4/scripting/python/samba/netcmd/dns.py b/source4/scripting/python/samba/netcmd/dns.py new file mode 100644 index 0000000000..0ee4a6f06d --- /dev/null +++ b/source4/scripting/python/samba/netcmd/dns.py @@ -0,0 +1,859 @@ +#!/usr/bin/env python +# +# DNS management tool +# +# Copyright (C) Amitay Isaacs 2011 +# +# This program 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. +# + +import os +import samba.getopt as options +import ldb +from struct import pack +from socket import inet_ntoa + +from samba.netcmd import ( +    Command, +    CommandError, +    Option, +    SuperCommand, +    ) +from samba.dcerpc import dnsp, dnsserver +from samba.ndr import ndr_print + + +def dns_connect(server, lp, creds): +    binding_str = "ncacn_ip_tcp:%s[sign]" % server +    dns_conn = dnsserver.dnsserver(binding_str, lp, creds) +    return dns_conn + +def bool_string(flag): +    if flag == 0: +        ret = 'FALSE' +    elif flag == 1: +        ret = 'TRUE' +    else: +        ret = 'UNKNOWN (0x%x)' % flag +    return ret + +def enum_string(module, enum_defs, value): +    ret = None +    for e in enum_defs: +        if value == getattr(module, e): +            ret = e +            break +    if not ret: +        ret = 'UNKNOWN (0x%x)' % value +    return ret + +def bitmap_string(module, bitmap_defs, value): +    ret = '' +    for b in bitmap_defs: +        if value & getattr(module, b): +            ret += '%s ' % b +    if not ret: +        ret = 'NONE' +    return ret + +def boot_method_string(boot_method): +    enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE', +                    'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ] +    return enum_string(dnsserver, enum_defs, boot_method) + +def name_check_flag_string(check_flag): +    enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES', +                    'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ] +    return enum_string(dnsserver, enum_defs, check_flag) + +def zone_type_string(zone_type): +    enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY', +                    'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB', +                    'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ] +    return enum_string(dnsp, enum_defs, zone_type) + +def zone_update_string(zone_update): +    enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_SECURE', +                    'DNS_ZONE_UPDATE_SECURE' ] +    return enum_string(dnsp, enum_defs, zone_update) + +def zone_secondary_security_string(security): +    enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY', +                    'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ] +    return enum_string(dnsserver, enum_defs, security) + +def zone_notify_level_string(notify_level): +    enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES', +                    'DNS_ZONE_NOTIFY_LIST_ONLY' ] +    return enum_string(dnsserver, enum_defs, notify_level) + +def dp_flags_string(dp_flags): +    bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT', +                'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ] +    return bitmap_string(dnsserver, bitmap_defs, dp_flags) + +def zone_flags_string(flags): +    bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN', +                    'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED', +                    'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING', +                    'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE', +                    'DNS_RPC_ZONE_READONLY'] +    return bitmap_string(dnsserver, bitmap_defs, flags) + +def ip4_array_string(array): +    ret = [] +    if not array: +        return ret +    for i in xrange(array.AddrCount): +        addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i])) +        ret.append(addr) +    return ret + +def dns_addr_array_string(array): +    ret = [] +    if not array: +        return ret +    for i in xrange(array.AddrCount): +        if array.AddrArray[i].MaxSa[0] == 0x02: +            addr = '%d.%d.%d.%d (%d)' % \ +                tuple(array.AddrArray[i].MaxSa[4:8] + [array.AddrArray[i].MaxSa[3]]) +        elif array.AddrArray[i].MaxSa[0] == 0x17: +            addr = '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \ +                tuple(array.AddrArray[i].MaxSa[4:20] + [array.AddrArray[i].MaxSa[3]]) +        else: +            addr = 'UNKNOWN' +        ret.append(addr) +    return ret + +def dns_type_flag(rec_type): +    rtype = rec_type.upper() +    if rtype == 'A': +        record_type = dnsp.DNS_TYPE_A +    elif rtype == 'NS': +        record_type = dnsp.DNS_TYPE_NS +    elif rtype == 'CNAME': +        record_type = dnsp.DNS_TYPE_CNAME +    elif rtype == 'SOA': +        record_type = dnsp.DNS_TYPE_SOA +    elif rtype == 'MX': +        record_type = dnsp.DNS_TYPE_MX +    elif rtype == 'SRV': +        record_type = dnsp.DNS_TYPE_SRV +    elif rtype == 'ALL': +        record_type = dnsp.DNS_TYPE_ALL +    else: +        raise CommandError('Unknown type of DNS record %s' % rec_type) +    return record_type + +def dns_client_version(cli_version): +    version = cli_version.upper() +    if version == 'W2K': +        client_version = dnsserver.DNS_CLIENT_VERSION_W2K +    elif version == 'DOTNET': +        client_version = dnsserver.DNS_CLIENT_VERSION_DOTNET +    elif version == 'LONGHORN': +        client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN +    else: +        raise CommandError('Unknown client version %s' % cli_version) +    return client_version + +def print_serverinfo(outf, typeid, serverinfo): +    outf.write('  dwVersion                   : 0x%x\n' % serverinfo.dwVersion) +    outf.write('  fBootMethod                 : %s\n' % boot_method_string(serverinfo.fBootMethod)) +    outf.write('  fAdminConfigured            : %s\n' % bool_string(serverinfo.fAdminConfigured)) +    outf.write('  fAllowUpdate                : %s\n' % bool_string(serverinfo.fAllowUpdate)) +    outf.write('  fDsAvailable                : %s\n' % bool_string(serverinfo.fDsAvailable)) +    outf.write('  pszServerName               : %s\n' % serverinfo.pszServerName) +    outf.write('  pszDsContainer              : %s\n' % serverinfo.pszDsContainer) + +    if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO: +        outf.write('  aipServerAddrs              : %s\n' % +                    ip4_array_string(serverinfo.aipServerAddrs)) +        outf.write('  aipListenAddrs              : %s\n' % +                    ip4_array_string(serverinfo.aipListenAddrs)) +        outf.write('  aipForwarders               : %s\n' % +                    ip4_array_string(serverinfo.aipForwarders)) +    else: +        outf.write('  aipServerAddrs              : %s\n' % +                    dns_addr_array_string(serverinfo.aipServerAddrs)) +        outf.write('  aipListenAddrs              : %s\n' % +                    dns_addr_array_string(serverinfo.aipListenAddrs)) +        outf.write('  aipForwarders               : %s\n' % +                    dns_addr_array_string(serverinfo.aipForwarders)) + +    outf.write('  dwLogLevel                  : %d\n' % serverinfo.dwLogLevel) +    outf.write('  dwDebugLevel                : %d\n' % serverinfo.dwDebugLevel) +    outf.write('  dwForwardTimeout            : %d\n' % serverinfo.dwForwardTimeout) +    outf.write('  dwRpcPrototol               : 0x%x\n' % serverinfo.dwRpcProtocol) +    outf.write('  dwNameCheckFlag             : %s\n' % name_check_flag_string(serverinfo.dwNameCheckFlag)) +    outf.write('  cAddressAnswerLimit         : %d\n' % serverinfo.cAddressAnswerLimit) +    outf.write('  dwRecursionRetry            : %d\n' % serverinfo.dwRecursionRetry) +    outf.write('  dwRecursionTimeout          : %d\n' % serverinfo.dwRecursionTimeout) +    outf.write('  dwMaxCacheTtl               : %d\n' % serverinfo.dwMaxCacheTtl) +    outf.write('  dwDsPollingInterval         : %d\n' % serverinfo.dwDsPollingInterval) +    outf.write('  dwScavengingInterval        : %d\n' % serverinfo.dwScavengingInterval) +    outf.write('  dwDefaultRefreshInterval    : %d\n' % serverinfo.dwDefaultRefreshInterval) +    outf.write('  dwDefaultNoRefreshInterval  : %d\n' % serverinfo.dwDefaultNoRefreshInterval) +    outf.write('  fAutoReverseZones           : %s\n' % bool_string(serverinfo.fAutoReverseZones)) +    outf.write('  fAutoCacheUpdate            : %s\n' % bool_string(serverinfo.fAutoCacheUpdate)) +    outf.write('  fRecurseAfterForwarding     : %s\n' % bool_string(serverinfo.fRecurseAfterForwarding)) +    outf.write('  fForwardDelegations         : %s\n' % bool_string(serverinfo.fForwardDelegations)) +    outf.write('  fNoRecursion                : %s\n' % bool_string(serverinfo.fNoRecursion)) +    outf.write('  fSecureResponses            : %s\n' % bool_string(serverinfo.fSecureResponses)) +    outf.write('  fRoundRobin                 : %s\n' % bool_string(serverinfo.fRoundRobin)) +    outf.write('  fLocalNetPriority           : %s\n' % bool_string(serverinfo.fLocalNetPriority)) +    outf.write('  fBindSecondaries            : %s\n' % bool_string(serverinfo.fBindSecondaries)) +    outf.write('  fWriteAuthorityNs           : %s\n' % bool_string(serverinfo.fWriteAuthorityNs)) +    outf.write('  fStrictFileParsing          : %s\n' % bool_string(serverinfo.fStrictFileParsing)) +    outf.write('  fLooseWildcarding           : %s\n' % bool_string(serverinfo.fLooseWildcarding)) +    outf.write('  fDefaultAgingState          : %s\n' % bool_string(serverinfo.fDefaultAgingState)) + +    if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K: +        outf.write('  dwRpcStructureVersion       : 0x%x\n' % serverinfo.dwRpcStructureVersion) +        outf.write('  aipLogFilter                : %s\n' % dns_addr_array_string(serverinfo.aipLogFilter)) +        outf.write('  pwszLogFilePath             : %s\n' % serverinfo.pwszLogFilePath) +        outf.write('  pszDomainName               : %s\n' % serverinfo.pszDomainName) +        outf.write('  pszForestName               : %s\n' % serverinfo.pszForestName) +        outf.write('  pszDomainDirectoryPartition : %s\n' % serverinfo.pszDomainDirectoryPartition) +        outf.write('  pszForestDirectoryPartition : %s\n' % serverinfo.pszForestDirectoryPartition) + +        outf.write('  dwLocalNetPriorityNetMask   : 0x%x\n' % serverinfo.dwLocalNetPriorityNetMask) +        outf.write('  dwLastScavengeTime          : %d\n' % serverinfo.dwLastScavengeTime) +        outf.write('  dwEventLogLevel             : %d\n' % serverinfo.dwEventLogLevel) +        outf.write('  dwLogFileMaxSize            : %d\n' % serverinfo.dwLogFileMaxSize) +        outf.write('  dwDsForestVersion           : %d\n' % serverinfo.dwDsForestVersion) +        outf.write('  dwDsDomainVersion           : %d\n' % serverinfo.dwDsDomainVersion) +        outf.write('  dwDsDsaVersion              : %d\n' % serverinfo.dwDsDsaVersion) + +    if typeid == dnsserver.DNSSRV_TYPEID_SERVER_INFO: +        outf.write('  fReadOnlyDC                 : %s\n' % bool_string(serverinfo.fReadOnlyDC)) + + +def print_zoneinfo(outf, typeid, zoneinfo): +    outf.write('  pszZoneName                 : %s\n' % zoneinfo.pszZoneName) +    outf.write('  dwZoneType                  : %s\n' % zone_type_string(zoneinfo.dwZoneType)) +    outf.write('  fReverse                    : %s\n' % bool_string(zoneinfo.fReverse)) +    outf.write('  fAllowUpdate                : %s\n' % zone_update_string(zoneinfo.fAllowUpdate)) +    outf.write('  fPaused                     : %s\n' % bool_string(zoneinfo.fPaused)) +    outf.write('  fShutdown                   : %s\n' % bool_string(zoneinfo.fShutdown)) +    outf.write('  fAutoCreated                : %s\n' % bool_string(zoneinfo.fAutoCreated)) +    outf.write('  fUseDatabase                : %s\n' % bool_string(zoneinfo.fUseDatabase)) +    outf.write('  pszDataFile                 : %s\n' % zoneinfo.pszDataFile) +    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO: +        outf.write('  aipMasters                  : %s\n' % +                    ip4_array_string(zoneinfo.aipMasters)) +    else: +        outf.write('  aipMasters                  : %s\n' % +                    dns_addr_array_string(zoneinfo.aipMasters)) +    outf.write('  fSecureSecondaries          : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries)) +    outf.write('  fNotifyLevel                : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel)) +    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO: +        outf.write('  aipSecondaries              : %s\n' % +                    ip4_array_string(zoneinfo.aipSecondaries)) +        outf.write('  aipNotify                   : %s\n' % +                    ip4_array_string(zoneinfo.aipNotify)) +    else: +        outf.write('  aipSecondaries              : %s\n' % +                    dns_addr_array_string(zoneinfo.aipSecondaries)) +        outf.write('  aipNotify                   : %s\n' % +                    dns_addr_array_string(zoneinfo.aipNotify)) +    outf.write('  fUseWins                    : %s\n' % bool_string(zoneinfo.fUseWins)) +    outf.write('  fUseNbstat                  : %s\n' % bool_string(zoneinfo.fUseNbstat)) +    outf.write('  fAging                      : %s\n' % bool_string(zoneinfo.fAging)) +    outf.write('  dwNoRefreshInterval         : %d\n' % zoneinfo.dwNoRefreshInterval) +    outf.write('  dwRefreshInterval           : %d\n' % zoneinfo.dwRefreshInterval) +    outf.write('  dwAvailForScavengeTime      : %d\n' % zoneinfo.dwAvailForScavengeTime) +    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO: +        outf.write('  aipScavengeServers          : %s\n' % +                    ip4_array_string(zoneinfo.aipScavengeServers)) +    else: +        outf.write('  aipScavengeServers          : %s\n' % +                    dns_addr_array_string(zoneinfo.aipScavengeServers)) + +    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K: +        outf.write('  dwRpcStructureVersion       : 0x%x\n' % zoneinfo.dwRpcStructureVersion) +        outf.write('  dwForwarderTimeout          : %d\n' % zoneinfo.dwForwarderTimeout) +        outf.write('  fForwarderSlave             : %d\n' % zoneinfo.fForwarderSlave) +        if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO: +            outf.write('  aipLocalMasters             : %s\n' % +                        ip4_array_string(zoneinfo.aipLocalMasters)) +        else: +            outf.write('  aipLocalMasters             : %s\n' % +                        dns_addr_array_string(zoneinfo.aipLocalMasters)) +        outf.write('  dwDpFlags                   : %s\n' % dp_flags_string(zoneinfo.dwDpFlags)) +        outf.write('  pszDpFqdn                   : %s\n' % zoneinfo.pszDpFqdn) +        outf.write('  pwszZoneDn                  : %s\n' % zoneinfo.pwszZoneDn) +        outf.write('  dwLastSuccessfulSoaCheck    : %d\n' % zoneinfo.dwLastSuccessfulSoaCheck) +        outf.write('  dwLastSuccessfulXfr         : %d\n' % zoneinfo.dwLastSuccessfulXfr) + +    if typeid == dnsserver.DNSSRV_TYPEID_ZONE_INFO: +        outf.write('  fQueuedForBackgroundLoad    : %s\n' % bool_string(zoneinfo.fQueuedForBackgroundLoad)) +        outf.write('  fBackgroundLoadInProgress   : %s\n' % bool_string(zoneinfo.fBackgroundLoadInProgress)) +        outf.write('  fReadOnlyZone               : %s\n' % bool_string(zoneinfo.fReadOnlyZone)) +        outf.write('  dwLastXfrAttempt            : %d\n' % zoneinfo.dwLastXfrAttempt) +        outf.write('  dwLastXfrResult             : %d\n' % zoneinfo.dwLastXfrResult) + + +def print_zone(outf, typeid, zone): +    outf.write('  pszZoneName                 : %s\n' % zone.pszZoneName) +    outf.write('  Flags                       : %s\n' % zone_flags_string(zone.Flags)) +    outf.write('  ZoneType                    : %s\n' % zone_type_string(zone.ZoneType)) +    outf.write('  Version                     : %s\n' % zone.Version) + +    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_W2K: +        outf.write('  dwDpFlags                   : %s\n' % dp_flags_string(zone.dwDpFlags)) +        outf.write('  pszDpFqdn                   : %s\n' % zone.pszDpFqdn) + + +def print_enumzones(outf, typeid, zones): +    outf.write('  %d zone(s) found\n' % zones.dwZoneCount) +    for zone in zones.ZoneArray: +        outf.write('\n') +        print_zone(outf, typeid, zone) + + +def print_dns_record(outf, rec): +    mesg = 'Unknown: ' +    if rec.wType == dnsp.DNS_TYPE_A: +        mesg = 'A: %s' % (rec.data) +    elif rec.wType == dnsp.DNS_TYPE_NS: +        mesg = 'NS: %s' % (rec.data.str) +    elif rec.wType == dnsp.DNS_TYPE_CNAME: +        mesg = 'CNAME: %s' % (rec.data.str) +    elif rec.wType == dnsp.DNS_TYPE_SOA: +        mesg = 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, ns=%s, email=%s' % ( +                    rec.data.dwSerialNo, +                    rec.data.dwRefresh, +                    rec.data.dwRetry, +                    rec.data.dwExpire, +                    rec.data.NamePrimaryServer.str, +                    rec.data.ZoneAdministratorEmail.str) +    elif rec.wType == dnsp.DNS_TYPE_MX: +        mesg = 'MX: %s' % (rec.data.str) +    elif rec.wType == dnsp.DNS_TYPE_SRV: +        mesg = 'SRV: %s (%d)' % (rec.data.nameTarget.str, rec.data.wPort) +    outf.write('    %s (flags=%x, serial=%d, ttl=%d)\n' % ( +                mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds)) + + +def print_dnsrecords(outf, records): +    for rec in records.rec: +        outf.write('  Name=%s, Records=%d, Children=%d\n' % ( +                    rec.dnsNodeName.str, +                    rec.wRecordCount, +                    rec.dwChildCount)) +        for dns_rec in rec.records: +                print_dns_record(outf, dns_rec) + + +class ARecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE, +                    node_flag=0): +        super(ARecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_A +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        self.data = ip_addr + +class AAAARecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE, +                    node_flag=0): +        super(AAAARecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_AAAA +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        self.data = ip6_addr + +class CNameRecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE, +                    node_flag=0): +        super(CNameRecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_CNAME +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        cname_name = dnsserver.DNS_RPC_NAME() +        cname_name.str = cname +        cname_name.len = len(cname) +        self.data = cname_name + +class NSRecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE, +                    node_flag=0): +        super(NSRecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_NS +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        ns = dnsserver.DNS_RPC_NAME() +        ns.str = dns_server +        ns.len = len(dns_server) +        self.data = ns + +class SOARecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, mname, rname, serial=1, refresh=900, retry=600, +                 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE, +                 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT): +        super(SOARecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_SOA +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        soa = dnsserver.DNS_RPC_RECORD_SOA() +        soa.dwSerialNo = serial +        soa.dwRefresh = refresh +        soa.dwRetry = retry +        soa.dwExpire = expire +        soa.NamePrimaryServer.str = mname +        soa.NamePrimaryServer.len = len(mname) +        soa.ZoneAdministratorEmail.str = rname +        soa.ZoneAdministratorEmail.len = len(rname) +        self.data = soa + +class SRVRecord(dnsserver.DNS_RPC_RECORD): +    def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900, +                rank=dnsp.DNS_RANK_ZONE, node_flag=0): +        super(SRVRecord, self).__init__() +        self.wType = dnsp.DNS_TYPE_SRV +        self.dwFlags = rank | node_flag +        self.dwSerial = serial +        self.dwTtlSeconds = ttl +        srv = dnsserver.DNS_RPC_RECORD_SRV() +        srv.wPriority = priority +        srv.wWeight = weight +        srv.wPort = port +        srv.nameTarget.str = target +        srv.nameTarget.len = len(target) +        self.data = srv + +def dns_record_match(dns_conn, server, zone, name, record_type, data): +    select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA + +    try: +        buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                                    0, +                                                    server, +                                                    zone, +                                                    name, +                                                    None, +                                                    record_type, +                                                    select_flags, +                                                    None, +                                                    None) +    except RuntimeError, e: +        return None + +    rec_match = None +    if res and res.count > 0: +        recs = res.rec[0] +        for rec in recs.records: +            if rec.wType == record_type: +                rec_match = rec +                break + +    if rec_match: +        found = False +        if record_type == dnsp.DNS_TYPE_A: +            if rec_match.data == data: +                found = True +        elif record_type == dnsp.DNS_TYPE_AAAA: +            if rec_match.data == data: +                found = True +        elif record_type == dnsp.DNS_TYPE_CNAME: +            if rec_match.data == data: +                found = True +        elif record_type == dnsp.DNS_TYPE_NS: +            if rec_match.data == data: +                found = True + +        if found: +            return rec_match + +    return None + + +class cmd_serverinfo(Command): +    """Query for Server information""" + +    synopsis = '%prog <server> [options]' + +    takes_args = [ 'server' ] + +    takes_options = [ +        Option('--client-version', help='Client Version', default='longhorn', +                choices=['w2k','dotnet','longhorn'], dest='cli_ver'), +    ] + +    def run(self, server, cli_ver, sambaopts=None, credopts=None, versionopts=None): +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        client_version = dns_client_version(cli_ver) + +        typeid, res = dns_conn.DnssrvQuery2(client_version, +                                            0, +                                            server, +                                            None, +                                            'ServerInfo') +        print_serverinfo(self.outf, typeid, res) + + +class cmd_zoneinfo(Command): +    """Query for zone information""" + +    synopsis = '%prog <server> <zone> [options]' + +    takes_args = [ 'server', 'zone' ] + +    takes_options = [ +        Option('--client-version', help='Client Version', default='longhorn', +                choices=['w2k','dotnet','longhorn'], dest='cli_ver'), +    ] + +    def run(self, server, zone, cli_ver, sambaopts=None, credopts=None, versionopts=None): +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        client_version = dns_client_version(cli_ver) + +        typeid, res = dns_conn.DnssrvQuery2(client_version, +                                            0, +                                            server, +                                            zone, +                                            'ZoneInfo') +        print_zoneinfo(self.outf, typeid, res) + + +class cmd_zonelist(Command): +    """Query for zones""" + +    synopsis = '%prog <server> [options]' + +    takes_args = [ 'server' ] + +    takes_options = [ +        Option('--client-version', help='Client Version', default='longhorn', +                choices=['w2k','dotnet','longhorn'], dest='cli_ver'), +        Option('--primary', help='List primary zones (default)', +                action='store_true', dest='primary'), +        Option('--secondary', help='List secondary zones', +                action='store_true', dest='secondary'), +        Option('--cache', help='List cached zones', +                action='store_true', dest='cache'), +        Option('--auto', help='List automatically created zones', +                action='store_true', dest='auto'), +        Option('--forward', help='List forward zones', +                action='store_true', dest='forward'), +        Option('--reverse', help='List reverse zones', +                action='store_true', dest='reverse'), +        Option('--ds', help='List directory integrated zones', +                action='store_true', dest='ds'), +        Option('--non-ds', help='List non-directory zones', +                action='store_true', dest='nonds') +    ] + +    def run(self, server, cli_ver, primary=False, secondary=False, cache=False, +                auto=False, forward=False, reverse=False, ds=False, nonds=False, +                sambaopts=None, credopts=None, versionopts=None): +        request_filter = 0 + +        if primary: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY +        if secondary: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY +        if cache: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE +        if auto: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO +        if forward: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD +        if reverse: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE +        if ds: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_DS +        if nonds: +            request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS + +        if request_filter == 0: +            request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        client_version = dns_client_version(cli_ver) + +        typeid, res = dns_conn.DnssrvComplexOperation2(client_version, +                                                        0, +                                                        server, +                                                        None, +                                                        'EnumZones', +                                                        dnsserver.DNSSRV_TYPEID_DWORD, +                                                        request_filter) + +        if client_version == dnsserver.DNS_CLIENT_VERSION_W2K: +            typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K +        else: +            typeid = dnsserver.DNSSRV_TYPEID_ZONE +        print_enumzones(self.outf, typeid, res) + + +class cmd_query(Command): +    """Query a name""" + +    synopsis = '%prog <server> <zone> <name> <type> [options]' + +    takes_args = [ 'server', 'zone', 'name', 'rtype' ] + +    takes_options = [ +        Option('--authority', help='Search authoritative records (default)', +                action='store_true', dest='authority'), +        Option('--cache', help='Search cached records', +                action='store_true', dest='cache'), +        Option('--glue', help='Search glue records', +                action='store_true', dest='glue'), +        Option('--root', help='Search root hints', +                action='store_true', dest='root'), +        Option('--additional', help='List additional records', +                action='store_true', dest='additional'), +        Option('--no-children', help='Do not list children', +                action='store_true', dest='no_children'), +        Option('--only-children', help='List only children', +                action='store_true', dest='only_children') +    ] + +    def run(self, server, zone, name, rtype, authority=False, cache=False, glue=False, +                root=False, additional=False, no_children=False, only_children=False, +                sambaopts=None, credopts=None, versionopts=None): +        record_type = dns_type_flag(rtype) + +        select_flags = 0 +        if authority: +            select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA +        if cache: +            select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA +        if glue: +            select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA +        if root: +            select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA +        if additional: +            select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA +        if no_children: +            select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN +        if only_children: +            select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN + +        if select_flags == 0: +            select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                                    0, +                                                    server, +                                                    zone, +                                                    name, +                                                    None, +                                                    record_type, +                                                    select_flags, +                                                    None, +                                                    None) +        print_dnsrecords(self.outf, res) + + +class cmd_roothints(Command): +    """Query root hints""" + +    synopsis = '%prog <server> [<name>] [options]' + +    takes_args = [ 'server', 'name?' ] + +    def run(self, server, name='.', sambaopts=None, credopts=None, versionopts=None): +        record_type = dnsp.DNS_TYPE_NS +        select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA | +                        dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA) + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                                    0, +                                                    server, +                                                    '..RootHints', +                                                    name, +                                                    None, +                                                    record_type, +                                                    select_flags, +                                                    None, +                                                    None) +        print_dnsrecords(self.outf, res) + + +class cmd_add_record(Command): +    """Add a DNS record""" + +    synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>' + +    takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ] + +    def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None): + +        record_type = dns_type_flag(rtype) + +        if record_type == dnsp.DNS_TYPE_A: +            rec = ARecord(data) +        elif record_type == dnsp.DNS_TYPE_AAAA: +            rec = AAAARecord(data) +        elif record_type == dnsp.DNS_TYPE_CNAME: +            rec = CNameRecord(data) +        elif record_type == dnsp.DNS_TYPE_NS: +            rec = NSRecord(data) +        else: +            raise CommandError('Adding record of type %s is not supported' % rtype) + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data) +        if rec_match is not None: +            raise CommandError('Record already exists') + +        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() +        add_rec_buf.rec = rec + +        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                        0, +                                        server, +                                        zone, +                                        name, +                                        add_rec_buf, +                                        None) +        self.outf.write('Record added succefully\n') + + +class cmd_update_record(Command): +    """Update a DNS record""" + +    synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <olddata> <newdata>' + +    takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ] + +    def run(self, server, zone, name, rtype, olddata, newdata, +                sambaopts=None, credopts=None, versionopts=None): + +        record_type = dns_type_flag(rtype) +        if record_type == dnsp.DNS_TYPE_A: +            rec = ARecord(newdata) +        elif record_type == dnsp.DNS_TYPE_AAAA: +            rec = AAAARecord(newdata) +        elif record_type == dnsp.DNS_TYPE_CNAME: +            rec = CNameRecord(newdata) +        elif record_type == dnsp.DNS_TYPE_NS: +            rec = NSRecord(newdata) +        else: +            raise CommandError('Updating record of type %s is not supported' % rtype) + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, olddata) +        if not rec_match: +            raise CommandError('Record does not exist') + +        # Copy properties from existing record to new record +        rec.dwFlags = rec_match.dwFlags +        rec.dwSerial = rec_match.dwSerial +        rec.dwTtlSeconds = rec_match.dwTtlSeconds +        rec.dwTimeStamp = rec_match.dwTimeStamp + +        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() +        add_rec_buf.rec = rec + +        del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() +        del_rec_buf.rec = rec_match + +        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                        0, +                                        server, +                                        zone, +                                        name, +                                        add_rec_buf, +                                        del_rec_buf) +        self.outf.write('Record updated succefully\n') + + +class cmd_delete_record(Command): +    """Delete a DNS record""" + +    synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>' + +    takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ] + +    def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None): + +        record_type = dns_type_flag(rtype) + +        if record_type == dnsp.DNS_TYPE_A: +            rec = ARecord(data) +        elif record_type == dnsp.DNS_TYPE_AAAA: +            rec = AAAARecord(data) +        elif record_type == dnsp.DNS_TYPE_CNAME: +            rec = CNameRecord(data) +        elif record_type == dnsp.DNS_TYPE_NS: +            rec = NSRecord(data) +        else: +            raise CommandError('Deleting record of type %s is not supported' % rtype) + +        self.lp = sambaopts.get_loadparm() +        self.creds = credopts.get_credentials(self.lp) +        dns_conn = dns_connect(server, self.lp, self.creds) + +        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data) +        if not rec_match: +            raise CommandError('Record does not exist') + +        del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() +        del_rec_buf.rec = rec_match + +        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, +                                        0, +                                        server, +                                        zone, +                                        name, +                                        None, +                                        del_rec_buf) +        self.outf.write('Record deleted succefully\n') + + +class cmd_dns(SuperCommand): +    """Domain Name Service (DNS) management""" + +    subcommands = {} +    subcommands['serverinfo'] = cmd_serverinfo() +    subcommands['zoneinfo'] = cmd_zoneinfo() +    subcommands['zonelist'] = cmd_zonelist() +    subcommands['query'] = cmd_query() +    subcommands['roothints'] = cmd_roothints() +    subcommands['add'] = cmd_add_record() +    subcommands['update'] = cmd_update_record() +    subcommands['delete'] = cmd_delete_record() diff --git a/source4/scripting/python/samba/netcmd/main.py b/source4/scripting/python/samba/netcmd/main.py index 657963208b..61bbcf16e2 100644 --- a/source4/scripting/python/samba/netcmd/main.py +++ b/source4/scripting/python/samba/netcmd/main.py @@ -22,6 +22,7 @@  from samba.netcmd import SuperCommand  from samba.netcmd.dbcheck import cmd_dbcheck  from samba.netcmd.delegation import cmd_delegation +from samba.netcmd.dns import cmd_dns  from samba.netcmd.domain import cmd_domain  from samba.netcmd.drs import cmd_drs  from samba.netcmd.dsacl import cmd_dsacl @@ -44,6 +45,7 @@ class cmd_sambatool(SuperCommand):      subcommands = {}      subcommands["dbcheck"] =  cmd_dbcheck()      subcommands["delegation"] = cmd_delegation() +    subcommands["dns"] = cmd_dns()      subcommands["domain"] = cmd_domain()      subcommands["drs"] = cmd_drs()      subcommands["dsacl"] = cmd_dsacl()  | 
