mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add a prototype client tool to configure a client of the IPA server
Right now it does only discovery (or fallback)
This commit is contained in:
26
Makefile
26
Makefile
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS=ipa-server ipa-admintools ipa-python
|
SUBDIRS=ipa-server ipa-admintools ipa-python ipa-client
|
||||||
|
|
||||||
PRJ_PREFIX=freeipa
|
PRJ_PREFIX=freeipa
|
||||||
|
|
||||||
@@ -31,6 +31,13 @@ PYTHON_VERSION=$(PYTHON_MAJOR).$(PYTHON_MINOR).$(PYTHON_RELEASE)
|
|||||||
PYTHON_TARBALL_PREFIX=$(PRJ_PREFIX)-python-$(PYTHON_VERSION)
|
PYTHON_TARBALL_PREFIX=$(PRJ_PREFIX)-python-$(PYTHON_VERSION)
|
||||||
PYTHON_TARBALL=$(PYTHON_TARBALL_PREFIX).tgz
|
PYTHON_TARBALL=$(PYTHON_TARBALL_PREFIX).tgz
|
||||||
|
|
||||||
|
CLI_MAJOR=0
|
||||||
|
CLI_MINOR=1
|
||||||
|
CLI_RELEASE=0
|
||||||
|
CLI_VERSION=$(CLI_MAJOR).$(CLI_MINOR).$(CLI_RELEASE)
|
||||||
|
CLI_TARBALL_PREFIX=$(PRJ_PREFIX)-client-$(CLI_VERSION)
|
||||||
|
CLI_TARBALL=$(CLI_TARBALL_PREFIX).tgz
|
||||||
|
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
export CFLAGS = -g -Wall -Wshadow
|
export CFLAGS = -g -Wall -Wshadow
|
||||||
export LDFLAGS = -g
|
export LDFLAGS = -g
|
||||||
@@ -63,6 +70,9 @@ version-update:
|
|||||||
sed s/VERSION/$(PYTHON_VERSION)/ ipa-python/freeipa-python.spec.in \
|
sed s/VERSION/$(PYTHON_VERSION)/ ipa-python/freeipa-python.spec.in \
|
||||||
> ipa-python/freeipa-python.spec
|
> ipa-python/freeipa-python.spec
|
||||||
|
|
||||||
|
sed s/VERSION/$(CLI_VERSION)/ ipa-client/freeipa-client.spec.in \
|
||||||
|
> ipa-client/freeipa-client.spec
|
||||||
|
|
||||||
|
|
||||||
archive:
|
archive:
|
||||||
-mkdir -p dist
|
-mkdir -p dist
|
||||||
@@ -96,6 +106,12 @@ tarballs:
|
|||||||
cd dist; tar cfz $(PYTHON_TARBALL) $(PYTHON_TARBALL_PREFIX)
|
cd dist; tar cfz $(PYTHON_TARBALL) $(PYTHON_TARBALL_PREFIX)
|
||||||
rm -fr dist/$(PYTHON_TARBALL_PREFIX)
|
rm -fr dist/$(PYTHON_TARBALL_PREFIX)
|
||||||
|
|
||||||
|
# ipa-client
|
||||||
|
mv dist/freeipa/ipa-client dist/$(CLI_TARBALL_PREFIX)
|
||||||
|
rm -f dist/$(CLI_TARBALL)
|
||||||
|
cd dist; tar cfz $(CLI_TARBALL) $(CLI_TARBALL_PREFIX)
|
||||||
|
rm -fr dist/$(CLI_TARBALL_PREFIX)
|
||||||
|
|
||||||
rpmroot:
|
rpmroot:
|
||||||
mkdir -p $(RPMBUILD)/BUILD
|
mkdir -p $(RPMBUILD)/BUILD
|
||||||
mkdir -p $(RPMBUILD)/RPMS
|
mkdir -p $(RPMBUILD)/RPMS
|
||||||
@@ -121,7 +137,13 @@ rpm-ipa-python:
|
|||||||
cp rpmbuild/RPMS/noarch/$(PRJ_PREFIX)-python-$(PYTHON_VERSION)-*.rpm dist/.
|
cp rpmbuild/RPMS/noarch/$(PRJ_PREFIX)-python-$(PYTHON_VERSION)-*.rpm dist/.
|
||||||
cp rpmbuild/SRPMS/$(PRJ_PREFIX)-python-$(PYTHON_VERSION)-*.src.rpm dist/.
|
cp rpmbuild/SRPMS/$(PRJ_PREFIX)-python-$(PYTHON_VERSION)-*.src.rpm dist/.
|
||||||
|
|
||||||
rpms: rpmroot rpm-ipa-server rpm-ipa-admin rpm-ipa-python
|
rpm-ipa-client:
|
||||||
|
cp dist/$(CLI_TARBALL) $(RPMBUILD)/SOURCES/.
|
||||||
|
rpmbuild --define "_topdir $(RPMBUILD)" -ba ipa-client/freeipa-client.spec
|
||||||
|
cp rpmbuild/RPMS/*/$(PRJ_PREFIX)-client-$(CLI_VERSION)-*.rpm dist/.
|
||||||
|
cp rpmbuild/SRPMS/$(PRJ_PREFIX)-client-$(CLI_VERSION)-*.src.rpm dist/.
|
||||||
|
|
||||||
|
rpms: rpmroot rpm-ipa-server rpm-ipa-admin rpm-ipa-python rpm-ipa-client
|
||||||
|
|
||||||
dist: version-update archive tarballs archive-cleanup rpms
|
dist: version-update archive tarballs archive-cleanup rpms
|
||||||
|
|
||||||
|
|||||||
23
ipa-client/Makefile
Normal file
23
ipa-client/Makefile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
SUBDIRS=ipa-install
|
||||||
|
PYTHONDIR=$(DESTDIR)/usr/share/ipa/ipaclient
|
||||||
|
|
||||||
|
all:
|
||||||
|
@for subdir in $(SUBDIRS); do \
|
||||||
|
(cd $$subdir && $(MAKE) $@) || exit 1; \
|
||||||
|
done
|
||||||
|
|
||||||
|
install-ipaclient:
|
||||||
|
-mkdir -p $(PYTHONDIR)
|
||||||
|
install -m 644 ipaclient/*.py $(PYTHONDIR)
|
||||||
|
|
||||||
|
install: install-ipaclient
|
||||||
|
@for subdir in $(SUBDIRS); do \
|
||||||
|
(cd $$subdir && $(MAKE) $@) || exit 1; \
|
||||||
|
done
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@for subdir in $(SUBDIRS); do \
|
||||||
|
(cd $$subdir && $(MAKE) $@) || exit 1; \
|
||||||
|
done
|
||||||
|
rm -f *~
|
||||||
|
rm -f ipaclient/*~
|
||||||
47
ipa-client/freeipa-client.spec
Executable file
47
ipa-client/freeipa-client.spec
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
Name: freeipa-client
|
||||||
|
Version: 0.1.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: FreeIPA client
|
||||||
|
|
||||||
|
Group: System Environment/Base
|
||||||
|
License: GPL
|
||||||
|
URL: http://www.freeipa.org
|
||||||
|
Source0: %{name}-%{version}.tgz
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
|
|
||||||
|
Requires: python python-ldap freeipa-python
|
||||||
|
|
||||||
|
%description
|
||||||
|
FreeIPA is a server for identity, policy, and audit.
|
||||||
|
The client package provide install and configuration scripts for clients.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q
|
||||||
|
|
||||||
|
%build
|
||||||
|
|
||||||
|
make DESTDIR=%{buildroot}
|
||||||
|
|
||||||
|
%install
|
||||||
|
rm -rf %{buildroot}
|
||||||
|
mkdir -p %{buildroot}%{_sbindir}
|
||||||
|
|
||||||
|
make install DESTDIR=%{buildroot}
|
||||||
|
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf %{buildroot}
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_sbindir}/ipa-client-install
|
||||||
|
|
||||||
|
%dir %{_usr}/share/ipa
|
||||||
|
%{_usr}/share/ipa/*
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu Aug 16 2007 Simo Sorce <ssorce@redhat.com> - 0.1.0-1
|
||||||
|
- Initial rpm version
|
||||||
|
|
||||||
|
|
||||||
47
ipa-client/freeipa-client.spec.in
Normal file
47
ipa-client/freeipa-client.spec.in
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
Name: freeipa-client
|
||||||
|
Version: VERSION
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: FreeIPA client
|
||||||
|
|
||||||
|
Group: System Environment/Base
|
||||||
|
License: GPL
|
||||||
|
URL: http://www.freeipa.org
|
||||||
|
Source0: %{name}-%{version}.tgz
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
|
|
||||||
|
Requires: python python-ldap freeipa-python
|
||||||
|
|
||||||
|
%description
|
||||||
|
FreeIPA is a server for identity, policy, and audit.
|
||||||
|
The client package provide install and configuration scripts for clients.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q
|
||||||
|
|
||||||
|
%build
|
||||||
|
|
||||||
|
make DESTDIR=%{buildroot}
|
||||||
|
|
||||||
|
%install
|
||||||
|
rm -rf %{buildroot}
|
||||||
|
mkdir -p %{buildroot}%{_sbindir}
|
||||||
|
|
||||||
|
make install DESTDIR=%{buildroot}
|
||||||
|
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf %{buildroot}
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_sbindir}/ipa-client-install
|
||||||
|
|
||||||
|
%dir %{_usr}/share/ipa
|
||||||
|
%{_usr}/share/ipa/*
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu Aug 16 2007 Simo Sorce <ssorce@redhat.com> - 0.1.0-1
|
||||||
|
- Initial rpm version
|
||||||
|
|
||||||
|
|
||||||
10
ipa-client/ipa-install/Makefile
Normal file
10
ipa-client/ipa-install/Makefile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
SBINDIR=$(DESTDIR)/usr/sbin
|
||||||
|
|
||||||
|
all: ;
|
||||||
|
|
||||||
|
install:
|
||||||
|
-mkdir $(SBINDIR)
|
||||||
|
install -m 755 ipa-client-install $(SBINDIR)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.pyc
|
||||||
109
ipa-client/ipa-install/ipa-client-install
Normal file
109
ipa-client/ipa-install/ipa-client-install
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#! /usr/bin/python -E
|
||||||
|
# Authors: Simo Sorce <ssorce@redhat.com>
|
||||||
|
# Karl MacMillan <kmacmillan@mentalrootkit.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# 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; version 2 only
|
||||||
|
#
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
VERSION = "%prog .1"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append("/usr/share/ipa")
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import logging
|
||||||
|
from optparse import OptionParser
|
||||||
|
import ipaclient.ipadiscovery
|
||||||
|
from ipaserver.util import run
|
||||||
|
|
||||||
|
def parse_options():
|
||||||
|
parser = OptionParser(version=VERSION)
|
||||||
|
parser.add_option("--domain", dest="domain", help="domain name")
|
||||||
|
parser.add_option("--server", dest="server", help="IPA server")
|
||||||
|
parser.add_option("--realm", dest="realm_name", help="realm name")
|
||||||
|
parser.add_option("-d", "--debug", dest="debug", action="store_true",
|
||||||
|
dest="debug", default=False, help="print debugging information")
|
||||||
|
parser.add_option("-u", "--unattended", dest="unattended",
|
||||||
|
help="unattended installation never prompts the user")
|
||||||
|
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
def logging_setup(options):
|
||||||
|
# Always log everything (i.e., DEBUG) to the log
|
||||||
|
# file.
|
||||||
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
|
format='%(asctime)s %(levelname)s %(message)s',
|
||||||
|
filename='ipaclient-install.log',
|
||||||
|
filemode='w')
|
||||||
|
|
||||||
|
console = logging.StreamHandler()
|
||||||
|
# If the debug option is set, also log debug messages to the console
|
||||||
|
if options.debug:
|
||||||
|
console.setLevel(logging.DEBUG)
|
||||||
|
else:
|
||||||
|
# Otherwise, log critical and error messages
|
||||||
|
console.setLevel(logging.ERROR)
|
||||||
|
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
|
||||||
|
console.setFormatter(formatter)
|
||||||
|
logging.getLogger('').addHandler(console)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
options = parse_options()
|
||||||
|
logging_setup(options)
|
||||||
|
|
||||||
|
# Create the discovery instance
|
||||||
|
ds = ipaclient.ipadiscovery.IPADiscovery()
|
||||||
|
|
||||||
|
ret = ds.search()
|
||||||
|
if ret == -10:
|
||||||
|
print "Can't get the fully qualified name of this host"
|
||||||
|
print "Please check that the client is properly configured"
|
||||||
|
return ret
|
||||||
|
if ret == -1:
|
||||||
|
logging.debug("Domain not found")
|
||||||
|
if options.domain:
|
||||||
|
dom = options.domain
|
||||||
|
elif options.unattended:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
print "Failed to determine your DNS domain (DNS misconfigured?)"
|
||||||
|
dom = raw_input("Please provide your domain name (ex: example.com):")
|
||||||
|
ret = ds.search(domain=dom)
|
||||||
|
if ret == -2:
|
||||||
|
logging.debug("IPA Server not found")
|
||||||
|
if options.server:
|
||||||
|
srv = options.server
|
||||||
|
elif options.unattended:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
print "Failed to find the IPA Server (DNS misconfigured?)"
|
||||||
|
srv = raw_input("Please provide your server name (ex: ipa.example.com):")
|
||||||
|
ret = ds.search(domain=dom, server=srv)
|
||||||
|
if ret != 0:
|
||||||
|
print "Failed to verify that "+srv+" is an IPA Server, aborting!"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
print "Discovery was successful!"
|
||||||
|
print "Realm: "+ds.getRealmName()
|
||||||
|
print "DNS Domain: "+ds.getDomainName()
|
||||||
|
print "IPA Server: "+ds.getServerName()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
main()
|
||||||
23
ipa-client/ipaclient/__init__.py
Normal file
23
ipa-client/ipaclient/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#! /usr/bin/python -E
|
||||||
|
# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
|
||||||
|
# see inline
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# 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; version 2 or later
|
||||||
|
#
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
__all__ = ["ipadiscovery"]
|
||||||
|
|
||||||
445
ipa-client/ipaclient/dnsclient.py
Normal file
445
ipa-client/ipaclient/dnsclient.py
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2001, 2005 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This 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.
|
||||||
|
#
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import acutil
|
||||||
|
|
||||||
|
DNS_C_IN = 1
|
||||||
|
DNS_C_CS = 2
|
||||||
|
DNS_C_CHAOS = 3
|
||||||
|
DNS_C_HS = 4
|
||||||
|
DNS_C_ANY = 255
|
||||||
|
|
||||||
|
DNS_T_A = 1
|
||||||
|
DNS_T_NS = 2
|
||||||
|
DNS_T_CNAME = 5
|
||||||
|
DNS_T_SOA = 6
|
||||||
|
DNS_T_NULL = 10
|
||||||
|
DNS_T_WKS = 11
|
||||||
|
DNS_T_PTR = 12
|
||||||
|
DNS_T_HINFO = 13
|
||||||
|
DNS_T_MX = 15
|
||||||
|
DNS_T_TXT = 16
|
||||||
|
DNS_T_SRV = 33
|
||||||
|
DNS_T_ANY = 255
|
||||||
|
|
||||||
|
DEBUG_DNSCLIENT = False
|
||||||
|
|
||||||
|
class DNSQueryHeader:
|
||||||
|
FORMAT = "!HBBHHHH"
|
||||||
|
def __init__(self):
|
||||||
|
self.dns_id = 0
|
||||||
|
self.dns_rd = 0
|
||||||
|
self.dns_tc = 0
|
||||||
|
self.dns_aa = 0
|
||||||
|
self.dns_opcode = 0
|
||||||
|
self.dns_qr = 0
|
||||||
|
self.dns_rcode = 0
|
||||||
|
self.dns_z = 0
|
||||||
|
self.dns_ra = 0
|
||||||
|
self.dns_qdcount = 0
|
||||||
|
self.dns_ancount = 0
|
||||||
|
self.dns_nscount = 0
|
||||||
|
self.dns_arcount = 0
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
return struct.pack(DNSQueryHeader.FORMAT,
|
||||||
|
self.dns_id,
|
||||||
|
(self.dns_rd & 1) |
|
||||||
|
(self.dns_tc & 1) << 1 |
|
||||||
|
(self.dns_aa & 1) << 2 |
|
||||||
|
(self.dns_opcode & 15) << 3 |
|
||||||
|
(self.dns_qr & 1) << 7,
|
||||||
|
(self.dns_rcode & 15) |
|
||||||
|
(self.dns_z & 7) << 4 |
|
||||||
|
(self.dns_ra & 1) << 7,
|
||||||
|
self.dns_qdcount,
|
||||||
|
self.dns_ancount,
|
||||||
|
self.dns_nscount,
|
||||||
|
self.dns_arcount)
|
||||||
|
|
||||||
|
def unpack(self, data):
|
||||||
|
(self.dns_id, byte1, byte2, self.dns_qdcount, self.dns_ancount,
|
||||||
|
self.dns_nscount, self.dns_arcount) = struct.unpack(DNSQueryHeader.FORMAT, data[0:self.size()])
|
||||||
|
self.dns_rd = byte1 & 1
|
||||||
|
self.dns_tc = (byte1 >> 1) & 1
|
||||||
|
self.dns_aa = (byte1 >> 2) & 1
|
||||||
|
self.dns_opcode = (byte1 >> 3) & 15
|
||||||
|
self.dns_qr = (byte1 >> 7) & 1
|
||||||
|
self.dns_rcode = byte2 & 15
|
||||||
|
self.dns_z = (byte2 >> 4) & 7
|
||||||
|
self.dns_ra = (byte1 >> 7) & 1
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return struct.calcsize(DNSQueryHeader.FORMAT)
|
||||||
|
|
||||||
|
def unpackQueryHeader(data):
|
||||||
|
header = DNSQueryHeader()
|
||||||
|
header.unpack(data)
|
||||||
|
return header
|
||||||
|
|
||||||
|
class DNSResult:
|
||||||
|
FORMAT = "!HHIH"
|
||||||
|
QFORMAT = "!HH"
|
||||||
|
def __init__(self):
|
||||||
|
self.dns_name = ""
|
||||||
|
self.dns_type = 0
|
||||||
|
self.dns_class = 0
|
||||||
|
self.dns_ttl = 0
|
||||||
|
self.dns_rlength = 0
|
||||||
|
self.rdata = None
|
||||||
|
|
||||||
|
def unpack(self, data):
|
||||||
|
(self.dns_type, self.dns_class, self.dns_ttl,
|
||||||
|
self.dns_rlength) = struct.unpack(DNSResult.FORMAT, data[0:self.size()])
|
||||||
|
|
||||||
|
def qunpack(self, data):
|
||||||
|
(self.dns_type, self.dns_class) = struct.unpack(DNSResult.QFORMAT, data[0:self.qsize()])
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return struct.calcsize(DNSResult.FORMAT)
|
||||||
|
|
||||||
|
def qsize(self):
|
||||||
|
return struct.calcsize(DNSResult.QFORMAT)
|
||||||
|
|
||||||
|
class DNSRData:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#typedef struct dns_rr_a {
|
||||||
|
# u_int32_t address;
|
||||||
|
#} dns_rr_a_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_cname {
|
||||||
|
# const char *cname;
|
||||||
|
#} dns_rr_cname_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_hinfo {
|
||||||
|
# const char *cpu, *os;
|
||||||
|
#} dns_rr_hinfo_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_mx {
|
||||||
|
# u_int16_t preference;
|
||||||
|
# const char *exchange;
|
||||||
|
#} dns_rr_mx_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_null {
|
||||||
|
# unsigned const char *data;
|
||||||
|
#} dns_rr_null_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_ns {
|
||||||
|
# const char *nsdname;
|
||||||
|
#} dns_rr_ns_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_ptr {
|
||||||
|
# const char *ptrdname;
|
||||||
|
#} dns_rr_ptr_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_soa {
|
||||||
|
# const char *mname;
|
||||||
|
# const char *rname;
|
||||||
|
# u_int32_t serial;
|
||||||
|
# int32_t refresh;
|
||||||
|
# int32_t retry;
|
||||||
|
# int32_t expire;
|
||||||
|
# int32_t minimum;
|
||||||
|
#} dns_rr_soa_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_txt {
|
||||||
|
# const char *data;
|
||||||
|
#} dns_rr_txt_t;
|
||||||
|
#
|
||||||
|
#typedef struct dns_rr_srv {
|
||||||
|
# const char *server;
|
||||||
|
# u_int16_t priority;
|
||||||
|
# u_int16_t weight;
|
||||||
|
# u_int16_t port;
|
||||||
|
#} dns_rr_srv_t;
|
||||||
|
|
||||||
|
def dnsNameToLabel(name):
|
||||||
|
out = ""
|
||||||
|
name = name.split(".")
|
||||||
|
for part in name:
|
||||||
|
out += chr(len(part)) + part
|
||||||
|
return out
|
||||||
|
|
||||||
|
def dnsFormatQuery(query, qclass, qtype):
|
||||||
|
header = DNSQueryHeader()
|
||||||
|
|
||||||
|
header.dns_id = 0 # FIXME: id = 0
|
||||||
|
header.dns_rd = 1 # don't know why the original code didn't request recursion for non SOA requests
|
||||||
|
header.dns_qr = 0 # query
|
||||||
|
header.dns_opcode = 0 # standard query
|
||||||
|
header.dns_qdcount = 1 # single query
|
||||||
|
|
||||||
|
qlabel = dnsNameToLabel(query)
|
||||||
|
if not qlabel:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
out = header.pack() + qlabel
|
||||||
|
out += chr(qtype >> 8)
|
||||||
|
out += chr(qtype & 0xff)
|
||||||
|
out += chr(qclass >> 8)
|
||||||
|
out += chr(qclass & 0xff)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def dnsParseLabel(label, base):
|
||||||
|
# returns (output, rest)
|
||||||
|
if not label:
|
||||||
|
return ("", None)
|
||||||
|
|
||||||
|
update = 1
|
||||||
|
rest = label
|
||||||
|
output = ""
|
||||||
|
skip = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
while ord(rest[0]):
|
||||||
|
if ord(rest[0]) & 0xc0:
|
||||||
|
rest = base[((ord(rest[0]) & 0x3f) << 8) + ord(rest[1]):]
|
||||||
|
if update:
|
||||||
|
skip += 2
|
||||||
|
update = 0
|
||||||
|
continue
|
||||||
|
output += rest[1:ord(rest[0]) + 1] + "."
|
||||||
|
if update:
|
||||||
|
skip += ord(rest[0]) + 1
|
||||||
|
rest = rest[ord(rest[0]) + 1:]
|
||||||
|
except IndexError:
|
||||||
|
return ("", None)
|
||||||
|
return (label[skip+update:], output)
|
||||||
|
|
||||||
|
def dnsParseA(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
if len(data) < 4:
|
||||||
|
rdata.address = 0
|
||||||
|
return None
|
||||||
|
|
||||||
|
rdata.address = (ord(data[0])<<24) | (ord(data[1])<<16) | (ord(data[2])<<8) | (ord(data[3])<<0)
|
||||||
|
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "A = %d.%d.%d.%d." % (ord(data[0]), ord(data[1]), ord(data[2]), ord(data[3]))
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseText(data):
|
||||||
|
if len(data) < 1:
|
||||||
|
return ("", None)
|
||||||
|
tlen = ord(data[0])
|
||||||
|
if len(data) < tlen + 1:
|
||||||
|
return ("", None)
|
||||||
|
return (data[tlen+1:], data[1:tlen+1])
|
||||||
|
|
||||||
|
def dnsParseNS(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
(rest, rdata.nsdname) = dnsParseLabel(data, base)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "NS DNAME = \"%s\"." % (rdata.nsdname)
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseCNAME(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
(rest, rdata.cname) = dnsParseLabel(data, base)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "CNAME = \"%s\"." % (rdata.cname)
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseSOA(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
format = "!IIIII"
|
||||||
|
|
||||||
|
(rest, rdata.mname) = dnsParseLabel(data, base)
|
||||||
|
if rdata.mname is None:
|
||||||
|
return None
|
||||||
|
(rest, rdata.rname) = dnsParseLabel(rest, base)
|
||||||
|
if rdata.rname is None:
|
||||||
|
return None
|
||||||
|
if len(rest) < struct.calcsize(format):
|
||||||
|
return None
|
||||||
|
|
||||||
|
(rdata.serial, rdata.refresh, rdata.retry, rdata.expire,
|
||||||
|
rdata.minimum) = struct.unpack(format, rest[:struct.calcsize(format)])
|
||||||
|
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "SOA(mname) = \"%s\"." % rdata.mname
|
||||||
|
print "SOA(rname) = \"%s\"." % rdata.rname
|
||||||
|
print "SOA(serial) = %d." % rdata.serial
|
||||||
|
print "SOA(refresh) = %d." % rdata.refresh
|
||||||
|
print "SOA(retry) = %d." % rdata.retry
|
||||||
|
print "SOA(expire) = %d." % rdata.expire
|
||||||
|
print "SOA(minimum) = %d." % rdata.minimum
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseNULL(data, base):
|
||||||
|
# um, yeah
|
||||||
|
return None
|
||||||
|
|
||||||
|
def dnsParseWKS(data, base):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def dnsParseHINFO(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
(rest, rdata.cpu) = dnsParseText(data)
|
||||||
|
if rest:
|
||||||
|
(rest, rdata.os) = dnsParseText(rest)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "HINFO(cpu) = \"%s\"." % rdata.cpu
|
||||||
|
print "HINFO(os) = \"%s\"." % rdata.os
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseMX(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
if len(data) < 2:
|
||||||
|
return None
|
||||||
|
rdata.preference = (ord(data[0]) << 8) | ord(data[1])
|
||||||
|
(rest, rdata.exchange) = dnsParseLabel(data[2:], base)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "MX(exchanger) = \"%s\"." % rdata.exchange
|
||||||
|
print "MX(preference) = %d." % rdata.preference
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseTXT(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
(rest, rdata.data) = dnsParseText(data)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "TXT = \"%s\"." % rdata.data
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParsePTR(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
(rest, rdata.ptrdname) = dnsParseLabel(data, base)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "PTR = \"%s\"." % rdata.ptrdname
|
||||||
|
|
||||||
|
def dnsParseSRV(data, base):
|
||||||
|
rdata = DNSRData()
|
||||||
|
format = "!HHH"
|
||||||
|
flen = struct.calcsize(format)
|
||||||
|
if len(data) < flen:
|
||||||
|
return None
|
||||||
|
|
||||||
|
(rdata.priority, rdata.weight, rdata.port) = struct.unpack(format, data[:flen])
|
||||||
|
(rest, rdata.server) = dnsParseLabel(data[flen:], base)
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "SRV(server) = \"%s\"." % rdata.server
|
||||||
|
print "SRV(weight) = %d." % rdata.weight
|
||||||
|
print "SRV(priority) = %d." % rdata.priority
|
||||||
|
print "SRV(port) = %d." % rdata.port
|
||||||
|
return rdata
|
||||||
|
|
||||||
|
def dnsParseResults(results):
|
||||||
|
try:
|
||||||
|
header = unpackQueryHeader(results)
|
||||||
|
except struct.error:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if header.dns_qr != 1: # should be a response
|
||||||
|
return []
|
||||||
|
|
||||||
|
if header.dns_rcode != 0: # should be no error
|
||||||
|
return []
|
||||||
|
|
||||||
|
rest = results[header.size():]
|
||||||
|
|
||||||
|
rrlist = []
|
||||||
|
|
||||||
|
for i in xrange(header.dns_qdcount):
|
||||||
|
if not rest:
|
||||||
|
return []
|
||||||
|
|
||||||
|
rr = DNSResult()
|
||||||
|
|
||||||
|
(rest, label) = dnsParseLabel(rest, results)
|
||||||
|
if label is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if len(rest) < rr.qsize():
|
||||||
|
return []
|
||||||
|
|
||||||
|
rr.qunpack(rest)
|
||||||
|
|
||||||
|
rest = rest[rr.qsize():]
|
||||||
|
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "Queried for '%s', class = %d, type = %d." % (label,
|
||||||
|
rr.dns_class, rr.dns_type)
|
||||||
|
|
||||||
|
for i in xrange(header.dns_ancount + header.dns_nscount + header.dns_arcount):
|
||||||
|
(rest, label) = dnsParseLabel(rest, results)
|
||||||
|
if label is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
rr = DNSResult()
|
||||||
|
|
||||||
|
rr.dns_name = label
|
||||||
|
|
||||||
|
if len(rest) < rr.size():
|
||||||
|
return []
|
||||||
|
|
||||||
|
rr.unpack(rest)
|
||||||
|
|
||||||
|
rest = rest[rr.size():]
|
||||||
|
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "Answer %d for '%s', class = %d, type = %d, ttl = %d." % (i,
|
||||||
|
rr.dns_name, rr.dns_class, rr.dns_type,
|
||||||
|
rr.dns_ttl)
|
||||||
|
|
||||||
|
if len(rest) < rr.dns_rlength:
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "Answer too short."
|
||||||
|
return []
|
||||||
|
|
||||||
|
fmap = { DNS_T_A: dnsParseA, DNS_T_NS: dnsParseNS,
|
||||||
|
DNS_T_CNAME: dnsParseCNAME, DNS_T_SOA: dnsParseSOA,
|
||||||
|
DNS_T_NULL: dnsParseNULL, DNS_T_WKS: dnsParseWKS,
|
||||||
|
DNS_T_PTR: dnsParsePTR, DNS_T_HINFO: dnsParseHINFO,
|
||||||
|
DNS_T_MX: dnsParseMX, DNS_T_TXT: dnsParseTXT,
|
||||||
|
DNS_T_SRV: dnsParseSRV}
|
||||||
|
|
||||||
|
if not rr.dns_type in fmap:
|
||||||
|
if DEBUG_DNSCLIENT:
|
||||||
|
print "Don't know how to parse RR type %d!" % rr.dns_type
|
||||||
|
else:
|
||||||
|
rr.rdata = fmap[rr.dns_type](rest[:rr.dns_rlength], results)
|
||||||
|
|
||||||
|
rest = rest[rr.dns_rlength:]
|
||||||
|
rrlist += [rr]
|
||||||
|
|
||||||
|
if not rrlist:
|
||||||
|
rrlist = [rr]
|
||||||
|
return rrlist
|
||||||
|
|
||||||
|
def query(query, qclass, qtype):
|
||||||
|
qdata = dnsFormatQuery(query, qclass, qtype)
|
||||||
|
if not qdata:
|
||||||
|
return []
|
||||||
|
answer = acutil.res_send(qdata)
|
||||||
|
if not answer:
|
||||||
|
return []
|
||||||
|
return dnsParseResults(answer)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
DEBUG_DNSCLIENT = True
|
||||||
|
print "Sending query."
|
||||||
|
rr = query(len(sys.argv) > 1 and sys.argv[1] or "devserv.devel.redhat.com.",
|
||||||
|
DNS_C_IN, DNS_T_ANY)
|
||||||
|
sys.exit(0)
|
||||||
239
ipa-client/ipaclient/ipadiscovery.py
Normal file
239
ipa-client/ipaclient/ipadiscovery.py
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
#! /usr/bin/python -E
|
||||||
|
# Authors: Simo Sorce <ssorce@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# 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; version 2 or later
|
||||||
|
#
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import logging
|
||||||
|
import dnsclient
|
||||||
|
import ldap
|
||||||
|
from ldap import LDAPError
|
||||||
|
|
||||||
|
class IPADiscovery:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.realm = None
|
||||||
|
self.domain = None
|
||||||
|
self.server = None
|
||||||
|
|
||||||
|
def getServerName(self):
|
||||||
|
return str(self.server)
|
||||||
|
|
||||||
|
def getDomainName(self):
|
||||||
|
return str(self.domain)
|
||||||
|
|
||||||
|
def getRealmName(self):
|
||||||
|
return str(self.realm)
|
||||||
|
|
||||||
|
def search(self, domain = "", server = ""):
|
||||||
|
hostname = ""
|
||||||
|
qname = ""
|
||||||
|
results = []
|
||||||
|
result = []
|
||||||
|
krbret = []
|
||||||
|
ldapret = []
|
||||||
|
|
||||||
|
if not server:
|
||||||
|
|
||||||
|
if not domain: #domain not provided do full DNS discovery
|
||||||
|
|
||||||
|
# get the local host name
|
||||||
|
hostname = socket.getfqdn()
|
||||||
|
if not hostname:
|
||||||
|
return -10 #bad host configuration
|
||||||
|
|
||||||
|
# first, check for an LDAP server for the local domain
|
||||||
|
p = hostname.find(".")
|
||||||
|
if p == -1: #no domain name
|
||||||
|
return -1
|
||||||
|
domain = hostname[p+1:]
|
||||||
|
|
||||||
|
while not self.server:
|
||||||
|
logging.debug("[ipadnssearchldap("+domain+")]")
|
||||||
|
self.server = self.ipadnssearchldap(domain)
|
||||||
|
if self.server:
|
||||||
|
self.domain = domain
|
||||||
|
else:
|
||||||
|
p = domain.find(".")
|
||||||
|
if p == -1: #no ldap server found and last component of the domain already tested
|
||||||
|
return -1
|
||||||
|
domain = domain[p+1:]
|
||||||
|
else:
|
||||||
|
logging.debug("[ipadnssearchldap]")
|
||||||
|
self.server = self.ipadnssearchldap(domain)
|
||||||
|
if self.server:
|
||||||
|
self.domain = domain
|
||||||
|
else:
|
||||||
|
return -2 #no ldap server found
|
||||||
|
|
||||||
|
|
||||||
|
#search for kerberos TODO: move this after ipacheckldap()
|
||||||
|
logging.debug("[ipadnssearchkrb]")
|
||||||
|
krbret = self.ipadnssearchkrb(self.domain)
|
||||||
|
if not krbret:
|
||||||
|
return -3 #no krb server found
|
||||||
|
|
||||||
|
self.realm = krbret[0]
|
||||||
|
|
||||||
|
else: #server forced on us, this means DNS doesn't work :/
|
||||||
|
|
||||||
|
self.domain = domain
|
||||||
|
self.server = server
|
||||||
|
|
||||||
|
logging.debug("[ipacheckldap]")
|
||||||
|
# check ldap now
|
||||||
|
ldapret = self.ipacheckldap(self.server, self.realm);
|
||||||
|
|
||||||
|
if not ldapret:
|
||||||
|
return -4 # not an IPA server (or broken config)
|
||||||
|
|
||||||
|
self.server = ldapret[0]
|
||||||
|
self.realm = ldapret[1]
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def ipacheckldap(self, thost, trealm):
|
||||||
|
|
||||||
|
lret = []
|
||||||
|
lres = []
|
||||||
|
lattr = ""
|
||||||
|
linfo = ""
|
||||||
|
lrealms = []
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
#now verify the server is really an IPA server
|
||||||
|
try:
|
||||||
|
logging.debug("Init ldap with: ldap://"+thost+":389")
|
||||||
|
lh = ldap.initialize("ldap://"+thost+":389")
|
||||||
|
lh.simple_bind_s("","")
|
||||||
|
|
||||||
|
logging.debug("Search rootdse")
|
||||||
|
lret = lh.search_s("", ldap.SCOPE_BASE, "(objectClass=*)")
|
||||||
|
for lattr in lret[0][1]:
|
||||||
|
if lattr.lower() == "namingcontexts":
|
||||||
|
lbase = lret[0][1][lattr][0]
|
||||||
|
|
||||||
|
logging.debug("Search for (info=*) in "+lbase+"(base)")
|
||||||
|
lret = lh.search_s(lbase, ldap.SCOPE_BASE, "(info=IPA*)")
|
||||||
|
if not lret:
|
||||||
|
return []
|
||||||
|
logging.debug("Found: "+str(lret))
|
||||||
|
|
||||||
|
for lattr in lret[0][1]:
|
||||||
|
if lattr.lower() == "info":
|
||||||
|
linfo = lret[0][1][lattr][0].lower()
|
||||||
|
break
|
||||||
|
|
||||||
|
if not linfo:
|
||||||
|
return []
|
||||||
|
|
||||||
|
#search and return known realms
|
||||||
|
logging.debug("Search for (objectClass=krbRealmContainer) in "+lbase+"(sub)")
|
||||||
|
lret = lh.search_s("cn=kerberos,"+lbase, ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
|
||||||
|
if not lret:
|
||||||
|
#something very wrong
|
||||||
|
return []
|
||||||
|
logging.debug("Found: "+str(lret))
|
||||||
|
|
||||||
|
for lres in lret:
|
||||||
|
for lattr in lres[1]:
|
||||||
|
if lattr.lower() == "cn":
|
||||||
|
lrealms.append(lres[1][lattr][0])
|
||||||
|
|
||||||
|
|
||||||
|
if trealm:
|
||||||
|
for r in lrealms:
|
||||||
|
if trealm == r:
|
||||||
|
return [thost, trealm]
|
||||||
|
# must match or something is very wrong
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
if len(lrealms) != 1:
|
||||||
|
#which one? we can't attach to a multi-realm server without DNS working
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return [thost, lrealms[0]]
|
||||||
|
|
||||||
|
#we shouldn't get here
|
||||||
|
return []
|
||||||
|
|
||||||
|
except LDAPError, err:
|
||||||
|
#no good
|
||||||
|
logging.error("Ldap Error: "+str(err))
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def ipadnssearchldap(self, tdomain):
|
||||||
|
servers = ""
|
||||||
|
rserver = ""
|
||||||
|
|
||||||
|
qname = "_ldap._tcp."+tdomain
|
||||||
|
# terminate the name
|
||||||
|
if not qname.endswith("."):
|
||||||
|
qname += "."
|
||||||
|
results = dnsclient.query(qname, dnsclient.DNS_C_IN, dnsclient.DNS_T_SRV)
|
||||||
|
|
||||||
|
for result in results:
|
||||||
|
if result.dns_type == dnsclient.DNS_T_SRV:
|
||||||
|
rserver = result.rdata.server.rstrip(".")
|
||||||
|
if result.rdata.port and result.rdata.port != 389:
|
||||||
|
rserver += ":" + str(result.rdata.port)
|
||||||
|
if servers:
|
||||||
|
servers += "," + rserver
|
||||||
|
else:
|
||||||
|
servers = rserver
|
||||||
|
break
|
||||||
|
|
||||||
|
return servers
|
||||||
|
|
||||||
|
def ipadnssearchkrb(self, tdomain):
|
||||||
|
realm = ""
|
||||||
|
kdc = ""
|
||||||
|
# now, check for a Kerberos realm the local host or domain is in
|
||||||
|
qname = "_kerberos." + tdomain
|
||||||
|
# terminate the name
|
||||||
|
if not qname.endswith("."):
|
||||||
|
qname += "."
|
||||||
|
results = dnsclient.query(qname, dnsclient.DNS_C_IN, dnsclient.DNS_T_TXT)
|
||||||
|
|
||||||
|
for result in results:
|
||||||
|
if result.dns_type == dnsclient.DNS_T_TXT:
|
||||||
|
realm = result.rdata.data
|
||||||
|
if realm:
|
||||||
|
break
|
||||||
|
|
||||||
|
if realm:
|
||||||
|
# now fetch server information for the realm
|
||||||
|
qname = "_kerberos._udp." + tdomain
|
||||||
|
# terminate the name
|
||||||
|
if not qname.endswith("."):
|
||||||
|
qname += "."
|
||||||
|
results = dnsclient.query(qname, dnsclient.DNS_C_IN, dnsclient.DNS_T_SRV)
|
||||||
|
for result in results:
|
||||||
|
if result.dns_type == dnsclient.DNS_T_SRV:
|
||||||
|
qname = result.rdata.server.rstrip(".")
|
||||||
|
if result.rdata.port and result.rdata.port != 88:
|
||||||
|
qname += ":" + str(result.rdata.port)
|
||||||
|
if kdc:
|
||||||
|
kdc += "," + qname
|
||||||
|
else:
|
||||||
|
kdc = qname
|
||||||
|
|
||||||
|
print "["+realm+", "+kdc+"]"
|
||||||
|
return [realm, kdc]
|
||||||
Reference in New Issue
Block a user