summaryrefslogtreecommitdiffstats
path: root/ipa-server/ipaserver
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-01-29 16:26:07 -0500
committerRob Crittenden <rcritten@redhat.com>2009-02-03 15:27:14 -0500
commite30cd6ba42c256d2016db45146d616f329455e86 (patch)
treed4c5291095c80c92bc4803fe7f20fc2838124ffa /ipa-server/ipaserver
parentc4ed025001895bfc65c613cabbbfcb27c19cc29f (diff)
downloadfreeipa-e30cd6ba42c256d2016db45146d616f329455e86.tar.gz
freeipa-e30cd6ba42c256d2016db45146d616f329455e86.tar.xz
freeipa-e30cd6ba42c256d2016db45146d616f329455e86.zip
Mass tree reorganization for IPAv2. To view previous history of files use:
% git log --follow -- <file> renamed: ipa-server/autogen.sh -> autogen.sh renamed: ipa-server/ipa-kpasswd/Makefile.am -> daemons/ipa-kpasswd/Makefile.am renamed: ipa-server/ipa-kpasswd/README -> daemons/ipa-kpasswd/README renamed: ipa-server/ipa-kpasswd/ipa_kpasswd.c -> daemons/ipa-kpasswd/ipa_kpasswd.c renamed: ipa-server/ipa-kpasswd/ipa_kpasswd.init -> daemons/ipa-kpasswd/ipa_kpasswd.init renamed: ipa-server/ipa-slapi-plugins/Makefile.am -> daemons/ipa-slapi-plugins/Makefile.am renamed: ipa-server/ipa-slapi-plugins/README -> daemons/ipa-slapi-plugins/README renamed: ipa-server/ipa-slapi-plugins/dna/Makefile.am -> daemons/ipa-slapi-plugins/dna/Makefile.am renamed: ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif -> daemons/ipa-slapi-plugins/dna/dna-conf.ldif renamed: ipa-server/ipa-slapi-plugins/dna/dna.c -> daemons/ipa-slapi-plugins/dna/dna.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am -> daemons/ipa-slapi-plugins/ipa-memberof/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif -> daemons/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am -> daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README -> daemons/ipa-slapi-plugins/ipa-pwd-extop/README renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c -> daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif -> daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am -> daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/README -> daemons/ipa-slapi-plugins/ipa-winsync/README renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h renamed: ipa-server/xmlrpc-server/ipa-rewrite.conf -> install/conf/ipa-rewrite.conf renamed: ipa-server/xmlrpc-server/ipa.conf -> install/conf/ipa.conf renamed: ipa-server/xmlrpc-server/ssbrowser.html -> install/html/ssbrowser.html renamed: ipa-server/xmlrpc-server/unauthorized.html -> install/html/unauthorized.html renamed: ipa-server/ipa-install/share/60ipaconfig.ldif -> install/share/60ipaconfig.ldif renamed: ipa-server/ipa-install/share/60kerberos.ldif -> install/share/60kerberos.ldif renamed: ipa-server/ipa-install/share/60radius.ldif -> install/share/60radius.ldif renamed: ipa-server/ipa-install/share/60samba.ldif -> install/share/60samba.ldif renamed: ipa-server/ipa-install/share/Makefile.am -> install/share/Makefile.am renamed: ipa-server/ipa-install/share/bind.named.conf.template -> install/share/bind.named.conf.template renamed: ipa-server/ipa-install/share/bind.zone.db.template -> install/share/bind.zone.db.template renamed: ipa-server/ipa-install/share/bootstrap-template.ldif -> install/share/bootstrap-template.ldif renamed: ipa-server/ipa-install/share/certmap.conf.template -> install/share/certmap.conf.template renamed: ipa-server/ipa-install/share/default-aci.ldif -> install/share/default-aci.ldif renamed: ipa-server/ipa-install/share/default-keytypes.ldif -> install/share/default-keytypes.ldif renamed: ipa-server/ipa-install/share/dna-posix.ldif -> install/share/dna-posix.ldif renamed: ipa-server/ipa-install/share/encrypted_attribute.ldif -> install/share/encrypted_attribute.ldif renamed: ipa-server/ipa-install/share/fedora-ds.init.patch -> install/share/fedora-ds.init.patch renamed: ipa-server/ipa-install/share/indices.ldif -> install/share/indices.ldif renamed: ipa-server/ipa-install/share/kdc.conf.template -> install/share/kdc.conf.template renamed: ipa-server/ipa-install/share/kerberos.ldif -> install/share/kerberos.ldif renamed: ipa-server/ipa-install/share/krb.con.template -> install/share/krb.con.template renamed: ipa-server/ipa-install/share/krb5.conf.template -> install/share/krb5.conf.template renamed: ipa-server/ipa-install/share/krb5.ini.template -> install/share/krb5.ini.template renamed: ipa-server/ipa-install/share/krbrealm.con.template -> install/share/krbrealm.con.template renamed: ipa-server/ipa-install/share/master-entry.ldif -> install/share/master-entry.ldif renamed: ipa-server/ipa-install/share/memberof-task.ldif -> install/share/memberof-task.ldif renamed: ipa-server/ipa-install/share/ntp.conf.server.template -> install/share/ntp.conf.server.template renamed: ipa-server/ipa-install/share/ntpd.sysconfig.template -> install/share/ntpd.sysconfig.template renamed: ipa-server/ipa-install/share/preferences.html.template -> install/share/preferences.html.template renamed: ipa-server/ipa-install/share/referint-conf.ldif -> install/share/referint-conf.ldif renamed: ipa-server/ipa-install/share/schema_compat.uldif -> install/share/schema_compat.uldif renamed: ipa-server/ipa-install/share/unique-attributes.ldif -> install/share/unique-attributes.ldif renamed: ipa-server/ipa-install/Makefile.am -> install/tools/Makefile.am renamed: ipa-server/ipa-install/README -> install/tools/README renamed: ipa-server/ipa-compat-manage -> install/tools/ipa-compat-manage renamed: ipa-server/ipa-fix-CVE-2008-3274 -> install/tools/ipa-fix-CVE-2008-3274 renamed: ipa-server/ipa-ldap-updater -> install/tools/ipa-ldap-updater renamed: ipa-server/ipa-install/ipa-replica-install -> install/tools/ipa-replica-install renamed: ipa-server/ipa-install/ipa-replica-manage -> install/tools/ipa-replica-manage renamed: ipa-server/ipa-install/ipa-replica-prepare -> install/tools/ipa-replica-prepare renamed: ipa-server/ipa-install/ipa-server-certinstall -> install/tools/ipa-server-certinstall renamed: ipa-server/ipa-install/ipa-server-install -> install/tools/ipa-server-install renamed: ipa-server/ipa-upgradeconfig -> install/tools/ipa-upgradeconfig renamed: ipa-server/ipa-install/ipactl -> install/tools/ipactl renamed: ipa-server/man/Makefile.am -> install/tools/man/Makefile.am renamed: ipa-server/man/ipa-compat-manage.1 -> install/tools/man/ipa-compat-manage.1 renamed: ipa-server/man/ipa-ldap-updater.1 -> install/tools/man/ipa-ldap-updater.1 renamed: ipa-server/man/ipa-replica-install.1 -> install/tools/man/ipa-replica-install.1 renamed: ipa-server/man/ipa-replica-manage.1 -> install/tools/man/ipa-replica-manage.1 renamed: ipa-server/man/ipa-replica-prepare.1 -> install/tools/man/ipa-replica-prepare.1 renamed: ipa-server/man/ipa-server-certinstall.1 -> install/tools/man/ipa-server-certinstall.1 renamed: ipa-server/man/ipa-server-install.1 -> install/tools/man/ipa-server-install.1 renamed: ipa-server/man/ipa_kpasswd.8 -> install/tools/man/ipa_kpasswd.8 renamed: ipa-server/man/ipa_webgui.8 -> install/tools/man/ipa_webgui.8 renamed: ipa-server/man/ipactl.8 -> install/tools/man/ipactl.8 renamed: ipa-server/ipa-install/updates/Makefile.am -> install/updates/Makefile.am renamed: ipa-server/ipa-install/updates/RFC2307bis.update -> install/updates/RFC2307bis.update renamed: ipa-server/ipa-install/updates/RFC4876.update -> install/updates/RFC4876.update renamed: ipa-server/ipa-install/updates/indices.update -> install/updates/indices.update renamed: ipa-server/ipa-install/updates/nss_ldap.update -> install/updates/nss_ldap.update renamed: ipa-server/ipa-install/updates/replication.update -> install/updates/replication.update renamed: ipa-server/ipa-install/updates/winsync_index.update -> install/updates/winsync_index.update renamed: ipa-server/ipaserver/Makefile.am -> ipaserver/install/Makefile.am renamed: ipa-server/ipaserver/__init__.py -> ipaserver/install/__init__.py renamed: ipa-server/ipaserver/bindinstance.py -> ipaserver/install/bindinstance.py renamed: ipa-server/ipaserver/certs.py -> ipaserver/install/certs.py renamed: ipa-server/ipaserver/dsinstance.py -> ipaserver/install/dsinstance.py renamed: ipa-server/ipaserver/httpinstance.py -> ipaserver/install/httpinstance.py renamed: ipa-server/ipaserver/installutils.py -> ipaserver/install/installutils.py renamed: ipa-server/ipaserver/ipaldap.py -> ipaserver/install/ipaldap.py renamed: ipa-server/ipaserver/krbinstance.py -> ipaserver/install/krbinstance.py renamed: ipa-server/ipaserver/ldapupdate.py -> ipaserver/install/ldapupdate.py renamed: ipa-server/ipaserver/ntpinstance.py -> ipaserver/install/ntpinstance.py renamed: ipa-server/ipaserver/replication.py -> ipaserver/install/replication.py renamed: ipa-server/ipaserver/service.py -> ipaserver/install/service.py renamed: ipa-server/selinux/Makefile -> selinux/Makefile renamed: ipa-server/selinux/ipa-server-selinux.spec.in -> selinux/ipa-server-selinux.spec.in renamed: ipa-server/selinux/ipa_kpasswd/ipa_kpasswd.fc -> selinux/ipa_kpasswd/ipa_kpasswd.fc renamed: ipa-server/selinux/ipa_kpasswd/ipa_kpasswd.te -> selinux/ipa_kpasswd/ipa_kpasswd.te renamed: ipa-server/selinux/ipa_webgui/ipa_webgui.fc -> selinux/ipa_webgui/ipa_webgui.fc renamed: ipa-server/selinux/ipa_webgui/ipa_webgui.te -> selinux/ipa_webgui/ipa_webgui.te renamed: ipa-server/version.m4.in -> version.m4.in
Diffstat (limited to 'ipa-server/ipaserver')
-rw-r--r--ipa-server/ipaserver/Makefile.am24
-rw-r--r--ipa-server/ipaserver/__init__.py21
-rw-r--r--ipa-server/ipaserver/bindinstance.py156
-rw-r--r--ipa-server/ipaserver/certs.py424
-rw-r--r--ipa-server/ipaserver/dsinstance.py479
-rw-r--r--ipa-server/ipaserver/httpinstance.py231
-rw-r--r--ipa-server/ipaserver/installutils.py248
-rw-r--r--ipa-server/ipaserver/ipaldap.py701
-rw-r--r--ipa-server/ipaserver/krbinstance.py428
-rwxr-xr-xipa-server/ipaserver/ldapupdate.py593
-rw-r--r--ipa-server/ipaserver/ntpinstance.py107
-rw-r--r--ipa-server/ipaserver/replication.py532
-rw-r--r--ipa-server/ipaserver/service.py169
13 files changed, 0 insertions, 4113 deletions
diff --git a/ipa-server/ipaserver/Makefile.am b/ipa-server/ipaserver/Makefile.am
deleted file mode 100644
index 999dcf248..000000000
--- a/ipa-server/ipaserver/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-NULL =
-
-appdir = $(pythondir)/ipaserver
-app_PYTHON = \
- __init__.py \
- bindinstance.py \
- dsinstance.py \
- ipaldap.py \
- krbinstance.py \
- httpinstance.py \
- ntpinstance.py \
- service.py \
- installutils.py \
- replication.py \
- certs.py \
- ldapupdate.py \
- $(NULL)
-
-EXTRA_DIST = \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipaserver/__init__.py b/ipa-server/ipaserver/__init__.py
deleted file mode 100644
index ef86f9ec5..000000000
--- a/ipa-server/ipaserver/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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__ = ["dsinstance", "krbinstance"]
diff --git a/ipa-server/ipaserver/bindinstance.py b/ipa-server/ipaserver/bindinstance.py
deleted file mode 100644
index 5badf8603..000000000
--- a/ipa-server/ipaserver/bindinstance.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# 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 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
-#
-
-import string
-import tempfile
-import shutil
-import os
-import socket
-import logging
-
-import service
-from ipa import sysrestore
-from ipa import ipautil
-
-def check_inst():
- # So far this file is always present in both RHEL5 and Fedora if all the necessary
- # bind packages are installed (RHEL5 requires also the pkg: caching-nameserver)
- if not os.path.exists('/etc/named.rfc1912.zones'):
- return False
-
- return True
-
-class BindInstance(service.Service):
- def __init__(self, fstore=None):
- service.Service.__init__(self, "named")
- self.fqdn = None
- self.domain = None
- self.host = None
- self.ip_address = None
- self.realm = None
- self.sub_dict = None
-
- if fstore:
- self.fstore = fstore
- else:
- self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
-
- def setup(self, fqdn, ip_address, realm_name, domain_name):
- self.fqdn = fqdn
- self.ip_address = ip_address
- self.realm = realm_name
- self.domain = domain_name
- self.host = fqdn.split(".")[0]
-
- self.__setup_sub_dict()
-
- def create_sample_bind_zone(self):
- bind_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.zone.db.template", self.sub_dict)
- [bind_fd, bind_name] = tempfile.mkstemp(".db","sample.zone.")
- os.write(bind_fd, bind_txt)
- os.close(bind_fd)
- print "Sample zone file for bind has been created in "+bind_name
-
- def create_instance(self):
-
- try:
- self.stop()
- except:
- pass
-
- self.step("Setting up our zone", self.__setup_zone)
- self.step("Setting up named.conf", self.__setup_named_conf)
-
- self.step("restarting named", self.__start)
- self.step("configuring named to start on boot", self.__enable)
-
- self.step("Changing resolv.conf to point to ourselves", self.__setup_resolv_conf)
- self.start_creation("Configuring bind:")
-
- def __start(self):
- try:
- self.backup_state("running", self.is_running())
- self.restart()
- except:
- print "named service failed to start"
-
- def __enable(self):
- self.backup_state("enabled", self.is_running())
- self.chkconfig_on()
-
- def __setup_sub_dict(self):
- self.sub_dict = dict(FQDN=self.fqdn,
- IP=self.ip_address,
- DOMAIN=self.domain,
- HOST=self.host,
- REALM=self.realm)
-
- def __setup_zone(self):
- self.backup_state("domain", self.domain)
- zone_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.zone.db.template", self.sub_dict)
- self.fstore.backup_file('/var/named/'+self.domain+'.zone.db')
- zone_fd = open('/var/named/'+self.domain+'.zone.db', 'w')
- zone_fd.write(zone_txt)
- zone_fd.close()
-
- def __setup_named_conf(self):
- self.fstore.backup_file('/etc/named.conf')
- named_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.named.conf.template", self.sub_dict)
- named_fd = open('/etc/named.conf', 'w')
- named_fd.seek(0)
- named_fd.truncate(0)
- named_fd.write(named_txt)
- named_fd.close()
-
- def __setup_resolv_conf(self):
- self.fstore.backup_file('/etc/resolv.conf')
- resolv_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
- resolv_fd = open('/etc/resolv.conf', 'w')
- resolv_fd.seek(0)
- resolv_fd.truncate(0)
- resolv_fd.write(resolv_txt)
- resolv_fd.close()
-
- def uninstall(self):
- running = self.restore_state("running")
- enabled = self.restore_state("enabled")
- domain = self.restore_state("domain")
-
- if not running is None:
- self.stop()
-
- if not domain is None:
- try:
- self.fstore.restore_file(os.path.join ("/var/named/", domain + ".zone.db"))
- except ValueError, error:
- logging.debug(error)
- pass
-
- for f in ["/etc/named.conf", "/etc/resolv.conf"]:
- try:
- self.fstore.restore_file(f)
- except ValueError, error:
- logging.debug(error)
- pass
-
- if not enabled is None and not enabled:
- self.chkconfig_off()
-
- if not running is None and running:
- self.start()
diff --git a/ipa-server/ipaserver/certs.py b/ipa-server/ipaserver/certs.py
deleted file mode 100644
index 8cb1d0883..000000000
--- a/ipa-server/ipaserver/certs.py
+++ /dev/null
@@ -1,424 +0,0 @@
-# Authors: 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
-#
-
-import os, stat, subprocess, re
-import sha
-import errno
-import tempfile
-import shutil
-
-from ipa import sysrestore
-from ipa import ipautil
-
-CA_SERIALNO="/var/lib/ipa/ca_serialno"
-
-class CertDB(object):
- def __init__(self, dir, fstore=None):
- self.secdir = dir
-
- self.noise_fname = self.secdir + "/noise.txt"
- self.passwd_fname = self.secdir + "/pwdfile.txt"
- self.certdb_fname = self.secdir + "/cert8.db"
- self.keydb_fname = self.secdir + "/key3.db"
- self.secmod_fname = self.secdir + "/secmod.db"
- self.cacert_fname = self.secdir + "/cacert.asc"
- self.pk12_fname = self.secdir + "/cacert.p12"
- self.pin_fname = self.secdir + "/pin.txt"
- self.reqdir = tempfile.mkdtemp('', 'ipa-', '/var/lib/ipa')
- self.certreq_fname = self.reqdir + "/tmpcertreq"
- self.certder_fname = self.reqdir + "/tmpcert.der"
-
- # Making this a starting value that will generate
- # unique values for the current DB is the
- # responsibility of the caller for now. In the
- # future we might automatically determine this
- # for a given db.
- self.cur_serial = -1
-
- self.cacert_name = "CA certificate"
- self.valid_months = "120"
- self.keysize = "1024"
-
- # We are going to set the owner of all of the cert
- # files to the owner of the containing directory
- # instead of that of the process. This works when
- # this is called by root for a daemon that runs as
- # a normal user
- mode = os.stat(self.secdir)
- self.uid = mode[stat.ST_UID]
- self.gid = mode[stat.ST_GID]
-
- if fstore:
- self.fstore = fstore
- else:
- self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
-
- def __del__(self):
- shutil.rmtree(self.reqdir, ignore_errors=True)
-
- def set_serial_from_pkcs12(self):
- """A CA cert was loaded from a PKCS#12 file. Set up our serial file"""
-
- self.cur_serial = self.find_cacert_serial()
- try:
- f=open(CA_SERIALNO,"w")
- f.write(str(self.cur_serial))
- f.close()
- except IOError, e:
- raise RuntimeError("Unable to increment serial number: %s" % str(e))
-
- def next_serial(self):
- try:
- f=open(CA_SERIALNO,"r")
- r = f.readline()
- try:
- self.cur_serial = int(r) + 1
- except ValueError:
- raise RuntimeError("The value in %s is not an integer" % CA_SERIALNO)
- f.close()
- except IOError, e:
- if e.errno == errno.ENOENT:
- self.cur_serial = 1000
- f=open(CA_SERIALNO,"w")
- f.write(str(self.cur_serial))
- f.close()
- else:
- raise RuntimeError("Unable to determine serial number: %s" % str(e))
-
- try:
- f=open(CA_SERIALNO,"w")
- f.write(str(self.cur_serial))
- f.close()
- except IOError, e:
- raise RuntimeError("Unable to increment serial number: %s" % str(e))
-
- return str(self.cur_serial)
-
- def set_perms(self, fname, write=False):
- os.chown(fname, self.uid, self.gid)
- perms = stat.S_IRUSR
- if write:
- perms |= stat.S_IWUSR
- os.chmod(fname, perms)
-
- def gen_password(self):
- return sha.sha(ipautil.ipa_generate_password()).hexdigest()
-
- def run_certutil(self, args, stdin=None):
- new_args = ["/usr/bin/certutil", "-d", self.secdir]
- new_args = new_args + args
- return ipautil.run(new_args, stdin)
-
- def run_signtool(self, args, stdin=None):
- new_args = ["/usr/bin/signtool", "-d", self.secdir]
- new_args = new_args + args
- ipautil.run(new_args, stdin)
-
- def create_noise_file(self):
- ipautil.backup_file(self.noise_fname)
- f = open(self.noise_fname, "w")
- f.write(self.gen_password())
- self.set_perms(self.noise_fname)
-
- def create_passwd_file(self, passwd=None):
- ipautil.backup_file(self.passwd_fname)
- f = open(self.passwd_fname, "w")
- if passwd is not None:
- f.write("%s\n" % passwd)
- else:
- f.write(self.gen_password())
- f.close()
- self.set_perms(self.passwd_fname)
-
- def create_certdbs(self):
- ipautil.backup_file(self.certdb_fname)
- ipautil.backup_file(self.keydb_fname)
- ipautil.backup_file(self.secmod_fname)
- self.run_certutil(["-N",
- "-f", self.passwd_fname])
- self.set_perms(self.passwd_fname, write=True)
-
- def create_ca_cert(self):
- # Generate the encryption key
- self.run_certutil(["-G", "-z", self.noise_fname, "-f", self.passwd_fname])
- # Generate the self-signed cert
- self.run_certutil(["-S", "-n", self.cacert_name,
- "-s", "cn=IPA Test Certificate Authority",
- "-x",
- "-t", "CT,,C",
- "-m", self.next_serial(),
- "-v", self.valid_months,
- "-z", self.noise_fname,
- "-f", self.passwd_fname])
-
- def export_ca_cert(self, nickname, create_pkcs12=False):
- """create_pkcs12 tells us whether we should create a PKCS#12 file
- of the CA or not. If we are running on a replica then we won't
- have the private key to make a PKCS#12 file so we don't need to
- do that step."""
- # export the CA cert for use with other apps
- ipautil.backup_file(self.cacert_fname)
- self.run_certutil(["-L", "-n", nickname,
- "-a",
- "-o", self.cacert_fname])
- self.set_perms(self.cacert_fname)
- if create_pkcs12:
- ipautil.backup_file(self.pk12_fname)
- ipautil.run(["/usr/bin/pk12util", "-d", self.secdir,
- "-o", self.pk12_fname,
- "-n", self.cacert_name,
- "-w", self.passwd_fname,
- "-k", self.passwd_fname])
- self.set_perms(self.pk12_fname)
-
- def load_cacert(self, cacert_fname):
- self.run_certutil(["-A", "-n", self.cacert_name,
- "-t", "CT,,C",
- "-a",
- "-i", cacert_fname])
-
- def find_cacert_serial(self):
- (out,err) = self.run_certutil(["-L", "-n", self.cacert_name])
- data = out.split('\n')
- for line in data:
- x = re.match(r'\s+Serial Number: (\d+) .*', line)
- if x is not None:
- return x.group(1)
-
- raise RuntimeError("Unable to find serial number")
-
- def create_server_cert(self, nickname, name, other_certdb=None):
- cdb = other_certdb
- if not cdb:
- cdb = self
- self.request_cert(name)
- cdb.issue_server_cert(self.certreq_fname, self.certder_fname)
- self.add_cert(self.certder_fname, nickname)
- os.unlink(self.certreq_fname)
- os.unlink(self.certder_fname)
-
- def create_signing_cert(self, nickname, name, other_certdb=None):
- cdb = other_certdb
- if not cdb:
- cdb = self
- self.request_cert(name)
- cdb.issue_signing_cert(self.certreq_fname, self.certder_fname)
- self.add_cert(self.certder_fname, nickname)
- os.unlink(self.certreq_fname)
- os.unlink(self.certder_fname)
-
- def request_cert(self, name):
- self.run_certutil(["-R", "-s", name,
- "-o", self.certreq_fname,
- "-g", self.keysize,
- "-z", self.noise_fname,
- "-f", self.passwd_fname])
-
- def issue_server_cert(self, certreq_fname, cert_fname):
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", self.next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
-
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 2 - Key encipherment
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 1 - SSL Server
- # 9 - done
- # n - not critical
- p.stdin.write("2\n9\nn\n1\n9\nn\n")
- p.wait()
-
- def issue_signing_cert(self, certreq_fname, cert_fname):
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", self.next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
-
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 0 - Digital Signature
- # 5 - Cert signing key
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 3 - Object Signing
- # 9 - done
- # n - not critical
- p.stdin.write("0\n5\n9\nn\n3\n9\nn\n")
- p.wait()
-
- def add_cert(self, cert_fname, nickname):
- self.run_certutil(["-A", "-n", nickname,
- "-t", "u,u,u",
- "-i", cert_fname,
- "-f", cert_fname])
-
- def create_pin_file(self):
- ipautil.backup_file(self.pin_fname)
- f = open(self.pin_fname, "w")
- f.write("Internal (Software) Token:")
- pwd = open(self.passwd_fname)
- f.write(pwd.read())
- f.close()
- self.set_perms(self.pin_fname)
-
- def find_root_cert(self, nickname):
- p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
- "-O", "-n", nickname], stdout=subprocess.PIPE)
-
- chain = p.stdout.read()
- chain = chain.split("\n")
-
- root_nickname = re.match('\ *"(.*)".*', chain[0]).groups()[0]
-
- return root_nickname
-
- def trust_root_cert(self, nickname):
- root_nickname = self.find_root_cert(nickname)
-
- self.run_certutil(["-M", "-n", root_nickname,
- "-t", "CT,CT,"])
-
- def find_server_certs(self):
- p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
- "-L"], stdout=subprocess.PIPE)
-
- certs = p.stdout.read()
-
- certs = certs.split("\n")
-
- server_certs = []
-
- for cert in certs:
- fields = cert.split()
- if not len(fields):
- continue
- flags = fields[-1]
- if 'u' in flags:
- name = " ".join(fields[0:-1])
- # NSS 3.12 added a header to the certutil output
- if name == "Certificate Nickname Trust":
- continue
- server_certs.append((name, flags))
-
- return server_certs
-
- def import_pkcs12(self, pkcs12_fname, passwd_fname=None):
- args = ["/usr/bin/pk12util", "-d", self.secdir,
- "-i", pkcs12_fname,
- "-k", self.passwd_fname]
- if passwd_fname:
- args = args + ["-w", passwd_fname]
- try:
- ipautil.run(args)
- except ipautil.CalledProcessError, e:
- if e.returncode == 17:
- raise RuntimeError("incorrect password")
- else:
- raise RuntimeError("unknown error import pkcs#12 file")
-
- def export_pkcs12(self, pkcs12_fname, pkcs12_pwd_fname, nickname="CA certificate"):
- ipautil.run(["/usr/bin/pk12util", "-d", self.secdir,
- "-o", pkcs12_fname,
- "-n", nickname,
- "-k", self.passwd_fname,
- "-w", pkcs12_pwd_fname])
-
- def create_self_signed(self, passwd=None):
- self.create_noise_file()
- self.create_passwd_file(passwd)
- self.create_certdbs()
- self.create_ca_cert()
- self.export_ca_cert(self.cacert_name, True)
- self.create_pin_file()
-
- def create_from_cacert(self, cacert_fname, passwd=""):
- self.create_noise_file()
- self.create_passwd_file(passwd)
- self.create_certdbs()
- self.load_cacert(cacert_fname)
-
- def create_from_pkcs12(self, pkcs12_fname, pkcs12_pwd_fname, passwd=None):
- """Create a new NSS database using the certificates in a PKCS#12 file.
-
- pkcs12_fname: the filename of the PKCS#12 file
- pkcs12_pwd_fname: the file containing the pin for the PKCS#12 file
- nickname: the nickname/friendly-name of the cert we are loading
- passwd: The password to use for the new NSS database we are creating
- """
- self.create_noise_file()
- self.create_passwd_file(passwd)
- self.create_certdbs()
- self.import_pkcs12(pkcs12_fname, pkcs12_pwd_fname)
- server_certs = self.find_server_certs()
- if len(server_certs) == 0:
- raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_fname)
-
- # We only handle one server cert
- nickname = server_certs[0][0]
-
- self.cacert_name = self.find_root_cert(nickname)
- self.trust_root_cert(nickname)
- self.create_pin_file()
- self.export_ca_cert(self.cacert_name, False)
-
- # This file implies that we have our own self-signed CA. Ensure
- # that it no longer exists (from previous installs, for example).
- try:
- os.remove(CA_SERIALNO)
- except:
- pass
-
- def backup_files(self):
- self.fstore.backup_file(self.noise_fname)
- self.fstore.backup_file(self.passwd_fname)
- self.fstore.backup_file(self.certdb_fname)
- self.fstore.backup_file(self.keydb_fname)
- self.fstore.backup_file(self.secmod_fname)
- self.fstore.backup_file(self.cacert_fname)
- self.fstore.backup_file(self.pk12_fname)
- self.fstore.backup_file(self.pin_fname)
- self.fstore.backup_file(self.certreq_fname)
- self.fstore.backup_file(self.certder_fname)
diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py
deleted file mode 100644
index e9826bf68..000000000
--- a/ipa-server/ipaserver/dsinstance.py
+++ /dev/null
@@ -1,479 +0,0 @@
-# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
-# 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 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
-#
-
-import shutil
-import logging
-import pwd
-import glob
-import sys
-import os
-import re
-import time
-import tempfile
-import stat
-
-from ipa import ipautil
-
-import service
-import installutils
-import certs
-import ipaldap, ldap
-from ipaserver import ldapupdate
-
-SERVER_ROOT_64 = "/usr/lib64/dirsrv"
-SERVER_ROOT_32 = "/usr/lib/dirsrv"
-
-def realm_to_suffix(realm_name):
- s = realm_name.split(".")
- terms = ["dc=" + x.lower() for x in s]
- return ",".join(terms)
-
-def find_server_root():
- if ipautil.dir_exists(SERVER_ROOT_64):
- return SERVER_ROOT_64
- else:
- return SERVER_ROOT_32
-
-def realm_to_serverid(realm_name):
- return "-".join(realm_name.split("."))
-
-def config_dirname(serverid):
- return "/etc/dirsrv/slapd-" + serverid + "/"
-
-def schema_dirname(serverid):
- return config_dirname(serverid) + "/schema/"
-
-def erase_ds_instance_data(serverid):
- try:
- shutil.rmtree("/etc/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/usr/lib/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/usr/lib64/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/var/lib/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/var/lock/dirsrv/slapd-%s" % serverid)
- except:
- pass
-# try:
-# shutil.rmtree("/var/log/dirsrv/slapd-%s" % serverid)
-# except:
-# pass
-
-def check_existing_installation():
- dirs = glob.glob("/etc/dirsrv/slapd-*")
- if not dirs:
- return []
-
- serverids = []
- for d in dirs:
- serverids.append(os.path.basename(d).split("slapd-", 1)[1])
-
- return serverids
-
-def check_ports():
- ds_unsecure = installutils.port_available(389)
- ds_secure = installutils.port_available(636)
- return (ds_unsecure, ds_secure)
-
-def is_ds_running():
- """The DS init script always returns 0 when requesting status so it cannot
- be used to determine if the server is running. We have to look at the
- output.
- """
- ret = True
- try:
- (sout, serr) = ipautil.run(["/sbin/service", "dirsrv", "status"])
- if sout.find("is stopped") >= 0:
- ret = False
- except ipautil.CalledProcessError:
- ret = False
- return ret
-
-
-INF_TEMPLATE = """
-[General]
-FullMachineName= $FQHN
-SuiteSpotUserID= $USER
-ServerRoot= $SERVER_ROOT
-[slapd]
-ServerPort= 389
-ServerIdentifier= $SERVERID
-Suffix= $SUFFIX
-RootDN= cn=Directory Manager
-RootDNPwd= $PASSWORD
-InstallLdifFile= /var/lib/dirsrv/boot.ldif
-"""
-
-BASE_TEMPLATE = """
-dn: $SUFFIX
-objectClass: top
-objectClass: domain
-objectClass: pilotObject
-dc: $BASEDC
-info: IPA V1.0
-"""
-
-class DsInstance(service.Service):
- def __init__(self, realm_name=None, domain_name=None, dm_password=None):
- service.Service.__init__(self, "dirsrv")
- self.realm_name = realm_name
- self.dm_password = dm_password
- self.sub_dict = None
- self.domain = domain_name
- self.serverid = None
- self.host_name = None
- self.pkcs12_info = None
- self.ds_user = None
- if realm_name:
- self.suffix = realm_to_suffix(self.realm_name)
- self.__setup_sub_dict()
- else:
- self.suffix = None
-
- def create_instance(self, ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info=None):
- self.ds_user = ds_user
- self.realm_name = realm_name.upper()
- self.serverid = realm_to_serverid(self.realm_name)
- self.suffix = realm_to_suffix(self.realm_name)
- self.host_name = host_name
- self.dm_password = dm_password
- self.domain = domain_name
- self.pkcs12_info = pkcs12_info
- self.__setup_sub_dict()
-
- self.step("creating directory server user", self.__create_ds_user)
- self.step("creating directory server instance", self.__create_instance)
- self.step("adding default schema", self.__add_default_schemas)
- self.step("enabling memberof plugin", self.__add_memberof_module)
- self.step("enabling referential integrity plugin", self.__add_referint_module)
- self.step("enabling distributed numeric assignment plugin", self.__add_dna_module)
- self.step("enabling winsync plugin", self.__add_winsync_module)
- self.step("configuring uniqueness plugin", self.__set_unique_attrs)
- self.step("creating indices", self.__create_indices)
- self.step("configuring ssl for ds instance", self.__enable_ssl)
- self.step("configuring certmap.conf", self.__certmap_conf)
- self.step("restarting directory server", self.__restart_instance)
- self.step("adding default layout", self.__add_default_layout)
- self.step("configuring Posix uid/gid generation as first master",
- self.__config_uidgid_gen_first_master)
- self.step("adding master entry as first master",
- self.__add_master_entry_first_master)
- self.step("initializing group membership",
- self.init_memberof)
-
- self.step("configuring directory to start on boot", self.__enable)
-
- self.start_creation("Configuring directory server:")
-
- def __enable(self):
- self.backup_state("enabled", self.is_enabled())
- self.chkconfig_on()
-
- def __setup_sub_dict(self):
- server_root = find_server_root()
- self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid,
- PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(),
- REALM=self.realm_name, USER=self.ds_user,
- SERVER_ROOT=server_root, DOMAIN=self.domain,
- TIME=int(time.time()))
-
- def __create_ds_user(self):
- user_exists = True
- try:
- pwd.getpwnam(self.ds_user)
- logging.debug("ds user %s exists" % self.ds_user)
- except KeyError:
- user_exists = False
- logging.debug("adding ds user %s" % self.ds_user)
- args = ["/usr/sbin/useradd", "-c", "DS System User", "-d", "/var/lib/dirsrv", "-M", "-r", "-s", "/sbin/nologin", self.ds_user]
- try:
- ipautil.run(args)
- logging.debug("done adding user")
- except ipautil.CalledProcessError, e:
- logging.critical("failed to add user %s" % e)
-
- self.backup_state("user", self.ds_user)
- self.backup_state("user_exists", user_exists)
-
- def __create_instance(self):
- self.backup_state("running", is_ds_running())
- self.backup_state("serverid", self.serverid)
-
- self.sub_dict['BASEDC'] = self.realm_name.split('.')[0].lower()
- base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict)
- logging.debug(base_txt)
- base_fd = file("/var/lib/dirsrv/boot.ldif", "w")
- base_fd.write(base_txt)
- base_fd.flush()
- base_fd.close()
-
- inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict)
- logging.debug("writing inf template")
- inf_fd = ipautil.write_tmp_file(inf_txt)
- inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt)
- logging.debug(inf_txt)
- if ipautil.file_exists("/usr/sbin/setup-ds.pl"):
- args = ["/usr/sbin/setup-ds.pl", "--silent", "--logfile", "-", "-f", inf_fd.name]
- logging.debug("calling setup-ds.pl")
- else:
- args = ["/usr/bin/ds_newinst.pl", inf_fd.name]
- logging.debug("calling ds_newinst.pl")
- try:
- ipautil.run(args)
- logging.debug("completed creating ds instance")
- except ipautil.CalledProcessError, e:
- logging.critical("failed to restart ds instance %s" % e)
- logging.debug("restarting ds instance")
- try:
- self.restart()
- logging.debug("done restarting ds instance")
- except ipautil.CalledProcessError, e:
- print "failed to restart ds instance", e
- logging.debug("failed to restart ds instance %s" % e)
- inf_fd.close()
- os.remove("/var/lib/dirsrv/boot.ldif")
-
- def __add_default_schemas(self):
- shutil.copyfile(ipautil.SHARE_DIR + "60kerberos.ldif",
- schema_dirname(self.serverid) + "60kerberos.ldif")
- shutil.copyfile(ipautil.SHARE_DIR + "60samba.ldif",
- schema_dirname(self.serverid) + "60samba.ldif")
- shutil.copyfile(ipautil.SHARE_DIR + "60radius.ldif",
- schema_dirname(self.serverid) + "60radius.ldif")
- shutil.copyfile(ipautil.SHARE_DIR + "60ipaconfig.ldif",
- schema_dirname(self.serverid) + "60ipaconfig.ldif")
-
- def __restart_instance(self):
- try:
- self.restart()
- if not is_ds_running():
- logging.critical("Failed to restart the directory server. See the installation log for details.")
- sys.exit(1)
- except SystemExit, e:
- raise e
- except Exception, e:
- # TODO: roll back here?
- logging.critical("Failed to restart the directory server. See the installation log for details.")
-
- def __ldap_mod(self, ldif, sub_dict = None):
- fd = None
- path = ipautil.SHARE_DIR + ldif
-
- if not sub_dict is None:
- txt = ipautil.template_file(path, sub_dict)
- fd = ipautil.write_tmp_file(txt)
- path = fd.name
-
- [pw_fd, pw_name] = tempfile.mkstemp()
- os.write(pw_fd, self.dm_password)
- os.close(pw_fd)
-
- args = ["/usr/bin/ldapmodify", "-h", "127.0.0.1", "-xv",
- "-D", "cn=Directory Manager", "-y", pw_name, "-f", path]
-
- try:
- try:
- ipautil.run(args)
- except ipautil.CalledProcessError, e:
- logging.critical("Failed to load %s: %s" % (ldif, str(e)))
- finally:
- os.remove(pw_name)
-
- if not fd is None:
- fd.close()
-
- def __add_memberof_module(self):
- self.__ldap_mod("memberof-conf.ldif")
-
- def init_memberof(self):
- self.__ldap_mod("memberof-task.ldif", self.sub_dict)
-
- def apply_updates(self):
- ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password)
- files = ld.get_all_files(ldapupdate.UPDATES_DIR)
- ld.update(files)
-
- def __add_referint_module(self):
- self.__ldap_mod("referint-conf.ldif")
-
- def __add_dna_module(self):
- self.__ldap_mod("dna-conf.ldif")
-
- def __set_unique_attrs(self):
- self.__ldap_mod("unique-attributes.ldif", self.sub_dict)
-
- def __config_uidgid_gen_first_master(self):
- self.__ldap_mod("dna-posix.ldif", self.sub_dict)
-
- def __add_master_entry_first_master(self):
- self.__ldap_mod("master-entry.ldif", self.sub_dict)
-
- def __add_winsync_module(self):
- self.__ldap_mod("ipa-winsync-conf.ldif")
-
- def __enable_ssl(self):
- dirname = config_dirname(self.serverid)
- ca = certs.CertDB(dirname)
- if self.pkcs12_info:
- ca.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1])
- server_certs = ca.find_server_certs()
- if len(server_certs) == 0:
- raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_info[0])
-
- # We only handle one server cert
- nickname = server_certs[0][0]
- else:
- ca.create_self_signed()
- ca.create_server_cert("Server-Cert", "cn=%s,ou=Fedora Directory Server" % self.host_name)
- nickname = "Server-Cert"
-
- conn = ipaldap.IPAdmin("127.0.0.1")
- conn.simple_bind_s("cn=directory manager", self.dm_password)
-
- mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"),
- (ldap.MOD_REPLACE, "nsSSL3Ciphers",
- "-rsa_null_md5,+rsa_rc4_128_md5,+rsa_rc4_40_md5,+rsa_rc2_40_md5,\
-+rsa_des_sha,+rsa_fips_des_sha,+rsa_3des_sha,+rsa_fips_3des_sha,+fortezza,\
-+fortezza_rc4_128_sha,+fortezza_null,+tls_rsa_export1024_with_rc4_56_sha,\
-+tls_rsa_export1024_with_des_cbc_sha")]
- conn.modify_s("cn=encryption,cn=config", mod)
-
- mod = [(ldap.MOD_ADD, "nsslapd-security", "on"),
- (ldap.MOD_REPLACE, "nsslapd-ssl-check-hostname", "off")]
- conn.modify_s("cn=config", mod)
-
- entry = ipaldap.Entry("cn=RSA,cn=encryption,cn=config")
-
- entry.setValues("objectclass", "top", "nsEncryptionModule")
- entry.setValues("cn", "RSA")
- entry.setValues("nsSSLPersonalitySSL", nickname)
- entry.setValues("nsSSLToken", "internal (software)")
- entry.setValues("nsSSLActivation", "on")
-
- conn.addEntry(entry)
-
- conn.unbind()
-
- def __add_default_layout(self):
- self.__ldap_mod("bootstrap-template.ldif", self.sub_dict)
-
- def __create_indices(self):
- self.__ldap_mod("indices.ldif")
-
- def __certmap_conf(self):
- shutil.copyfile(ipautil.SHARE_DIR + "certmap.conf.template",
- config_dirname(self.serverid) + "certmap.conf")
-
- def change_admin_password(self, password):
- logging.debug("Changing admin password")
- dirname = config_dirname(self.serverid)
- if ipautil.dir_exists("/usr/lib64/mozldap"):
- app = "/usr/lib64/mozldap/ldappasswd"
- else:
- app = "/usr/lib/mozldap/ldappasswd"
- args = [app,
- "-D", "cn=Directory Manager", "-w", self.dm_password,
- "-P", dirname+"/cert8.db", "-ZZZ", "-s", password,
- "uid=admin,cn=users,cn=accounts,"+self.suffix]
- try:
- ipautil.run(args)
- logging.debug("ldappasswd done")
- except ipautil.CalledProcessError, e:
- print "Unable to set admin password", e
- logging.debug("Unable to set admin password %s" % e)
-
- def uninstall(self):
- running = self.restore_state("running")
- enabled = self.restore_state("enabled")
-
- if not running is None:
- self.stop()
-
- if not enabled is None and not enabled:
- self.chkconfig_off()
-
- serverid = self.restore_state("serverid")
- if not serverid is None:
- erase_ds_instance_data(serverid)
-
- ds_user = self.restore_state("user")
- user_exists = self.restore_state("user_exists")
-
- if not ds_user is None and not user_exists is None and not user_exists:
- try:
- ipautil.run(["/usr/sbin/userdel", ds_user])
- except ipautil.CalledProcessError, e:
- logging.critical("failed to delete user %s" % e)
-
- if self.restore_state("running"):
- self.start()
-
- # we could probably move this function into the service.Service
- # class - it's very generic - all we need is a way to get an
- # instance of a particular Service
- def add_ca_cert(self, cacert_fname, cacert_name=''):
- """Add a CA certificate to the directory server cert db. We
- first have to shut down the directory server in case it has
- opened the cert db read-only. Then we use the CertDB class
- to add the CA cert. We have to provide a nickname, and we
- do not use 'CA certificate' since that's the default, so
- we use 'Imported CA' if none specified. Then we restart
- the server."""
- # first make sure we have a valid cacert_fname
- try:
- if not os.access(cacert_fname, os.R_OK):
- logging.critical("The given CA cert file named [%s] could not be read" %
- cacert_fname)
- return False
- except OSError, e:
- logging.critical("The given CA cert file named [%s] could not be read: %s" %
- (cacert_fname, str(e)))
- return False
- # ok - ca cert file can be read
- # shutdown the server
- self.stop()
-
- dirname = config_dirname(realm_to_serverid(self.realm_name))
- certdb = certs.CertDB(dirname)
- if not cacert_name or len(cacert_name) == 0:
- cacert_name = "Imported CA"
- # we can't pass in the nickname, so we set the instance variable
- certdb.cacert_name = cacert_name
- status = True
- try:
- certdb.load_cacert(cacert_fname)
- except ipalib.CalledProcessError, e:
- logging.critical("Error importing CA cert file named [%s]: %s" %
- (cacert_fname, str(e)))
- status = False
- # restart the directory server
- self.start()
-
- return status
diff --git a/ipa-server/ipaserver/httpinstance.py b/ipa-server/ipaserver/httpinstance.py
deleted file mode 100644
index f5a903b30..000000000
--- a/ipa-server/ipaserver/httpinstance.py
+++ /dev/null
@@ -1,231 +0,0 @@
-# Authors: Rob Crittenden <rcritten@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 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
-#
-
-import os
-import os.path
-import subprocess
-import string
-import tempfile
-import logging
-import pwd
-import fileinput
-import sys
-import shutil
-
-import service
-import certs
-import dsinstance
-import installutils
-from ipa import sysrestore
-from ipa import ipautil
-
-HTTPD_DIR = "/etc/httpd"
-SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf"
-NSS_CONF = HTTPD_DIR + "/conf.d/nss.conf"
-NSS_DIR = HTTPD_DIR + "/alias"
-
-selinux_warning = """WARNING: could not set selinux boolean httpd_can_network_connect to true.
-The web interface may not function correctly until this boolean is
-successfully change with the command:
- /usr/sbin/setsebool -P httpd_can_network_connect true
-Try updating the policycoreutils and selinux-policy packages.
-"""
-
-class WebGuiInstance(service.SimpleServiceInstance):
- def __init__(self):
- service.SimpleServiceInstance.__init__(self, "ipa_webgui")
-
-class HTTPInstance(service.Service):
- def __init__(self, fstore = None):
- service.Service.__init__(self, "httpd")
- if fstore:
- self.fstore = fstore
- else:
- self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
-
- def create_instance(self, realm, fqdn, domain_name, autoconfig=True, pkcs12_info=None):
- self.fqdn = fqdn
- self.realm = realm
- self.domain = domain_name
- self.pkcs12_info = pkcs12_info
- self.sub_dict = { "REALM" : realm, "FQDN": fqdn, "DOMAIN" : self.domain }
-
- self.step("disabling mod_ssl in httpd", self.__disable_mod_ssl)
- self.step("Setting mod_nss port to 443", self.__set_mod_nss_port)
- self.step("Adding URL rewriting rules", self.__add_include)
- self.step("configuring httpd", self.__configure_http)
- self.step("creating a keytab for httpd", self.__create_http_keytab)
- self.step("Setting up ssl", self.__setup_ssl)
- if autoconfig:
- self.step("Setting up browser autoconfig", self.__setup_autoconfig)
- self.step("configuring SELinux for httpd", self.__selinux_config)
- self.step("restarting httpd", self.__start)
- self.step("configuring httpd to start on boot", self.__enable)
-
- self.start_creation("Configuring the web interface")
-
- def __start(self):
- self.backup_state("running", self.is_running())
- self.restart()
-
- def __enable(self):
- self.backup_state("enabled", self.is_running())
- self.chkconfig_on()
-
- def __selinux_config(self):
- selinux=0
- try:
- if (os.path.exists('/usr/sbin/selinuxenabled')):
- ipautil.run(["/usr/sbin/selinuxenabled"])
- selinux=1
- except ipautil.CalledProcessError:
- # selinuxenabled returns 1 if not enabled
- pass
-
- if selinux:
- try:
- # returns e.g. "httpd_can_network_connect --> off"
- (stdout, stderr) = ipautils.run(["/usr/sbin/getsebool",
- "httpd_can_network_connect"])
- self.backup_state("httpd_can_network_connect", stdout.split()[2])
- except:
- pass
-
- # Allow apache to connect to the turbogears web gui
- # This can still fail even if selinux is enabled
- try:
- ipautil.run(["/usr/sbin/setsebool", "-P", "httpd_can_network_connect", "true"])
- except:
- self.print_msg(selinux_warning)
-
- def __create_http_keytab(self):
- http_principal = "HTTP/" + self.fqdn + "@" + self.realm
- installutils.kadmin_addprinc(http_principal)
- installutils.create_keytab("/etc/httpd/conf/ipa.keytab", http_principal)
-
- pent = pwd.getpwnam("apache")
- os.chown("/etc/httpd/conf/ipa.keytab", pent.pw_uid, pent.pw_gid)
-
- def __configure_http(self):
- http_txt = ipautil.template_file(ipautil.SHARE_DIR + "ipa.conf", self.sub_dict)
- self.fstore.backup_file("/etc/httpd/conf.d/ipa.conf")
- http_fd = open("/etc/httpd/conf.d/ipa.conf", "w")
- http_fd.write(http_txt)
- http_fd.close()
-
- http_txt = ipautil.template_file(ipautil.SHARE_DIR + "ipa-rewrite.conf", self.sub_dict)
- self.fstore.backup_file("/etc/httpd/conf.d/ipa-rewrite.conf")
- http_fd = open("/etc/httpd/conf.d/ipa-rewrite.conf", "w")
- http_fd.write(http_txt)
- http_fd.close()
-
- def __disable_mod_ssl(self):
- if os.path.exists(SSL_CONF):
- self.fstore.backup_file(SSL_CONF)
- os.unlink(SSL_CONF)
-
- def __set_mod_nss_port(self):
- self.fstore.backup_file(NSS_CONF)
- if installutils.update_file(NSS_CONF, '8443', '443') != 0:
- print "Updating port in %s failed." % NSS_CONF
-
- def __set_mod_nss_nickname(self, nickname):
- installutils.set_directive(NSS_CONF, 'NSSNickname', nickname)
-
- def __add_include(self):
- """This should run after __set_mod_nss_port so is already backed up"""
- if installutils.update_file(NSS_CONF, '</VirtualHost>', 'Include conf.d/ipa-rewrite.conf\n</VirtualHost>') != 0:
- print "Adding Include conf.d/ipa-rewrite to %s failed." % NSS_CONF
-
- def __setup_ssl(self):
- ds_ca = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
- ca = certs.CertDB(NSS_DIR)
- if self.pkcs12_info:
- ca.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="")
- server_certs = ca.find_server_certs()
- if len(server_certs) == 0:
- raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_info[0])
-
- # We only handle one server cert
- nickname = server_certs[0][0]
-
- self.__set_mod_nss_nickname(nickname)
- else:
- ca.create_from_cacert(ds_ca.cacert_fname)
- ca.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca)
- ca.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ds_ca)
-
- # Fix the database permissions
- os.chmod(NSS_DIR + "/cert8.db", 0640)
- os.chmod(NSS_DIR + "/key3.db", 0640)
- os.chmod(NSS_DIR + "/secmod.db", 0640)
-
- pent = pwd.getpwnam("apache")
- os.chown(NSS_DIR + "/cert8.db", 0, pent.pw_gid )
- os.chown(NSS_DIR + "/key3.db", 0, pent.pw_gid )
- os.chown(NSS_DIR + "/secmod.db", 0, pent.pw_gid )
-
- def __setup_autoconfig(self):
- prefs_txt = ipautil.template_file(ipautil.SHARE_DIR + "preferences.html.template", self.sub_dict)
- prefs_fd = open("/usr/share/ipa/html/preferences.html", "w")
- prefs_fd.write(prefs_txt)
- prefs_fd.close()
-
- # The signing cert is generated in __setup_ssl
- ds_ca = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
- ca = certs.CertDB(NSS_DIR)
-
- # Publish the CA certificate
- shutil.copy(ds_ca.cacert_fname, "/usr/share/ipa/html/ca.crt")
- os.chmod("/usr/share/ipa/html/ca.crt", 0444)
-
- tmpdir = tempfile.mkdtemp(prefix = "tmp-")
- shutil.copy("/usr/share/ipa/html/preferences.html", tmpdir)
- ca.run_signtool(["-k", "Signing-Cert",
- "-Z", "/usr/share/ipa/html/configure.jar",
- "-e", ".html",
- tmpdir])
- shutil.rmtree(tmpdir)
-
- def uninstall(self):
- running = self.restore_state("running")
- enabled = self.restore_state("enabled")
-
- if not running is None:
- self.stop()
-
- if not enabled is None and not enabled:
- self.chkconfig_off()
-
- for f in ["/etc/httpd/conf.d/ipa.conf", SSL_CONF, NSS_CONF]:
- try:
- self.fstore.restore_file(f)
- except ValueError, error:
- logging.debug(error)
- pass
-
- sebool_state = self.restore_state("httpd_can_network_connect")
- if not sebool_state is None:
- try:
- ipautil.run(["/usr/sbin/setsebool", "-P", "httpd_can_network_connect", sebool_state])
- except:
- self.print_msg(selinux_warning)
-
- if not running is None and running:
- self.start()
diff --git a/ipa-server/ipaserver/installutils.py b/ipa-server/ipaserver/installutils.py
deleted file mode 100644
index 563b168e8..000000000
--- a/ipa-server/ipaserver/installutils.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# 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 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
-#
-
-import logging
-import socket
-import errno
-import getpass
-import os
-import re
-import fileinput
-import sys
-import time
-import struct
-import fcntl
-
-from ipa import ipautil
-from ipa import dnsclient
-
-def get_fqdn():
- fqdn = ""
- try:
- fqdn = socket.getfqdn()
- except:
- try:
- fqdn = socket.gethostname()
- except:
- fqdn = ""
- return fqdn
-
-def verify_fqdn(host_name,no_host_dns=False):
-
- if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
- raise RuntimeError("Invalid hostname: " + host_name)
-
- try:
- hostaddr = socket.getaddrinfo(host_name, None)
- except:
- raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
-
- if len(hostaddr) == 0:
- raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
-
- for a in hostaddr:
- if a[4][0] == '127.0.0.1' or a[4][0] == '::1':
- raise RuntimeError("The IPA Server hostname cannot resolve to localhost (%s). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s" % (a[4][0], host_name, a[4][0]))
- try:
- revname = socket.gethostbyaddr(a[4][0])[0]
- except:
- raise RuntimeError("Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution")
- if revname != host_name:
- raise RuntimeError("The host name %s does not match the reverse lookup %s" % (host_name, revname))
-
- if no_host_dns:
- print "Warning: skipping DNS resolution of host", host_name
- return
-
- # Verify this is NOT a CNAME
- rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_CNAME)
- if len(rs) != 0:
- for rsn in rs:
- if rsn.dns_type == dnsclient.DNS_T_CNAME:
- raise RuntimeError("The IPA Server Hostname cannot be a CNAME, only A names are allowed.")
-
- # Verify that it is a DNS A record
- rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
- if len(rs) == 0:
- print "Warning: Hostname (%s) not found in DNS" % host_name
- return
-
- rec = None
- for rsn in rs:
- if rsn.dns_type == dnsclient.DNS_T_A:
- rec = rsn
- break
-
- if rec == None:
- print "Warning: Hostname (%s) not found in DNS" % host_name
- return
-
- # Compare the forward and reverse
- forward = rec.dns_name
-
- addr = socket.inet_ntoa(struct.pack('<L',rec.rdata.address))
- ipaddr = socket.inet_ntoa(struct.pack('!L',rec.rdata.address))
-
- addr = addr + ".in-addr.arpa."
- rs = dnsclient.query(addr, dnsclient.DNS_C_IN, dnsclient.DNS_T_PTR)
- if len(rs) == 0:
- raise RuntimeError("Cannot find Reverse Address for %s (%s)" % (host_name, addr))
-
- rev = None
- for rsn in rs:
- if rsn.dns_type == dnsclient.DNS_T_PTR:
- rev = rsn
- break
-
- if rev == None:
- raise RuntimeError("Cannot find Reverse Address for %s (%s)" % (host_name, addr))
-
- reverse = rev.rdata.ptrdname
-
- if forward != reverse:
- raise RuntimeError("The DNS forward record %s does not match the reverse address %s" % (forward, reverse))
-
-def port_available(port):
- """Try to bind to a port on the wildcard host
- Return 1 if the port is available
- Return 0 if the port is in use
- """
- rv = 1
-
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- fcntl.fcntl(s, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- s.bind(('', port))
- s.close()
- except socket.error, e:
- if e[0] == errno.EADDRINUSE:
- rv = 0
-
- if rv:
- try:
- s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- fcntl.fcntl(s, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- s.bind(('', port))
- s.close()
- except socket.error, e:
- if e[0] == errno.EADDRINUSE:
- rv = 0
-
- return rv
-
-def standard_logging_setup(log_filename, debug=False):
- old_umask = os.umask(077)
- # Always log everything (i.e., DEBUG) to the log
- # file.
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s %(levelname)s %(message)s',
- filename=log_filename,
- filemode='w')
- os.umask(old_umask)
-
- console = logging.StreamHandler()
- # If the debug option is set, also log debug messages to the console
- if 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 get_password(prompt):
- if os.isatty(sys.stdin.fileno()):
- return getpass.getpass(prompt)
- else:
- return sys.stdin.readline().rstrip()
-
-def read_password(user, confirm=True, validate=True):
- correct = False
- pwd = ""
- while not correct:
- pwd = get_password(user + " password: ")
- if not pwd:
- continue
- if validate and len(pwd) < 8:
- print "Password must be at least 8 characters long"
- continue
- if not confirm:
- correct = True
- continue
- pwd_confirm = get_password("Password (confirm): ")
- if pwd != pwd_confirm:
- print "Password mismatch!"
- print ""
- else:
- correct = True
- print ""
- return pwd
-
-def update_file(filename, orig, subst):
- if os.path.exists(filename):
- pattern = "%s" % re.escape(orig)
- p = re.compile(pattern)
- for line in fileinput.input(filename, inplace=1):
- if not p.search(line):
- sys.stdout.write(line)
- else:
- sys.stdout.write(p.sub(subst, line))
- fileinput.close()
- return 0
- else:
- print "File %s doesn't exist." % filename
- return 1
-
-def set_directive(filename, directive, value):
- """Set a name/value pair directive in a configuration file.
-
- This has only been tested with nss.conf
- """
- fd = open(filename)
- file = []
- for line in fd:
- if directive in line:
- file.append('%s "%s"\n' % (directive, value))
- else:
- file.append(line)
- fd.close()
-
- fd = open(filename, "w")
- fd.write("".join(file))
- fd.close()
-
-def kadmin(command):
- ipautil.run(["/usr/kerberos/sbin/kadmin.local", "-q", command])
-
-def kadmin_addprinc(principal):
- kadmin("addprinc -randkey " + principal)
-
-def kadmin_modprinc(principal, options):
- kadmin("modprinc " + options + " " + principal)
-
-def create_keytab(path, principal):
- try:
- if ipautil.file_exists(path):
- os.remove(path)
- except os.error:
- logging.critical("Failed to remove %s." % path)
-
- kadmin("ktadd -k " + path + " " + principal)
-
diff --git a/ipa-server/ipaserver/ipaldap.py b/ipa-server/ipaserver/ipaldap.py
deleted file mode 100644
index c2dbe4e2d..000000000
--- a/ipa-server/ipaserver/ipaldap.py
+++ /dev/null
@@ -1,701 +0,0 @@
-# Authors: Rich Megginson <richm@redhat.com>
-# Rob Crittenden <rcritten@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 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
-#
-
-import sys
-import os
-import os.path
-import popen2
-import base64
-import urllib
-import urllib2
-import socket
-import ldif
-import re
-import string
-import ldap
-import cStringIO
-import time
-import operator
-import struct
-import ldap.sasl
-from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
-from ldap.ldapobject import SimpleLDAPObject
-from ipa import ipaerror, ipautil
-
-# Global variable to define SASL auth
-sasl_auth = ldap.sasl.sasl({},'GSSAPI')
-
-class Entry:
- """This class represents an LDAP Entry object. An LDAP entry consists of a DN
- and a list of attributes. Each attribute consists of a name and a list of
- values. In python-ldap, entries are returned as a list of 2-tuples.
- Instance variables:
- dn - string - the string DN of the entry
- data - CIDict - case insensitive dict of the attributes and values"""
-
- def __init__(self,entrydata):
- """data is the raw data returned from the python-ldap result method, which is
- a search result entry or a reference or None.
- If creating a new empty entry, data is the string DN."""
- if entrydata:
- if isinstance(entrydata,tuple):
- self.dn = entrydata[0]
- self.data = ipautil.CIDict(entrydata[1])
- elif isinstance(entrydata,str) or isinstance(entrydata,unicode):
- self.dn = entrydata
- self.data = ipautil.CIDict()
- else:
- self.dn = ''
- self.data = ipautil.CIDict()
-
- def __nonzero__(self):
- """This allows us to do tests like if entry: returns false if there is no data,
- true otherwise"""
- return self.data != None and len(self.data) > 0
-
- def hasAttr(self,name):
- """Return True if this entry has an attribute named name, False otherwise"""
- return self.data and self.data.has_key(name)
-
- def __getattr__(self,name):
- """If name is the name of an LDAP attribute, return the first value for that
- attribute - equivalent to getValue - this allows the use of
- entry.cn
- instead of
- entry.getValue('cn')
- This also allows us to return None if an attribute is not found rather than
- throwing an exception"""
- return self.getValue(name)
-
- def getValues(self,name):
- """Get the list (array) of values for the attribute named name"""
- return self.data.get(name)
-
- def getValue(self,name):
- """Get the first value for the attribute named name"""
- return self.data.get(name,[None])[0]
-
- def setValue(self,name,*value):
- """Value passed in may be a single value, several values, or a single sequence.
- For example:
- ent.setValue('name', 'value')
- ent.setValue('name', 'value1', 'value2', ..., 'valueN')
- ent.setValue('name', ['value1', 'value2', ..., 'valueN'])
- ent.setValue('name', ('value1', 'value2', ..., 'valueN'))
- Since *value is a tuple, we may have to extract a list or tuple from that
- tuple as in the last two examples above"""
- if isinstance(value[0],list) or isinstance(value[0],tuple):
- self.data[name] = value[0]
- else:
- self.data[name] = value
-
- setValues = setValue
-
- def toTupleList(self):
- """Convert the attrs and values to a list of 2-tuples. The first element
- of the tuple is the attribute name. The second element is either a
- single value or a list of values."""
- return self.data.items()
-
- def __str__(self):
- """Convert the Entry to its LDIF representation"""
- return self.__repr__()
-
- # the ldif class base64 encodes some attrs which I would rather see in raw form - to
- # encode specific attrs as base64, add them to the list below
- ldif.safe_string_re = re.compile('^$')
- base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData']
-
- def __repr__(self):
- """Convert the Entry to its LDIF representation"""
- sio = cStringIO.StringIO()
- # what's all this then? the unparse method will currently only accept
- # a list or a dict, not a class derived from them. self.data is a
- # cidict, so unparse barfs on it. I've filed a bug against python-ldap,
- # but in the meantime, we have to convert to a plain old dict for printing
- # I also don't want to see wrapping, so set the line width really high (1000)
- newdata = {}
- newdata.update(self.data)
- ldif.LDIFWriter(sio,Entry.base64_attrs,1000).unparse(self.dn,newdata)
- return sio.getvalue()
-
-def wrapper(f,name):
- """This is the method that wraps all of the methods of the superclass. This seems
- to need to be an unbound method, that's why it's outside of IPAdmin. Perhaps there
- is some way to do this with the new classmethod or staticmethod of 2.4.
- Basically, we replace every call to a method in SimpleLDAPObject (the superclass
- of IPAdmin) with a call to inner. The f argument to wrapper is the bound method
- of IPAdmin (which is inherited from the superclass). Bound means that it will implicitly
- be called with the self argument, it is not in the args list. name is the name of
- the method to call. If name is a method that returns entry objects (e.g. result),
- we wrap the data returned by an Entry class. If name is a method that takes an entry
- argument, we extract the raw data from the entry object to pass in."""
- def inner(*args, **kargs):
- if name == 'result':
- type, data = f(*args, **kargs)
- # data is either a 2-tuple or a list of 2-tuples
- # print data
- if data:
- if isinstance(data,tuple):
- return type, Entry(data)
- elif isinstance(data,list):
- return type, [Entry(x) for x in data]
- else:
- raise TypeError, "unknown data type %s returned by result" % type(data)
- else:
- return type, data
- elif name.startswith('add'):
- # the first arg is self
- # the second and third arg are the dn and the data to send
- # We need to convert the Entry into the format used by
- # python-ldap
- ent = args[0]
- if isinstance(ent,Entry):
- return f(ent.dn, ent.toTupleList(), *args[2:])
- else:
- return f(*args, **kargs)
- else:
- return f(*args, **kargs)
- return inner
-
-class LDIFConn(ldif.LDIFParser):
- def __init__(
- self,
- input_file,
- ignored_attr_types=None,max_entries=0,process_url_schemes=None
- ):
- """
- See LDIFParser.__init__()
-
- Additional Parameters:
- all_records
- List instance for storing parsed records
- """
- self.dndict = {} # maps dn to Entry
- self.dnlist = [] # contains entries in order read
- myfile = input_file
- if isinstance(input_file,str) or isinstance(input_file,unicode):
- myfile = open(input_file, "r")
- ldif.LDIFParser.__init__(self,myfile,ignored_attr_types,max_entries,process_url_schemes)
- self.parse()
- if isinstance(input_file,str) or isinstance(input_file,unicode):
- myfile.close()
-
- def handle(self,dn,entry):
- """
- Append single record to dictionary of all records.
- """
- if not dn:
- dn = ''
- newentry = Entry((dn, entry))
- self.dndict[IPAdmin.normalizeDN(dn)] = newentry
- self.dnlist.append(newentry)
-
- def get(self,dn):
- ndn = IPAdmin.normalizeDN(dn)
- return self.dndict.get(ndn, Entry(None))
-
-class IPAdmin(SimpleLDAPObject):
- CFGSUFFIX = "o=NetscapeRoot"
- DEFAULT_USER_ID = "nobody"
-
- def getDseAttr(self,attrname):
- conffile = self.confdir + '/dse.ldif'
- dseldif = LDIFConn(conffile)
- cnconfig = dseldif.get("cn=config")
- if cnconfig:
- return cnconfig.getValue(attrname)
- return None
-
- def __initPart2(self):
- if self.binddn and len(self.binddn) and not hasattr(self,'sroot'):
- try:
- ent = self.getEntry('cn=config', ldap.SCOPE_BASE, '(objectclass=*)',
- [ 'nsslapd-instancedir', 'nsslapd-errorlog',
- 'nsslapd-certdir', 'nsslapd-schemadir' ])
- self.errlog = ent.getValue('nsslapd-errorlog')
- self.confdir = ent.getValue('nsslapd-certdir')
- if not self.confdir:
- self.confdir = ent.getValue('nsslapd-schemadir')
- if self.confdir:
- self.confdir = os.path.dirname(self.confdir)
- instdir = ent.getValue('nsslapd-instancedir')
- ent = self.getEntry('cn=config,cn=ldbm database,cn=plugins,cn=config',
- ldap.SCOPE_BASE, '(objectclass=*)',
- [ 'nsslapd-directory' ])
- self.dbdir = os.path.dirname(ent.getValue('nsslapd-directory'))
- except (ldap.INSUFFICIENT_ACCESS, ldap.CONNECT_ERROR):
- pass # usually means
- except ldap.OPERATIONS_ERROR, e:
- pass # usually means this is Active Directory
- except ldap.LDAPError, e:
- print "caught exception ", e
- raise
-
- def __localinit__(self):
- """If a CA certificate is provided then it is assumed that we are
- doing SSL client authentication with proxy auth.
-
- If a CA certificate is not present then it is assumed that we are
- using a forwarded kerberos ticket for SASL auth. SASL provides
- its own encryption.
- """
- if self.cacert is not None:
- SimpleLDAPObject.__init__(self,'ldaps://%s:%d' % (self.host,self.port))
- else:
- SimpleLDAPObject.__init__(self,'ldap://%s:%d' % (self.host,self.port))
-
- def __init__(self,host,port=389,cacert=None,bindcert=None,bindkey=None,proxydn=None,debug=None):
- """We just set our instance variables and wrap the methods - the real
- work is done in __localinit__ and __initPart2 - these are separated
- out this way so that we can call them from places other than
- instance creation e.g. when we just need to reconnect, not create a
- new instance"""
- if debug and debug.lower() == "on":
- ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
- if cacert is not None:
- ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,cacert)
- if bindcert is not None:
- ldap.set_option(ldap.OPT_X_TLS_CERTFILE,bindcert)
- if bindkey is not None:
- ldap.set_option(ldap.OPT_X_TLS_KEYFILE,bindkey)
-
- self.__wrapmethods()
- self.port = port
- self.host = host
- self.cacert = cacert
- self.bindcert = bindcert
- self.bindkey = bindkey
- self.proxydn = proxydn
- self.suffixes = {}
- self.__localinit__()
-
- def __str__(self):
- return self.host + ":" + str(self.port)
-
- def __get_server_controls__(self):
- """Create the proxy user server control. The control has the form
- 0x04 = Octet String
- 4|0x80 sets the length of the string length field at 4 bytes
- the struct() gets us the length in bytes of string self.proxydn
- self.proxydn is the proxy dn to send"""
-
- import sys
-
- if self.proxydn is not None:
- proxydn = chr(0x04) + chr(4|0x80) + struct.pack('l', socket.htonl(len(self.proxydn))) + self.proxydn;
-
- # Create the proxy control
- sctrl=[]
- sctrl.append(LDAPControl('2.16.840.1.113730.3.4.18',True,proxydn))
- else:
- sctrl=None
-
- return sctrl
-
- def toLDAPURL(self):
- return "ldap://%s:%d/" % (self.host,self.port)
-
- def set_proxydn(self, proxydn):
- self.proxydn = proxydn
-
- def set_krbccache(self, krbccache, principal):
- if krbccache is not None:
- os.environ["KRB5CCNAME"] = krbccache
- self.sasl_interactive_bind_s("", sasl_auth)
- self.principal = principal
- self.proxydn = None
-
- def do_simple_bind(self, binddn="cn=directory manager", bindpw=""):
- self.binddn = binddn
- self.bindpwd = bindpw
- self.simple_bind_s(binddn, bindpw)
- self.__initPart2()
-
- def getEntry(self,*args):
- """This wraps the search function. It is common to just get one entry"""
-
- sctrl = self.__get_server_controls__()
-
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
-
- try:
- res = self.search(*args)
- type, obj = self.result(res)
- except ldap.NO_SUCH_OBJECT:
- raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
- notfound(args))
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
-
- if not obj:
- raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
- notfound(args))
- elif isinstance(obj,Entry):
- return obj
- else: # assume list/tuple
- return obj[0]
-
- def getList(self,*args):
- """This wraps the search function to find all users."""
-
- sctrl = self.__get_server_controls__()
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
-
- try:
- res = self.search(*args)
- type, obj = self.result(res)
- except (ldap.ADMINLIMIT_EXCEEDED, ldap.SIZELIMIT_EXCEEDED), e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR,
- "Too many results returned by search", e)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
-
- if not obj:
- raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
- notfound(args))
-
- all_users = []
- for s in obj:
- all_users.append(s)
-
- return all_users
-
- def getListAsync(self,*args):
- """This version performs an asynchronous search, to allow
- results even if we hit a limit.
-
- It returns a list: counter followed by the results.
- If the results are truncated, counter will be set to -1.
- """
-
- sctrl = self.__get_server_controls__()
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
-
- entries = []
- partial = 0
-
- try:
- msgid = self.search_ext(*args)
- type, result_list = self.result(msgid, 0)
- while result_list:
- for result in result_list:
- entries.append(result)
- type, result_list = self.result(msgid, 0)
- except (ldap.ADMINLIMIT_EXCEEDED, ldap.SIZELIMIT_EXCEEDED,
- ldap.TIMELIMIT_EXCEEDED), e:
- partial = 1
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
-
- if not entries:
- raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
- notfound(args))
-
- if partial == 1:
- counter = -1
- else:
- counter = len(entries)
-
- return [counter] + entries
-
- def addEntry(self,*args):
- """This wraps the add function. It assumes that the entry is already
- populated with all of the desired objectclasses and attributes"""
-
- sctrl = self.__get_server_controls__()
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.add_s(*args)
- except ldap.ALREADY_EXISTS:
- raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def updateRDN(self, dn, newrdn):
- """Wrap the modrdn function."""
-
- sctrl = self.__get_server_controls__()
-
- if dn == newrdn:
- # no need to report an error
- return "Success"
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.modrdn_s(dn, newrdn, delold=1)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def updateEntry(self,dn,olduser,newuser):
- """This wraps the mod function. It assumes that the entry is already
- populated with all of the desired objectclasses and attributes"""
-
- sctrl = self.__get_server_controls__()
-
- modlist = self.generateModList(olduser, newuser)
-
- if len(modlist) == 0:
- raise ipaerror.gen_exception(ipaerror.LDAP_EMPTY_MODLIST)
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.modify_s(dn, modlist)
- # this is raised when a 'delete' attribute isn't found.
- # it indicates the previous attribute was removed by another
- # update, making the olduser stale.
- except ldap.NO_SUCH_ATTRIBUTE:
- raise ipaerror.gen_exception(ipaerror.LDAP_MIDAIR_COLLISION)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def generateModList(self, old_entry, new_entry):
- """A mod list generator that computes more precise modification lists
- than the python-ldap version. This version purposely generates no
- REPLACE operations, to deal with multi-user updates more properly."""
- modlist = []
-
- old_entry = ipautil.CIDict(old_entry)
- new_entry = ipautil.CIDict(new_entry)
-
- keys = set(map(string.lower, old_entry.keys()))
- keys.update(map(string.lower, new_entry.keys()))
-
- for key in keys:
- new_values = new_entry.get(key, [])
- if not(isinstance(new_values,list) or isinstance(new_values,tuple)):
- new_values = [new_values]
- new_values = filter(lambda value:value!=None, new_values)
- new_values = set(new_values)
-
- old_values = old_entry.get(key, [])
- if not(isinstance(old_values,list) or isinstance(old_values,tuple)):
- old_values = [old_values]
- old_values = filter(lambda value:value!=None, old_values)
- old_values = set(old_values)
-
- adds = list(new_values.difference(old_values))
- removes = list(old_values.difference(new_values))
-
- if len(removes) > 0:
- modlist.append((ldap.MOD_DELETE, key, removes))
- if len(adds) > 0:
- modlist.append((ldap.MOD_ADD, key, adds))
-
- return modlist
-
- def inactivateEntry(self,dn,has_key):
- """Rather than deleting entries we mark them as inactive.
- has_key defines whether the entry already has nsAccountlock
- set so we can determine which type of mod operation to run."""
-
- sctrl = self.__get_server_controls__()
- modlist=[]
-
- if has_key == True:
- operation = ldap.MOD_REPLACE
- else:
- operation = ldap.MOD_ADD
-
- modlist.append((operation, "nsAccountlock", "true"))
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.modify_s(dn, modlist)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def deleteEntry(self,*args):
- """This wraps the delete function. Use with caution."""
-
- sctrl = self.__get_server_controls__()
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.delete_s(*args)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def modifyPassword(self,dn,oldpass,newpass):
- """Set the user password using RFC 3062, LDAP Password Modify Extended
- Operation. This ends up calling the IPA password slapi plugin
- handler so the Kerberos password gets set properly.
-
- oldpass is not mandatory
- """
-
- sctrl = self.__get_server_controls__()
-
- try:
- if sctrl is not None:
- self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
- self.passwd_s(dn, oldpass, newpass)
- except ldap.LDAPError, e:
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
- return "Success"
-
- def __wrapmethods(self):
- """This wraps all methods of SimpleLDAPObject, so that we can intercept
- the methods that deal with entries. Instead of using a raw list of tuples
- of lists of hashes of arrays as the entry object, we want to wrap entries
- in an Entry class that provides some useful methods"""
- for name in dir(self.__class__.__bases__[0]):
- attr = getattr(self, name)
- if callable(attr):
- setattr(self, name, wrapper(attr, name))
-
- def exportLDIF(self, file, suffix, forrepl=False, verbose=False):
- cn = "export" + str(int(time.time()))
- dn = "cn=%s, cn=export, cn=tasks, cn=config" % cn
- entry = Entry(dn)
- entry.setValues('objectclass', 'top', 'extensibleObject')
- entry.setValues('cn', cn)
- entry.setValues('nsFilename', file)
- entry.setValues('nsIncludeSuffix', suffix)
- if forrepl:
- entry.setValues('nsExportReplica', 'true')
-
- rc = self.startTaskAndWait(entry, verbose)
-
- if rc:
- if verbose:
- print "Error: export task %s for file %s exited with %d" % (cn,file,rc)
- else:
- if verbose:
- print "Export task %s for file %s completed successfully" % (cn,file)
- return rc
-
- def waitForEntry(self, dn, timeout=7200, attr='', quiet=True):
- scope = ldap.SCOPE_BASE
- filter = "(objectclass=*)"
- attrlist = []
- if attr:
- filter = "(%s=*)" % attr
- attrlist.append(attr)
- timeout += int(time.time())
-
- if isinstance(dn,Entry):
- dn = dn.dn
-
- # wait for entry and/or attr to show up
- if not quiet:
- sys.stdout.write("Waiting for %s %s:%s " % (self,dn,attr))
- sys.stdout.flush()
- entry = None
- while not entry and int(time.time()) < timeout:
- try:
- entry = self.getEntry(dn, scope, filter, attrlist)
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- pass # found entry, but no attr
- except ldap.NO_SUCH_OBJECT:
- pass # no entry yet
- except ldap.LDAPError, e: # badness
- print "\nError reading entry", dn, e
- break
- if not entry:
- if not quiet:
- sys.stdout.write(".")
- sys.stdout.flush()
- time.sleep(1)
-
- if not entry and int(time.time()) > timeout:
- print "\nwaitForEntry timeout for %s for %s" % (self,dn)
- elif entry and not quiet:
- print "\nThe waited for entry is:", entry
- elif not entry:
- print "\nError: could not read entry %s from %s" % (dn,self)
-
- return entry
-
- def addSchema(self, attr, val):
- dn = "cn=schema"
- self.modify_s(dn, [(ldap.MOD_ADD, attr, val)])
-
- def addAttr(self, *args):
- return self.addSchema('attributeTypes', args)
-
- def addObjClass(self, *args):
- return self.addSchema('objectClasses', args)
-
- ###########################
- # Static methods start here
- ###########################
- def normalizeDN(dn):
- # not great, but will do until we use a newer version of python-ldap
- # that has DN utilities
- ary = ldap.explode_dn(dn.lower())
- return ",".join(ary)
- normalizeDN = staticmethod(normalizeDN)
-
- def getfqdn(name=''):
- return socket.getfqdn(name)
- getfqdn = staticmethod(getfqdn)
-
- def getdomainname(name=''):
- fqdn = IPAdmin.getfqdn(name)
- index = fqdn.find('.')
- if index >= 0:
- return fqdn[index+1:]
- else:
- return fqdn
- getdomainname = staticmethod(getdomainname)
-
- def getdefaultsuffix(name=''):
- dm = IPAdmin.getdomainname(name)
- if dm:
- return "dc=" + dm.replace('.', ', dc=')
- else:
- return 'dc=localdomain'
- getdefaultsuffix = staticmethod(getdefaultsuffix)
-
- def is_a_dn(dn):
- """Returns True if the given string is a DN, False otherwise."""
- return (dn.find("=") > 0)
- is_a_dn = staticmethod(is_a_dn)
-
-
-def notfound(args):
- """Return a string suitable for displaying as an error when a
- search returns no results.
-
- This just returns whatever is after the equals sign"""
- if len(args) > 2:
- filter = args[2]
- try:
- target = re.match(r'\(.*=(.*)\)', filter).group(1)
- except:
- target = filter
- return "%s not found" % str(target)
- else:
- return args[0]
diff --git a/ipa-server/ipaserver/krbinstance.py b/ipa-server/ipaserver/krbinstance.py
deleted file mode 100644
index 252844304..000000000
--- a/ipa-server/ipaserver/krbinstance.py
+++ /dev/null
@@ -1,428 +0,0 @@
-# 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 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
-#
-
-import subprocess
-import string
-import tempfile
-import shutil
-import logging
-import fileinput
-import re
-import sys
-import os
-import pwd
-import socket
-import shutil
-
-import service
-import installutils
-from ipa import sysrestore
-from ipa import ipautil
-from ipa import ipaerror
-
-import ipaldap
-
-import ldap
-from ldap import LDAPError
-from ldap import ldapobject
-
-from pyasn1.type import univ, namedtype
-import pyasn1.codec.ber.encoder
-import pyasn1.codec.ber.decoder
-import struct
-import base64
-
-KRBMKEY_DENY_ACI = """
-(targetattr = "krbMKey")(version 3.0; acl "No external access"; deny (all) userdn != "ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";)
-"""
-
-def update_key_val_in_file(filename, key, val):
- if os.path.exists(filename):
- pattern = "^[\s#]*%s\s*=\s*%s\s*" % (re.escape(key), re.escape(val))
- p = re.compile(pattern)
- for line in fileinput.input(filename):
- if p.search(line):
- fileinput.close()
- return
- fileinput.close()
-
- pattern = "^[\s#]*%s\s*=" % re.escape(key)
- p = re.compile(pattern)
- for line in fileinput.input(filename, inplace=1):
- if not p.search(line):
- sys.stdout.write(line)
- fileinput.close()
- f = open(filename, "a")
- f.write("%s=%s\n" % (key, val))
- f.close()
-
-class KpasswdInstance(service.SimpleServiceInstance):
- def __init__(self):
- service.SimpleServiceInstance.__init__(self, "ipa_kpasswd")
-
-class KrbInstance(service.Service):
- def __init__(self, fstore=None):
- service.Service.__init__(self, "krb5kdc")
- self.ds_user = None
- self.fqdn = None
- self.realm = None
- self.domain = None
- self.host = None
- self.admin_password = None
- self.master_password = None
- self.suffix = None
- self.kdc_password = None
- self.sub_dict = None
-
- self.kpasswd = KpasswdInstance()
-
- if fstore:
- self.fstore = fstore
- else:
- self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
-
- def __common_setup(self, ds_user, realm_name, host_name, domain_name, admin_password):
- self.ds_user = ds_user
- self.fqdn = host_name
- self.realm = realm_name.upper()
- self.host = host_name.split(".")[0]
- self.ip = socket.gethostbyname(host_name)
- self.domain = domain_name
- self.suffix = ipautil.realm_to_suffix(self.realm)
- self.kdc_password = ipautil.ipa_generate_password()
- self.admin_password = admin_password
-
- self.__setup_sub_dict()
-
- # get a connection to the DS
- try:
- self.conn = ipaldap.IPAdmin(self.fqdn)
- self.conn.do_simple_bind(bindpw=self.admin_password)
- except Exception, e:
- logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
- raise e
-
- self.backup_state("running", self.is_running())
- try:
- self.stop()
- except:
- # It could have been not running
- pass
-
- def __common_post_setup(self):
- self.step("starting the KDC", self.__start_instance)
- self.step("configuring KDC to start on boot", self.__enable)
-
- def create_instance(self, ds_user, realm_name, host_name, domain_name, admin_password, master_password):
- self.master_password = master_password
-
- self.__common_setup(ds_user, realm_name, host_name, domain_name, admin_password)
-
- self.step("setting KDC account password", self.__configure_kdc_account_password)
- self.step("adding sasl mappings to the directory", self.__configure_sasl_mappings)
- self.step("adding kerberos entries to the DS", self.__add_krb_entries)
- self.step("adding default ACIs", self.__add_default_acis)
- self.step("configuring KDC", self.__create_instance)
- self.step("adding default keytypes", self.__add_default_keytypes)
- self.step("creating a keytab for the directory", self.__create_ds_keytab)
- self.step("creating a keytab for the machine", self.__create_host_keytab)
- self.step("exporting the kadmin keytab", self.__export_kadmin_changepw_keytab)
- self.step("adding the password extension to the directory", self.__add_pwd_extop_module)
- self.step("adding the kerberos master key to the directory", self.__add_master_key)
-
- self.__common_post_setup()
-
- self.start_creation("Configuring Kerberos KDC")
-
- self.kpasswd.create_instance()
-
- def create_replica(self, ds_user, realm_name, host_name, domain_name, admin_password, ldap_passwd_filename, kpasswd_filename):
- self.__copy_ldap_passwd(ldap_passwd_filename)
- self.__copy_kpasswd_keytab(kpasswd_filename)
-
- self.__common_setup(ds_user, realm_name, host_name, domain_name, admin_password)
-
- self.step("adding sasl mappings to the directory", self.__configure_sasl_mappings)
- self.step("writing stash file from DS", self.__write_stash_from_ds)
- self.step("configuring KDC", self.__create_replica_instance)
- self.step("creating a keytab for the directory", self.__create_ds_keytab)
- self.step("creating a keytab for the machine", self.__create_host_keytab)
- self.step("adding the password extension to the directory", self.__add_pwd_extop_module)
-
- self.__common_post_setup()
-
- self.start_creation("Configuring Kerberos KDC")
-
- self.kpasswd.create_instance()
-
- def __copy_ldap_passwd(self, filename):
- self.fstore.backup_file("/var/kerberos/krb5kdc/ldappwd")
- shutil.copy(filename, "/var/kerberos/krb5kdc/ldappwd")
- os.chmod("/var/kerberos/krb5kdc/ldappwd", 0600)
-
- def __copy_kpasswd_keytab(self, filename):
- self.fstore.backup_file("/var/kerberos/krb5kdc/kpasswd.keytab")
- shutil.copy(filename, "/var/kerberos/krb5kdc/kpasswd.keytab")
- os.chmod("/var/kerberos/krb5kdc/kpasswd.keytab", 0600)
-
-
- def __configure_kdc_account_password(self):
- hexpwd = ''
- for x in self.kdc_password:
- hexpwd += (hex(ord(x))[2:])
- self.fstore.backup_file("/var/kerberos/krb5kdc/ldappwd")
- pwd_fd = open("/var/kerberos/krb5kdc/ldappwd", "w")
- pwd_fd.write("uid=kdc,cn=sysaccounts,cn=etc,"+self.suffix+"#{HEX}"+hexpwd+"\n")
- pwd_fd.close()
- os.chmod("/var/kerberos/krb5kdc/ldappwd", 0600)
-
- def __enable(self):
- self.backup_state("enabled", self.is_enabled())
- self.chkconfig_on()
-
- def __start_instance(self):
- try:
- self.start()
- except:
- logging.critical("krb5kdc service failed to start")
-
- def __setup_sub_dict(self):
- self.sub_dict = dict(FQDN=self.fqdn,
- IP=self.ip,
- PASSWORD=self.kdc_password,
- SUFFIX=self.suffix,
- DOMAIN=self.domain,
- HOST=self.host,
- REALM=self.realm)
-
- def __ldap_mod(self, ldif):
- txt = ipautil.template_file(ipautil.SHARE_DIR + ldif, self.sub_dict)
- fd = ipautil.write_tmp_file(txt)
-
- [pw_fd, pw_name] = tempfile.mkstemp()
- os.write(pw_fd, self.admin_password)
- os.close(pw_fd)
-
- args = ["/usr/bin/ldapmodify", "-h", "127.0.0.1", "-xv",
- "-D", "cn=Directory Manager", "-y", pw_name, "-f", fd.name]
-
- try:
- try:
- ipautil.run(args)
- except ipautil.CalledProcessError, e:
- logging.critical("Failed to load %s: %s" % (ldif, str(e)))
- finally:
- os.remove(pw_name)
-
- fd.close()
-
- def __configure_sasl_mappings(self):
- # we need to remove any existing SASL mappings in the directory as otherwise they
- # they may conflict. There is no way to define the order they are used in atm.
-
- # FIXME: for some reason IPAdmin dies here, so we switch
- # it out for a regular ldapobject.
- conn = self.conn
- self.conn = ldapobject.SimpleLDAPObject("ldap://127.0.0.1/")
- self.conn.bind("cn=directory manager", self.admin_password)
- try:
- msgid = self.conn.search("cn=mapping,cn=sasl,cn=config", ldap.SCOPE_ONELEVEL, "(objectclass=nsSaslMapping)")
- res = self.conn.result(msgid)
- for r in res[1]:
- mid = self.conn.delete_s(r[0])
- #except LDAPError, e:
- # logging.critical("Error during SASL mapping removal: %s" % str(e))
- except Exception, e:
- logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
- raise e
- print type(e)
- print dir(e)
- raise e
-
- self.conn = conn
-
- entry = ipaldap.Entry("cn=Full Principal,cn=mapping,cn=sasl,cn=config")
- entry.setValues("objectclass", "top", "nsSaslMapping")
- entry.setValues("cn", "Full Principal")
- entry.setValues("nsSaslMapRegexString", '\(.*\)@\(.*\)')
- entry.setValues("nsSaslMapBaseDNTemplate", self.suffix)
- entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=\\1@\\2)')
-
- try:
- self.conn.add_s(entry)
- except ldap.ALREADY_EXISTS:
- logging.critical("failed to add Full Principal Sasl mapping")
- raise e
-
- entry = ipaldap.Entry("cn=Name Only,cn=mapping,cn=sasl,cn=config")
- entry.setValues("objectclass", "top", "nsSaslMapping")
- entry.setValues("cn", "Name Only")
- entry.setValues("nsSaslMapRegexString", '\(.*\)')
- entry.setValues("nsSaslMapBaseDNTemplate", self.suffix)
- entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=\\1@%s)' % self.realm)
-
- try:
- self.conn.add_s(entry)
- except ldap.ALREADY_EXISTS:
- logging.critical("failed to add Name Only Sasl mapping")
- raise e
-
- def __add_krb_entries(self):
- self.__ldap_mod("kerberos.ldif")
-
- def __add_default_acis(self):
- self.__ldap_mod("default-aci.ldif")
-
- def __add_default_keytypes(self):
- self.__ldap_mod("default-keytypes.ldif")
-
- def __create_replica_instance(self):
- self.__create_instance(replica=True)
-
- def __template_file(self, path):
- template = os.path.join(ipautil.SHARE_DIR, os.path.basename(path) + ".template")
- conf = ipautil.template_file(template, self.sub_dict)
- self.fstore.backup_file(path)
- fd = open(path, "w+")
- fd.write(conf)
- fd.close()
-
- def __create_instance(self, replica=False):
- self.__template_file("/var/kerberos/krb5kdc/kdc.conf")
- self.__template_file("/etc/krb5.conf")
- self.__template_file("/usr/share/ipa/html/krb5.ini")
- self.__template_file("/usr/share/ipa/html/krb.con")
- self.__template_file("/usr/share/ipa/html/krbrealm.con")
-
- if not replica:
- #populate the directory with the realm structure
- args = ["/usr/kerberos/sbin/kdb5_ldap_util", "-D", "uid=kdc,cn=sysaccounts,cn=etc,"+self.suffix, "-w", self.kdc_password, "create", "-s", "-P", self.master_password, "-r", self.realm, "-subtrees", self.suffix, "-sscope", "sub"]
- try:
- ipautil.run(args)
- except ipautil.CalledProcessError, e:
- print "Failed to populate the realm structure in kerberos", e
-
- def __write_stash_from_ds(self):
- try:
- entry = self.conn.getEntry("cn=%s, cn=kerberos, %s" % (self.realm, self.suffix), ldap.SCOPE_SUBTREE)
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND), e:
- logging.critical("Could not find master key in DS")
- raise e
-
- krbMKey = pyasn1.codec.ber.decoder.decode(entry.krbmkey)
- keytype = int(krbMKey[0][1][0])
- keydata = str(krbMKey[0][1][1])
-
- format = '=hi%ss' % len(keydata)
- s = struct.pack(format, keytype, len(keydata), keydata)
- try:
- fd = open("/var/kerberos/krb5kdc/.k5."+self.realm, "w")
- fd.write(s)
- fd.close()
- except os.error, e:
- logging.critical("failed to write stash file")
- raise e
-
- #add the password extop module
- def __add_pwd_extop_module(self):
- self.__ldap_mod("pwd-extop-conf.ldif")
-
- def __add_master_key(self):
- #get the Master Key from the stash file
- try:
- stash = open("/var/kerberos/krb5kdc/.k5."+self.realm, "r")
- keytype = struct.unpack('h', stash.read(2))[0]
- keylen = struct.unpack('i', stash.read(4))[0]
- keydata = stash.read(keylen)
- except os.error:
- logging.critical("Failed to retrieve Master Key from Stash file: %s")
- #encode it in the asn.1 attribute
- MasterKey = univ.Sequence()
- MasterKey.setComponentByPosition(0, univ.Integer(keytype))
- MasterKey.setComponentByPosition(1, univ.OctetString(keydata))
- krbMKey = univ.Sequence()
- krbMKey.setComponentByPosition(0, univ.Integer(0)) #we have no kvno
- krbMKey.setComponentByPosition(1, MasterKey)
- asn1key = pyasn1.codec.ber.encoder.encode(krbMKey)
-
- dn = "cn="+self.realm+",cn=kerberos,"+self.suffix
- #protect the master key by adding an appropriate deny rule along with the key
- mod = [(ldap.MOD_ADD, 'aci', ipautil.template_str(KRBMKEY_DENY_ACI, self.sub_dict)),
- (ldap.MOD_ADD, 'krbMKey', str(asn1key))]
- try:
- self.conn.modify_s(dn, mod)
- except ldap.TYPE_OR_VALUE_EXISTS, e:
- logging.critical("failed to add master key to kerberos database\n")
- raise e
-
- def __create_ds_keytab(self):
- ldap_principal = "ldap/" + self.fqdn + "@" + self.realm
- installutils.kadmin_addprinc(ldap_principal)
-
- self.fstore.backup_file("/etc/dirsrv/ds.keytab")
- installutils.create_keytab("/etc/dirsrv/ds.keytab", ldap_principal)
-
- self.fstore.backup_file("/etc/sysconfig/dirsrv")
- update_key_val_in_file("/etc/sysconfig/dirsrv", "export KRB5_KTNAME", "/etc/dirsrv/ds.keytab")
- pent = pwd.getpwnam(self.ds_user)
- os.chown("/etc/dirsrv/ds.keytab", pent.pw_uid, pent.pw_gid)
-
- def __create_host_keytab(self):
- host_principal = "host/" + self.fqdn + "@" + self.realm
- installutils.kadmin_addprinc(host_principal)
-
- self.fstore.backup_file("/etc/krb5.keytab")
- installutils.create_keytab("/etc/krb5.keytab", host_principal)
-
- # Make sure access is strictly reserved to root only for now
- os.chown("/etc/krb5.keytab", 0, 0)
- os.chmod("/etc/krb5.keytab", 0600)
-
- def __export_kadmin_changepw_keytab(self):
- installutils.kadmin_modprinc("kadmin/changepw", "+requires_preauth")
-
- self.fstore.backup_file("/var/kerberos/krb5kdc/kpasswd.keytab")
- installutils.create_keytab("/var/kerberos/krb5kdc/kpasswd.keytab", "kadmin/changepw")
-
- self.fstore.backup_file("/etc/sysconfig/ipa_kpasswd")
- update_key_val_in_file("/etc/sysconfig/ipa_kpasswd", "export KRB5_KTNAME", "/var/kerberos/krb5kdc/kpasswd.keytab")
-
- def uninstall(self):
- self.kpasswd.uninstall()
-
- running = self.restore_state("running")
- enabled = self.restore_state("enabled")
-
- try:
- self.stop()
- except:
- pass
-
- for f in ["/var/kerberos/krb5kdc/ldappwd", "/var/kerberos/krb5kdc/kdc.conf", "/etc/krb5.conf"]:
- try:
- self.fstore.restore_file(f)
- except ValueError, error:
- logging.debug(error)
- pass
-
- if not enabled is None and not enabled:
- self.chkconfig_off()
-
- if not running is None and running:
- self.start()
diff --git a/ipa-server/ipaserver/ldapupdate.py b/ipa-server/ipaserver/ldapupdate.py
deleted file mode 100755
index cdf23125a..000000000
--- a/ipa-server/ipaserver/ldapupdate.py
+++ /dev/null
@@ -1,593 +0,0 @@
-# Authors: Rob Crittenden <rcritten@redhat.com>
-#
-# Copyright (C) 2008 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
-#
-
-# Documentation can be found at http://freeipa.org/page/LdapUpdate
-
-# TODO
-# save undo files?
-
-UPDATES_DIR="/usr/share/ipa/updates/"
-
-import sys
-from ipaserver import ipaldap, installutils
-from ipa import entity, ipaerror, ipautil
-import ldap
-import logging
-import krbV
-import platform
-import shlex
-import time
-import random
-import os
-import fnmatch
-
-class BadSyntax(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-class LDAPUpdate:
- def __init__(self, dm_password, sub_dict={}, live_run=True):
- """dm_password = Directory Manager password
- sub_dict = substitution dictionary
- live_run = Apply the changes or just test
- """
- self.sub_dict = sub_dict
- self.live_run = live_run
- self.dm_password = dm_password
- self.conn = None
- self.modified = False
-
- krbctx = krbV.default_context()
-
- fqdn = installutils.get_fqdn()
- if fqdn is None:
- raise RuntimeError("Unable to determine hostname")
-
- domain = ipautil.get_domain_name()
- libarch = self.__identify_arch()
- suffix = ipautil.realm_to_suffix(krbctx.default_realm)
-
- if not self.sub_dict.get("REALM"):
- self.sub_dict["REALM"] = krbctx.default_realm
- if not self.sub_dict.get("FQDN"):
- self.sub_dict["FQDN"] = fqdn
- if not self.sub_dict.get("DOMAIN"):
- self.sub_dict["DOMAIN"] = domain
- if not self.sub_dict.get("SUFFIX"):
- self.sub_dict["SUFFIX"] = suffix
- if not self.sub_dict.get("LIBARCH"):
- self.sub_dict["LIBARCH"] = libarch
- if not self.sub_dict.get("TIME"):
- self.sub_dict["TIME"] = int(time.time())
-
- # Try out the password
- try:
- conn = ipaldap.IPAdmin(fqdn)
- conn.do_simple_bind(bindpw=self.dm_password)
- conn.unbind()
- except ldap.CONNECT_ERROR, e:
- raise RuntimeError("Unable to connect to LDAP server %s" % fqdn)
- except ldap.SERVER_DOWN, e:
- raise RuntimeError("Unable to connect to LDAP server %s" % fqdn)
- except ldap.INVALID_CREDENTIALS, e :
- raise RuntimeError("The password provided is incorrect for LDAP server %s" % fqdn)
-
- def __detail_error(self, detail):
- """IPA returns two errors back. One a generic one indicating the broad
- problem and a detailed message back as well which should have come
- from LDAP. This function will parse that into a human-readable
- string.
- """
- msg = ""
- desc = detail[0].get('desc')
- info = detail[0].get('info')
-
- if desc:
- msg = desc
- if info:
- msg = msg + " " + info
-
- return msg
-
- def __identify_arch(self):
- """On multi-arch systems some libraries may be in /lib64, /usr/lib64,
- etc. Determine if a suffix is needed based on the current
- architecture.
- """
- bits = platform.architecture()[0]
-
- if bits == "64bit":
- return "64"
- else:
- return ""
-
- def __template_str(self, s):
- try:
- return ipautil.template_str(s, self.sub_dict)
- except KeyError, e:
- raise BadSyntax("Unknown template keyword %s" % e)
-
- def __remove_quotes(self, line):
- """Remove leading and trailng double or single quotes"""
- if line.startswith('"'):
- line = line[1:]
- if line.endswith('"'):
- line = line[:-1]
- if line.startswith("'"):
- line = line[1:]
- if line.endswith("'"):
- line = line[:-1]
-
- return line
-
- def __parse_values(self, line):
- """Parse a comma-separated string into separate values and convert them
- into a list. This should handle quoted-strings with embedded commas
- """
- lexer = shlex.shlex(line)
- lexer.wordchars = lexer.wordchars + ".()-"
- l = []
- v = ""
- for token in lexer:
- if token != ',':
- if v:
- v = v + " " + token
- else:
- v = token
- else:
- l.append(self.__remove_quotes(v))
- v = ""
-
- l.append(self.__remove_quotes(v))
-
- return l
-
- def read_file(self, filename):
- if filename == '-':
- fd = sys.stdin
- else:
- fd = open(filename)
- text = fd.readlines()
- if fd != sys.stdin: fd.close()
- return text
-
- def __entry_to_entity(self, ent):
- """Tne Entry class is a bare LDAP entry. The Entity class has a lot more
- helper functions that we need, so convert to dict and then to Entity.
- """
- entry = dict(ent.data)
- entry['dn'] = ent.dn
- for key,value in entry.iteritems():
- if isinstance(value,list) or isinstance(value,tuple):
- if len(value) == 0:
- entry[key] = ''
- elif len(value) == 1:
- entry[key] = value[0]
- return entity.Entity(entry)
-
- def __combine_updates(self, dn_list, all_updates, update):
- """Combine a new update with the list of total updates
-
- Updates are stored in 2 lists:
- dn_list: contains a unique list of DNs in the updates
- all_updates: the actual updates that need to be applied
-
- We want to apply the updates from the shortest to the longest
- path so if new child and parent entries are in different updates
- we can be sure the parent gets written first. This also lets
- us apply any schema first since it is in the very short cn=schema.
- """
- dn = update.get('dn')
- dns = ldap.explode_dn(dn.lower())
- l = len(dns)
- if dn_list.get(l):
- if dn not in dn_list[l]:
- dn_list[l].append(dn)
- else:
- dn_list[l] = [dn]
- if not all_updates.get(dn):
- all_updates[dn] = update
- return all_updates
-
- e = all_updates[dn]
- e['updates'] = e['updates'] + update['updates']
-
- all_updates[dn] = e
-
- return all_updates
-
- def parse_update_file(self, data, all_updates, dn_list):
- """Parse the update file into a dictonary of lists and apply the update
- for each DN in the file."""
- valid_keywords = ["default", "add", "remove", "only"]
- update = {}
- d = ""
- index = ""
- dn = None
- lcount = 0
- for line in data:
- # Strip out \n and extra white space
- lcount = lcount + 1
-
- # skip comments and empty lines
- line = line.rstrip()
- if line.startswith('#') or line == '': continue
-
- if line.lower().startswith('dn:'):
- if dn is not None:
- all_updates = self.__combine_updates(dn_list, all_updates, update)
-
- update = {}
- dn = line[3:].strip()
- update['dn'] = self.__template_str(dn)
- else:
- if dn is None:
- raise BadSyntax, "dn is not defined in the update"
-
- if line.startswith(' '):
- v = d[len(d) - 1]
- v = v + " " + line.strip()
- d[len(d) - 1] = v
- update[index] = d
- continue
- line = line.strip()
- values = line.split(':', 2)
- if len(values) != 3:
- raise BadSyntax, "Bad formatting on line %d: %s" % (lcount,line)
-
- index = values[0].strip().lower()
-
- if index not in valid_keywords:
- raise BadSyntax, "Unknown keyword %s" % index
-
- attr = values[1].strip()
- value = values[2].strip()
- value = self.__template_str(value)
-
- new_value = ""
- if index == "default":
- new_value = attr + ":" + value
- else:
- new_value = index + ":" + attr + ":" + value
- index = "updates"
-
- d = update.get(index, [])
-
- d.append(new_value)
-
- update[index] = d
-
- if dn is not None:
- all_updates = self.__combine_updates(dn_list, all_updates, update)
-
- return (all_updates, dn_list)
-
- def create_index_task(self, attribute):
- """Create a task to update an index for an attribute"""
-
- r = random.SystemRandom()
-
- # Refresh the time to make uniqueness more probable. Add on some
- # randomness for good measure.
- self.sub_dict['TIME'] = int(time.time()) + r.randint(0,10000)
-
- cn = self.__template_str("indextask_$TIME")
- dn = "cn=%s, cn=index, cn=tasks, cn=config" % cn
-
- e = ipaldap.Entry(dn)
-
- e.setValues('objectClass', ['top', 'extensibleObject'])
- e.setValue('cn', cn)
- e.setValue('nsInstance', 'userRoot')
- e.setValues('nsIndexAttribute', attribute)
-
- logging.info("Creating task to index attribute: %s", attribute)
- logging.debug("Task id: %s", dn)
-
- if self.live_run:
- self.conn.addEntry(e.dn, e.toTupleList())
-
- return dn
-
- def monitor_index_task(self, dn):
- """Give a task DN monitor it and wait until it has completed (or failed)
- """
-
- if not self.live_run:
- # If not doing this live there is nothing to monitor
- return
-
- # Pause for a moment to give the task time to be created
- time.sleep(1)
-
- attrlist = ['nstaskstatus', 'nstaskexitcode']
- entry = None
-
- while True:
- try:
- entry = self.conn.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)", attrlist)
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- logging.error("Task not found: %s", dn)
- return
- except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR), e:
- logging.error("Task lookup failure %s: %s", e, self.__detail_error(e.detail))
- return
-
- status = entry.getValue('nstaskstatus')
- if status is None:
- # task doesn't have a status yet
- time.sleep(1)
- continue
-
- if status.lower().find("finished") > -1:
- logging.info("Indexing finished")
- break
-
- logging.debug("Indexing in progress")
- time.sleep(1)
-
- return
-
- def __create_default_entry(self, dn, default):
- """Create the default entry from the values provided.
-
- The return type is entity.Entity
- """
- entry = ipaldap.Entry(dn)
-
- if not default:
- # This means that the entire entry needs to be created with add
- return self.__entry_to_entity(entry)
-
- for line in default:
- # We already do syntax-parsing so this is safe
- (k, v) = line.split(':',1)
- e = entry.getValues(k)
- if e:
- # multi-valued attribute
- e = list(e)
- e.append(v)
- else:
- e = v
- entry.setValues(k, e)
-
- return self.__entry_to_entity(entry)
-
- def __get_entry(self, dn):
- """Retrieve an object from LDAP.
-
- The return type is ipaldap.Entry
- """
- searchfilter="objectclass=*"
- sattrs = ["*"]
- scope = ldap.SCOPE_BASE
-
- return self.conn.getList(dn, scope, searchfilter, sattrs)
-
- def __apply_updates(self, updates, entry):
- """updates is a list of changes to apply
- entry is the thing to apply them to
-
- returns the modified entry
- """
- if not updates:
- return entry
-
- only = {}
- for u in updates:
- # We already do syntax-parsing so this is safe
- (utype, k, values) = u.split(':',2)
-
- values = self.__parse_values(values)
-
- e = entry.getValues(k)
- if not isinstance(e, list):
- if e is None:
- e = []
- else:
- e = [e]
-
- for v in values:
- if utype == 'remove':
- logging.debug("remove: '%s' from %s, current value %s", v, k, e)
- try:
- e.remove(v)
- except ValueError:
- logging.warn("remove: '%s' not in %s", v, k)
- pass
- entry.setValues(k, e)
- logging.debug('remove: updated value %s', e)
- elif utype == 'add':
- logging.debug("add: '%s' to %s, current value %s", v, k, e)
- # Remove it, ignoring errors so we can blindly add it later
- try:
- e.remove(v)
- except ValueError:
- pass
- e.append(v)
- logging.debug('add: updated value %s', e)
- entry.setValues(k, e)
- elif utype == 'only':
- logging.debug("only: set %s to '%s', current value %s", k, v, e)
- if only.get(k):
- e.append(v)
- else:
- e = [v]
- only[k] = True
- entry.setValues(k, e)
- logging.debug('only: updated value %s', e)
-
- self.print_entity(entry)
-
- return entry
-
- def print_entity(self, e, message=None):
- """The entity object currently lacks a str() method"""
- logging.debug("---------------------------------------------")
- if message:
- logging.debug("%s", message)
- logging.debug("dn: " + e.dn)
- attr = e.attrList()
- for a in attr:
- value = e.getValues(a)
- if isinstance(value,str):
- logging.debug(a + ": " + value)
- else:
- logging.debug(a + ": ")
- for l in value:
- logging.debug("\t" + l)
- def is_schema_updated(self, s):
- """Compare the schema in 's' with the current schema in the DS to
- see if anything has changed. This should account for syntax
- differences (like added parens that make no difference but are
- detected as a change by generateModList()).
-
- This doesn't handle re-ordering of attributes. They are still
- detected as changes, so foo $ bar != bar $ foo.
-
- return True if the schema has changed
- return False if it has not
- """
- s = ldap.schema.SubSchema(s)
- s = s.ldap_entry()
-
- # Get a fresh copy and convert into a SubSchema
- n = self.__get_entry("cn=schema")[0]
- n = dict(n.data)
- n = ldap.schema.SubSchema(n)
- n = n.ldap_entry()
-
- if s == n:
- return False
- else:
- return True
-
- def __update_record(self, update):
- found = False
-
- new_entry = self.__create_default_entry(update.get('dn'),
- update.get('default'))
-
- try:
- e = self.__get_entry(new_entry.dn)
- if len(e) > 1:
- # we should only ever get back one entry
- raise BadSyntax, "More than 1 entry returned on a dn search!? %s" % new_entry.dn
- entry = self.__entry_to_entity(e[0])
- found = True
- logging.info("Updating existing entry: %s", entry.dn)
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- # Doesn't exist, start with the default entry
- entry = new_entry
- logging.info("New entry: %s", entry.dn)
- except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR):
- # Doesn't exist, start with the default entry
- entry = new_entry
- logging.info("New entry, using default value: %s", entry.dn)
-
- self.print_entity(entry)
-
- # Bring this entry up to date
- entry = self.__apply_updates(update.get('updates'), entry)
-
- self.print_entity(entry, "Final value")
-
- if not found:
- # New entries get their orig_data set to the entry itself. We want to
- # empty that so that everything appears new when generating the
- # modlist
- # entry.orig_data = {}
- try:
- if self.live_run:
- self.conn.addEntry(entry.dn, entry.toTupleList())
- except Exception, e:
- logging.error("Add failure %s: %s", e, self.__detail_error(e.detail))
- else:
- # Update LDAP
- try:
- updated = False
- changes = self.conn.generateModList(entry.origDataDict(), entry.toDict())
- if (entry.dn == "cn=schema"):
- updated = self.is_schema_updated(entry.toDict())
- else:
- if len(changes) > 1:
- updated = True
- logging.debug("%s" % changes)
- if self.live_run and updated:
- self.conn.updateEntry(entry.dn, entry.origDataDict(), entry.toDict())
- logging.info("Done")
- except ipaerror.exception_for(ipaerror.LDAP_EMPTY_MODLIST), e:
- logging.info("Entry already up-to-date")
- updated = False
- except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR), e:
- logging.error("Update failed: %s: %s", e, self.__detail_error(e.detail))
- updated = False
-
- if ("cn=index" in entry.dn and
- "cn=userRoot" in entry.dn):
- taskid = self.create_index_task(entry.cn)
- self.monitor_index_task(taskid)
-
- if updated:
- self.modified = True
- return
-
- def get_all_files(self, root, recursive=False):
- """Get all update files"""
- f = []
- for path, subdirs, files in os.walk(root):
- for name in files:
- if fnmatch.fnmatch(name, "*.update"):
- f.append(os.path.join(path, name))
- if not recursive:
- break
- return f
-
- def update(self, files):
- """Execute the update. files is a list of the update files to use.
-
- returns True if anything was changed, otherwise False
- """
-
- try:
- self.conn = ipaldap.IPAdmin(self.sub_dict['FQDN'])
- self.conn.do_simple_bind(bindpw=self.dm_password)
- all_updates = {}
- dn_list = {}
- for f in files:
- try:
- logging.info("Parsing file %s" % f)
- data = self.read_file(f)
- except Exception, e:
- print e
- sys.exit(1)
-
- (all_updates, dn_list) = self.parse_update_file(data, all_updates, dn_list)
-
- sortedkeys = dn_list.keys()
- sortedkeys.sort()
- for k in sortedkeys:
- for dn in dn_list[k]:
- self.__update_record(all_updates[dn])
- finally:
- if self.conn: self.conn.unbind()
-
- return self.modified
diff --git a/ipa-server/ipaserver/ntpinstance.py b/ipa-server/ipaserver/ntpinstance.py
deleted file mode 100644
index e2ec60650..000000000
--- a/ipa-server/ipaserver/ntpinstance.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# Authors: Karl MacMillan <kmacmillan@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 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
-#
-
-import shutil
-import logging
-
-import service
-from ipa import sysrestore
-from ipa import ipautil
-
-class NTPInstance(service.Service):
- def __init__(self, fstore=None):
- service.Service.__init__(self, "ntpd")
-
- if fstore:
- self.fstore = fstore
- else:
- self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
-
- def __write_config(self):
- # The template sets the config to point towards ntp.pool.org, but
- # they request that software not point towards the default pool.
- # We use the OS variable to point it towards either the rhel
- # or fedora pools. Other distros should be added in the future
- # or we can get our own pool.
- os = ""
- if ipautil.file_exists("/etc/fedora-release"):
- os = "fedora"
- elif ipautil.file_exists("/etc/redhat-release"):
- os = "rhel"
-
- sub_dict = { }
- sub_dict["SERVERA"] = "0.%s.pool.ntp.org" % os
- sub_dict["SERVERB"] = "1.%s.pool.ntp.org" % os
- sub_dict["SERVERC"] = "2.%s.pool.ntp.org" % os
-
- ntp_conf = ipautil.template_file(ipautil.SHARE_DIR + "ntp.conf.server.template", sub_dict)
- ntp_sysconf = ipautil.template_file(ipautil.SHARE_DIR + "ntpd.sysconfig.template", {})
-
- self.fstore.backup_file("/etc/ntp.conf")
- self.fstore.backup_file("/etc/sysconfig/ntpd")
-
- fd = open("/etc/ntp.conf", "w")
- fd.write(ntp_conf)
- fd.close()
-
- fd = open("/etc/sysconfig/ntpd", "w")
- fd.write(ntp_sysconf)
- fd.close()
-
- def __stop(self):
- self.backup_state("running", self.is_running())
- self.stop()
-
- def __start(self):
- self.start()
-
- def __enable(self):
- self.backup_state("enabled", self.is_enabled())
- self.chkconfig_on()
-
- def create_instance(self):
-
- # we might consider setting the date manually using ntpd -qg in case
- # the current time is very far off.
-
- self.step("stopping ntpd", self.__stop)
- self.step("writing configuration", self.__write_config)
- self.step("configuring ntpd to start on boot", self.__enable)
- self.step("starting ntpd", self.__start)
-
- self.start_creation("Configuring ntpd")
-
- def uninstall(self):
- running = self.restore_state("running")
- enabled = self.restore_state("enabled")
-
- if not running is None:
- self.stop()
-
- try:
- self.fstore.restore_file("/etc/ntp.conf")
- except ValueError, error:
- logging.debug(error)
- pass
-
- if not enabled is None and not enabled:
- self.chkconfig_off()
-
- if not running is None and running:
- self.start()
diff --git a/ipa-server/ipaserver/replication.py b/ipa-server/ipaserver/replication.py
deleted file mode 100644
index 8477bd18a..000000000
--- a/ipa-server/ipaserver/replication.py
+++ /dev/null
@@ -1,532 +0,0 @@
-# Authors: 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
-#
-
-import time, logging
-
-import ipaldap, ldap, dsinstance
-from ldap import modlist
-from ipa import ipaerror
-
-DIRMAN_CN = "cn=directory manager"
-CACERT="/usr/share/ipa/html/ca.crt"
-# the default container used by AD for user entries
-WIN_USER_CONTAINER="cn=Users"
-# the default container used by IPA for user entries
-IPA_USER_CONTAINER="cn=users,cn=accounts"
-PORT = 636
-TIMEOUT = 120
-
-IPA_REPLICA = 1
-WINSYNC = 2
-
-class ReplicationManager:
- """Manage replication agreements between DS servers, and sync
- agreements with Windows servers"""
- def __init__(self, hostname, dirman_passwd):
- self.hostname = hostname
- self.dirman_passwd = dirman_passwd
-
- self.conn = ipaldap.IPAdmin(hostname, port=PORT, cacert=CACERT)
- self.conn.do_simple_bind(bindpw=dirman_passwd)
-
- self.repl_man_passwd = dirman_passwd
-
- # these are likely constant, but you could change them
- # at runtime if you really want
- self.repl_man_dn = "cn=replication manager,cn=config"
- self.repl_man_cn = "replication manager"
- self.suffix = ""
-
- def _get_replica_id(self, conn, master_conn):
- """
- Returns the replica ID which is unique for each backend.
-
- conn is the connection we are trying to get the replica ID for.
- master_conn is the master we are going to replicate with.
- """
- # First see if there is already one set
- dn = self.replica_dn()
- try:
- replica = conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
- if replica.getValue('nsDS5ReplicaId'):
- return int(replica.getValue('nsDS5ReplicaId'))
- except ldap.NO_SUCH_OBJECT:
- pass
-
- # Ok, either the entry doesn't exist or the attribute isn't set
- # so get it from the other master
- retval = -1
- dn = "cn=replication, cn=etc, %s" % self.suffix
- try:
- replica = master_conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
- if not replica.getValue('nsDS5ReplicaId'):
- logging.debug("Unable to retrieve nsDS5ReplicaId from remote server")
- raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
- except ldap.NO_SUCH_OBJECT:
- logging.debug("Unable to retrieve nsDS5ReplicaId from remote server")
- raise
-
- # Now update the value on the master
- retval = int(replica.getValue('nsDS5ReplicaId'))
- mod = [(ldap.MOD_REPLACE, 'nsDS5ReplicaId', str(retval + 1))]
-
- try:
- master_conn.modify_s(dn, mod)
- except Exception, e:
- logging.debug("Problem updating nsDS5ReplicaID %s" % e)
- raise
-
- return retval
-
- def find_replication_dns(self, conn):
- filt = "(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement))"
- try:
- ents = conn.search_s("cn=mapping tree,cn=config", ldap.SCOPE_SUBTREE, filt)
- except ldap.NO_SUCH_OBJECT:
- return []
- return [ent.dn for ent in ents]
-
- def add_replication_manager(self, conn, passwd=None):
- """
- Create a pseudo user to use for replication. If no password
- is provided the directory manager password will be used.
- """
-
- if passwd:
- self.repl_man_passwd = passwd
-
- ent = ipaldap.Entry(self.repl_man_dn)
- ent.setValues("objectclass", "top", "person")
- ent.setValues("cn", self.repl_man_cn)
- ent.setValues("userpassword", self.repl_man_passwd)
- ent.setValues("sn", "replication manager pseudo user")
-
- try:
- conn.add_s(ent)
- except ldap.ALREADY_EXISTS:
- # should we set the password here?
- pass
-
- def delete_replication_manager(self, conn, dn="cn=replication manager,cn=config"):
- try:
- conn.delete_s(dn)
- except ldap.NO_SUCH_OBJECT:
- pass
-
- def get_replica_type(self, master=True):
- if master:
- return "3"
- else:
- return "2"
-
- def replica_dn(self):
- return 'cn=replica, cn="%s", cn=mapping tree, cn=config' % self.suffix
-
- def local_replica_config(self, conn, replica_id):
- dn = self.replica_dn()
-
- try:
- conn.getEntry(dn, ldap.SCOPE_BASE)
- # replication is already configured
- return
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- pass
-
- replica_type = self.get_replica_type()
-
- entry = ipaldap.Entry(dn)
- entry.setValues('objectclass', "top", "nsds5replica", "extensibleobject")
- entry.setValues('cn', "replica")
- entry.setValues('nsds5replicaroot', self.suffix)
- entry.setValues('nsds5replicaid', str(replica_id))
- entry.setValues('nsds5replicatype', replica_type)
- entry.setValues('nsds5flags', "1")
- entry.setValues('nsds5replicabinddn', [self.repl_man_dn])
- entry.setValues('nsds5replicalegacyconsumer', "off")
-
- conn.add_s(entry)
-
- def setup_changelog(self, conn):
- dn = "cn=changelog5, cn=config"
- dirpath = conn.dbdir + "/cldb"
- entry = ipaldap.Entry(dn)
- entry.setValues('objectclass', "top", "extensibleobject")
- entry.setValues('cn', "changelog5")
- entry.setValues('nsslapd-changelogdir', dirpath)
- try:
- conn.add_s(entry)
- except ldap.ALREADY_EXISTS:
- return
-
- def setup_chaining_backend(self, conn):
- chaindn = "cn=chaining database, cn=plugins, cn=config"
- benamebase = "chaindb"
- urls = [self.to_ldap_url(conn)]
- cn = ""
- benum = 1
- done = False
- while not done:
- try:
- cn = benamebase + str(benum) # e.g. localdb1
- dn = "cn=" + cn + ", " + chaindn
- entry = ipaldap.Entry(dn)
- entry.setValues('objectclass', 'top', 'extensibleObject', 'nsBackendInstance')
- entry.setValues('cn', cn)
- entry.setValues('nsslapd-suffix', self.suffix)
- entry.setValues('nsfarmserverurl', urls)
- entry.setValues('nsmultiplexorbinddn', self.repl_man_dn)
- entry.setValues('nsmultiplexorcredentials', self.repl_man_passwd)
-
- self.conn.add_s(entry)
- done = True
- except ldap.ALREADY_EXISTS:
- benum += 1
- except ldap.LDAPError, e:
- print "Could not add backend entry " + dn, e
- raise
-
- return cn
-
- def to_ldap_url(self, conn):
- return "ldap://%s:%d/" % (conn.host, conn.port)
-
- def setup_chaining_farm(self, conn):
- try:
- conn.modify_s(self.suffix, [(ldap.MOD_ADD, 'aci',
- [ "(targetattr = \"*\")(version 3.0; acl \"Proxied authorization for database links\"; allow (proxy) userdn = \"ldap:///%s\";)" % self.repl_man_dn ])])
- except ldap.TYPE_OR_VALUE_EXISTS:
- logging.debug("proxy aci already exists in suffix %s on %s" % (self.suffix, conn.host))
-
- def get_mapping_tree_entry(self):
- try:
- entry = self.conn.getEntry("cn=mapping tree,cn=config", ldap.SCOPE_ONELEVEL,
- "(cn=\"%s\")" % (self.suffix))
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND), e:
- logging.debug("failed to find mappting tree entry for %s" % self.suffix)
- raise e
-
- return entry
-
-
- def enable_chain_on_update(self, bename):
- mtent = self.get_mapping_tree_entry()
- dn = mtent.dn
-
- plgent = self.conn.getEntry("cn=Multimaster Replication Plugin,cn=plugins,cn=config",
- ldap.SCOPE_BASE, "(objectclass=*)", ['nsslapd-pluginPath'])
- path = plgent.getValue('nsslapd-pluginPath')
-
- mod = [(ldap.MOD_REPLACE, 'nsslapd-state', 'backend'),
- (ldap.MOD_ADD, 'nsslapd-backend', bename),
- (ldap.MOD_ADD, 'nsslapd-distribution-plugin', path),
- (ldap.MOD_ADD, 'nsslapd-distribution-funct', 'repl_chain_on_update')]
-
- try:
- self.conn.modify_s(dn, mod)
- except ldap.TYPE_OR_VALUE_EXISTS:
- logging.debug("chainOnUpdate already enabled for %s" % self.suffix)
-
- def setup_chain_on_update(self, other_conn):
- chainbe = self.setup_chaining_backend(other_conn)
- self.enable_chain_on_update(chainbe)
-
- def add_passsync_user(self, conn, password):
- pass_dn = "uid=passsync,cn=sysaccounts,cn=etc,%s" % self.suffix
- print "The user for the Windows PassSync service is %s" % pass_dn
- try:
- conn.getEntry(pass_dn, ldap.SCOPE_BASE)
- print "Windows PassSync entry exists, not resetting password"
- return
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- pass
-
- # The user doesn't exist, add it
- entry = ipaldap.Entry(pass_dn)
- entry.setValues("objectclass", ["account", "simplesecurityobject"])
- entry.setValues("uid", "passsync")
- entry.setValues("userPassword", password)
- conn.add_s(entry)
-
- # Add it to the list of users allowed to bypass password policy
- extop_dn = "cn=ipa_pwd_extop,cn=plugins,cn=config"
- entry = conn.getEntry(extop_dn, ldap.SCOPE_BASE)
- pass_mgrs = entry.getValues('passSyncManagersDNs')
- if not pass_mgrs:
- pass_mgrs = []
- if not isinstance(pass_mgrs, list):
- pass_mgrs = [pass_mgrs]
- pass_mgrs.append(pass_dn)
- mod = [(ldap.MOD_REPLACE, 'passSyncManagersDNs', pass_mgrs)]
- conn.modify_s(extop_dn, mod)
-
- # And finally grant it permission to write passwords
- mod = [(ldap.MOD_ADD, 'aci',
- ['(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Windows PassSync service can write passwords"; allow (write) userdn="ldap:///%s";)' % pass_dn])]
- try:
- conn.modify_s(self.suffix, mod)
- except ldap.TYPE_OR_VALUE_EXISTS:
- logging.debug("passsync aci already exists in suffix %s on %s" % (self.suffix, conn.host))
-
- def setup_winsync_agmt(self, entry, **kargs):
- entry.setValues("objectclass", "nsDSWindowsReplicationAgreement")
- entry.setValues("nsds7WindowsReplicaSubtree",
- kargs.get("win_subtree",
- WIN_USER_CONTAINER + "," + self.suffix))
- entry.setValues("nsds7DirectoryReplicaSubtree",
- kargs.get("ds_subtree",
- IPA_USER_CONTAINER + "," + self.suffix))
- # for now, just sync users and ignore groups
- entry.setValues("nsds7NewWinUserSyncEnabled", kargs.get('newwinusers', 'true'))
- entry.setValues("nsds7NewWinGroupSyncEnabled", kargs.get('newwingroups', 'false'))
- windomain = ''
- if kargs.has_key('windomain'):
- windomain = kargs['windomain']
- else:
- windomain = '.'.join(ldap.explode_dn(self.suffix, 1))
- entry.setValues("nsds7WindowsDomain", windomain)
-
- def agreement_dn(self, hostname, port=PORT):
- cn = "meTo%s%d" % (hostname, port)
- dn = "cn=%s, %s" % (cn, self.replica_dn())
-
- return (cn, dn)
-
- def setup_agreement(self, a, b, **kargs):
- cn, dn = self.agreement_dn(b.host)
- try:
- a.getEntry(dn, ldap.SCOPE_BASE)
- return
- except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- pass
-
- iswinsync = kargs.get("winsync", False)
- repl_man_dn = kargs.get("binddn", self.repl_man_dn)
- repl_man_passwd = kargs.get("bindpw", self.repl_man_passwd)
- port = kargs.get("port", PORT)
-
- entry = ipaldap.Entry(dn)
- entry.setValues('objectclass', "nsds5replicationagreement")
- entry.setValues('cn', cn)
- entry.setValues('nsds5replicahost', b.host)
- entry.setValues('nsds5replicaport', str(port))
- entry.setValues('nsds5replicatimeout', str(TIMEOUT))
- entry.setValues('nsds5replicabinddn', repl_man_dn)
- entry.setValues('nsds5replicacredentials', repl_man_passwd)
- entry.setValues('nsds5replicabindmethod', 'simple')
- entry.setValues('nsds5replicaroot', self.suffix)
- entry.setValues('nsds5replicaupdateschedule', '0000-2359 0123456')
- entry.setValues('nsds5replicatransportinfo', 'SSL')
- entry.setValues('nsDS5ReplicatedAttributeList', '(objectclass=*) $ EXCLUDE memberOf')
- entry.setValues('description', "me to %s%d" % (b.host, port))
- if iswinsync:
- self.setup_winsync_agmt(entry, **kargs)
-
- a.add_s(entry)
-
- entry = a.waitForEntry(entry)
-
- def delete_agreement(self, hostname):
- cn, dn = self.agreement_dn(hostname)
- return self.conn.deleteEntry(dn)
-
- def check_repl_init(self, conn, agmtdn):
- done = False
- hasError = 0
- attrlist = ['cn', 'nsds5BeginReplicaRefresh', 'nsds5replicaUpdateInProgress',
- 'nsds5ReplicaLastInitStatus', 'nsds5ReplicaLastInitStart',
- 'nsds5ReplicaLastInitEnd']
- entry = conn.getEntry(agmtdn, ldap.SCOPE_BASE, "(objectclass=*)", attrlist)
- if not entry:
- print "Error reading status from agreement", agmtdn
- hasError = 1
- else:
- refresh = entry.nsds5BeginReplicaRefresh
- inprogress = entry.nsds5replicaUpdateInProgress
- status = entry.nsds5ReplicaLastInitStatus
- if not refresh: # done - check status
- if not status:
- print "No status yet"
- elif status.find("replica busy") > -1:
- print "[%s] reports: Replica Busy! Status: [%s]" % (conn.host, status)
- done = True
- hasError = 2
- elif status.find("Total update succeeded") > -1:
- print "Update succeeded"
- done = True
- elif inprogress.lower() == 'true':
- print "Update in progress yet not in progress"
- else:
- print "[%s] reports: Update failed! Status: [%s]" % (conn.host, status)
- hasError = 1
- done = True
- else:
- print "Update in progress"
-
- return done, hasError
-
- def check_repl_update(self, conn, agmtdn):
- done = False
- hasError = 0
- attrlist = ['cn', 'nsds5replicaUpdateInProgress',
- 'nsds5ReplicaLastUpdateStatus', 'nsds5ReplicaLastUpdateStart',
- 'nsds5ReplicaLastUpdateEnd']
- entry = conn.getEntry(agmtdn, ldap.SCOPE_BASE, "(objectclass=*)", attrlist)
- if not entry:
- print "Error reading status from agreement", agmtdn
- hasError = 1
- else:
- inprogress = entry.nsds5replicaUpdateInProgress
- status = entry.nsds5ReplicaLastUpdateStatus
- start = entry.nsds5ReplicaLastUpdateStart
- end = entry.nsds5ReplicaLastUpdateEnd
- # incremental update is done if inprogress is false and end >= start
- done = inprogress and inprogress.lower() == 'false' and start and end and (start <= end)
- logging.info("Replication Update in progress: %s: status: %s: start: %s: end: %s" %
- (inprogress, status, start, end))
- if not done and status: # check for errors
- # status will usually be a number followed by a string
- # number != 0 means error
- rc, msg = status.split(' ', 1)
- if rc != '0':
- hasError = 1
- done = True
-
- return done, hasError
-
- def wait_for_repl_init(self, conn, agmtdn):
- done = False
- haserror = 0
- while not done and not haserror:
- time.sleep(1) # give it a few seconds to get going
- done, haserror = self.check_repl_init(conn, agmtdn)
- return haserror
-
- def wait_for_repl_update(self, conn, agmtdn, maxtries=600):
- done = False
- haserror = 0
- while not done and not haserror and maxtries > 0:
- time.sleep(1) # give it a few seconds to get going
- done, haserror = self.check_repl_update(conn, agmtdn)
- maxtries -= 1
- if maxtries == 0: # too many tries
- print "Error: timeout: could not determine agreement status: please check your directory server logs for possible errors"
- haserror = 1
- return haserror
-
- def start_replication(self, other_conn, conn=None):
- print "Starting replication, please wait until this has completed."
- if conn == None:
- conn = self.conn
- cn, dn = self.agreement_dn(conn.host)
-
- mod = [(ldap.MOD_ADD, 'nsds5BeginReplicaRefresh', 'start')]
- other_conn.modify_s(dn, mod)
-
- return self.wait_for_repl_init(other_conn, dn)
-
- def basic_replication_setup(self, conn, replica_id):
- self.add_replication_manager(conn)
- self.local_replica_config(conn, replica_id)
- self.setup_changelog(conn)
-
- def setup_replication(self, other_hostname, realm_name, **kargs):
- """
- NOTES:
- - the directory manager password needs to be the same on
- both directories. Or use the optional binddn and bindpw
- """
- iswinsync = kargs.get("winsync", False)
- oth_port = kargs.get("port", PORT)
- oth_cacert = kargs.get("cacert", CACERT)
- oth_binddn = kargs.get("binddn", DIRMAN_CN)
- oth_bindpw = kargs.get("bindpw", self.dirman_passwd)
- # note - there appears to be a bug in python-ldap - it does not
- # allow connections using two different CA certs
- other_conn = ipaldap.IPAdmin(other_hostname, port=oth_port, cacert=oth_cacert)
- try:
- other_conn.do_simple_bind(binddn=oth_binddn, bindpw=oth_bindpw)
- except Exception, e:
- if iswinsync:
- logging.info("Could not validate connection to remote server %s:%d - continuing" %
- (other_hostname, oth_port))
- logging.info("The error was: %s" % e)
- else:
- raise e
-
- self.suffix = ipaldap.IPAdmin.normalizeDN(dsinstance.realm_to_suffix(realm_name))
-
- if not iswinsync:
- local_id = self._get_replica_id(self.conn, other_conn)
- else:
- # there is no other side to get a replica ID from
- local_id = self._get_replica_id(self.conn, self.conn)
- self.basic_replication_setup(self.conn, local_id)
-
- if not iswinsync:
- other_id = self._get_replica_id(other_conn, other_conn)
- self.basic_replication_setup(other_conn, other_id)
- self.setup_agreement(other_conn, self.conn)
- self.setup_agreement(self.conn, other_conn)
- return self.start_replication(other_conn)
- else:
- self.add_passsync_user(self.conn, kargs.get("passsync"))
- self.setup_agreement(self.conn, other_conn, **kargs)
- logging.info("Added new sync agreement, waiting for it to become ready . . .")
- cn, dn = self.agreement_dn(other_hostname)
- self.wait_for_repl_update(self.conn, dn, 30)
- logging.info("Agreement is ready, starting replication . . .")
- return self.start_replication(self.conn, other_conn)
-
- def initialize_replication(self, dn, conn):
- mod = [(ldap.MOD_ADD, 'nsds5BeginReplicaRefresh', 'start')]
- try:
- conn.modify_s(dn, mod)
- except ldap.ALREADY_EXISTS:
- return
-
- def force_synch(self, dn, schedule, conn):
- newschedule = '2358-2359 0'
-
- # On the remote chance of a match. We force a synch to happen right
- # now by changing the schedule to something else and quickly changing
- # it back.
- if newschedule == schedule:
- newschedule = '2358-2359 1'
- logging.info("Changing agreement %s schedule to %s to force synch" %
- (dn, newschedule))
- mod = [(ldap.MOD_REPLACE, 'nsDS5ReplicaUpdateSchedule', [ newschedule ])]
- conn.modify_s(dn, mod)
- time.sleep(1)
- logging.info("Changing agreement %s to restore original schedule %s" %
- (dn, schedule))
- mod = [(ldap.MOD_REPLACE, 'nsDS5ReplicaUpdateSchedule', [ schedule ])]
- conn.modify_s(dn, mod)
-
- def get_agreement_type(self, hostname):
- cn, dn = self.agreement_dn(hostname)
-
- entry = self.conn.getEntry(dn, ldap.SCOPE_BASE)
-
- objectclass = entry.getValues("objectclass")
-
- for o in objectclass:
- if o.lower() == "nsdswindowsreplicationagreement":
- return WINSYNC
-
- return IPA_REPLICA
diff --git a/ipa-server/ipaserver/service.py b/ipa-server/ipaserver/service.py
deleted file mode 100644
index b9f6c505d..000000000
--- a/ipa-server/ipaserver/service.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Authors: 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
-#
-
-import logging, sys
-from ipa import sysrestore
-from ipa import ipautil
-
-
-def stop(service_name):
- ipautil.run(["/sbin/service", service_name, "stop"])
-
-def start(service_name):
- ipautil.run(["/sbin/service", service_name, "start"])
-
-def restart(service_name):
- ipautil.run(["/sbin/service", service_name, "restart"])
-
-def is_running(service_name):
- ret = True
- try:
- ipautil.run(["/sbin/service", service_name, "status"])
- except ipautil.CalledProcessError:
- ret = False
- return ret
-
-def chkconfig_on(service_name):
- ipautil.run(["/sbin/chkconfig", service_name, "on"])
-
-def chkconfig_off(service_name):
- ipautil.run(["/sbin/chkconfig", service_name, "off"])
-
-def chkconfig_add(service_name):
- ipautil.run(["/sbin/chkconfig", "--add", service_name])
-
-def chkconfig_del(service_name):
- ipautil.run(["/sbin/chkconfig", "--del", service_name])
-
-def is_enabled(service_name):
- (stdout, stderr) = ipautil.run(["/sbin/chkconfig", "--list", service_name])
-
- runlevels = {}
- for runlevel in range(0, 7):
- runlevels[runlevel] = False
-
- for line in stdout.split("\n"):
- parts = line.split()
- if parts[0] == service_name:
- for s in parts[1:]:
- (runlevel, status) = s.split(":")[0:2]
- try:
- runlevels[int(runlevel)] = status == "on"
- except ValueError:
- pass
- break
-
- return (runlevels[3] and runlevels[4] and runlevels[5])
-
-def print_msg(message, output_fd=sys.stdout):
- logging.debug(message)
- output_fd.write(message)
- output_fd.write("\n")
-
-
-class Service:
- def __init__(self, service_name, sstore=None):
- self.service_name = service_name
- self.steps = []
- self.output_fd = sys.stdout
-
- if sstore:
- self.sstore = sstore
- else:
- self.sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore')
-
- def set_output(self, fd):
- self.output_fd = fd
-
- def stop(self):
- stop(self.service_name)
-
- def start(self):
- start(self.service_name)
-
- def restart(self):
- restart(self.service_name)
-
- def is_running(self):
- return is_running(self.service_name)
-
- def chkconfig_add(self):
- chkconfig_add(self.service_name)
-
- def chkconfig_del(self):
- chkconfig_del(self.service_name)
-
- def chkconfig_on(self):
- chkconfig_on(self.service_name)
-
- def chkconfig_off(self):
- chkconfig_off(self.service_name)
-
- def is_enabled(self):
- return is_enabled(self.service_name)
-
- def backup_state(self, key, value):
- self.sstore.backup_state(self.service_name, key, value)
-
- def restore_state(self, key):
- return self.sstore.restore_state(self.service_name, key)
-
- def print_msg(self, message):
- print_msg(message, self.output_fd)
-
- def step(self, message, method):
- self.steps.append((message, method))
-
- def start_creation(self, message):
- self.print_msg(message)
-
- step = 0
- for (message, method) in self.steps:
- self.print_msg(" [%d/%d]: %s" % (step+1, len(self.steps), message))
- method()
- step += 1
-
- self.print_msg("done configuring %s." % self.service_name)
-
- self.steps = []
-
-class SimpleServiceInstance(Service):
- def create_instance(self):
- self.step("starting %s " % self.service_name, self.__start)
- self.step("configuring %s to start on boot" % self.service_name, self.__enable)
- self.start_creation("Configuring %s" % self.service_name)
-
- def __start(self):
- self.backup_state("running", self.is_running())
- self.restart()
-
- def __enable(self):
- self.chkconfig_add()
- self.backup_state("enabled", self.is_enabled())
- self.chkconfig_on()
-
- def uninstall(self):
- running = self.restore_state("running")
- enabled = not self.restore_state("enabled")
-
- if not running is None and not running:
- self.stop()
- if not enabled is None and not enabled:
- self.chkconfig_off()
- self.chkconfig_del()