summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2011-09-07 10:17:12 +0200
committerSimo Sorce <ssorce@redhat.com>2011-09-14 18:45:13 -0400
commit29a7a7e8cee8ec767ee8f5bb67534c68d2fcc2b5 (patch)
tree678f6adda60d25dff56a4939209c177093dcc0bb /ipaserver
parent29ec63c3813cee5fa8d8b1e9ad032a89992791eb (diff)
downloadfreeipa-29a7a7e8cee8ec767ee8f5bb67534c68d2fcc2b5.tar.gz
freeipa-29a7a7e8cee8ec767ee8f5bb67534c68d2fcc2b5.tar.xz
freeipa-29a7a7e8cee8ec767ee8f5bb67534c68d2fcc2b5.zip
Add ipa-adtrust-install utility
https://fedorahosted.org/freeipa/ticket/1619
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/Makefile.am1
-rw-r--r--ipaserver/install/adtrustinstance.py281
-rw-r--r--ipaserver/install/service.py3
3 files changed, 284 insertions, 1 deletions
diff --git a/ipaserver/install/Makefile.am b/ipaserver/install/Makefile.am
index 8932eadbb..9fcad4e77 100644
--- a/ipaserver/install/Makefile.am
+++ b/ipaserver/install/Makefile.am
@@ -10,6 +10,7 @@ app_PYTHON = \
krbinstance.py \
httpinstance.py \
ntpinstance.py \
+ adtrustinstance.py \
service.py \
installutils.py \
replication.py \
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
new file mode 100644
index 000000000..f2cc3327d
--- /dev/null
+++ b/ipaserver/install/adtrustinstance.py
@@ -0,0 +1,281 @@
+# Authors: Sumit Bose <sbose@redhat.com>
+#
+# Copyright (C) 2011 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import logging
+
+import os
+import errno
+import ldap
+import service
+import tempfile
+import installutils
+from ipaserver import ipaldap
+from ipaserver.install.dsinstance import realm_to_serverid
+from ipalib import errors
+from ipapython import sysrestore
+from ipapython import ipautil
+
+import random
+import string
+import struct
+
+allowed_netbios_chars = string.ascii_uppercase + string.digits
+
+def check_inst(unattended):
+ for f in ['/usr/sbin/smbd', '/usr/bin/net', '/usr/bin/smbpasswd']:
+ if not os.path.exists(f):
+ print "%s was not found on this system" % f
+ print "Please install the 'samba' packages and start the installation again"
+ return False
+
+ #TODO: Add check for needed samba4 libraries
+
+ return True
+
+def ipa_smb_conf_exists():
+ try:
+ fd = open('/etc/samba/smb.conf', 'r')
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ return False
+
+ lines = fd.readlines()
+ fd.close()
+ for line in lines:
+ if line.startswith('### Added by IPA Installer ###'):
+ return True
+ return False
+
+
+def check_netbios_name(s):
+ # NetBIOS names may not be longer than 15 allowed characters
+ if not s or len(s) > 15 or ''.join([c for c in s if c not in allowed_netbios_chars]):
+ return False
+
+ return True
+
+def make_netbios_name(s):
+ return ''.join([c for c in s.split('.')[0].upper() if c in allowed_netbios_chars])[:15]
+
+class ADTRUSTInstance(service.Service):
+ def __init__(self, fstore=None, dm_password=None):
+ service.Service.__init__(self, "smb", dm_password=dm_password)
+
+ if fstore:
+ self.fstore = fstore
+ else:
+ self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+
+ def __create_samba_user(self):
+ print "The user for Samba is %s" % self.smb_dn
+ try:
+ self.admin_conn.getEntry(self.smb_dn, ldap.SCOPE_BASE)
+ print "Samba user entry exists, resetting password"
+
+ self.admin_conn.modify_s(self.smb_dn, [(ldap.MOD_REPLACE, "userPassword", self.smb_dn_pwd)])
+ return
+
+ except errors.NotFound:
+ pass
+
+ # The user doesn't exist, add it
+ entry = ipaldap.Entry(self.smb_dn)
+ entry.setValues("objectclass", ["account", "simplesecurityobject"])
+ entry.setValues("uid", "samba")
+ entry.setValues("userPassword", self.smb_dn_pwd)
+ self.admin_conn.add_s(entry)
+
+ # And finally grant it permission to read NT passwords, we do not want
+ # to support LM passwords so there is no need to allow access to them
+ mod = [(ldap.MOD_ADD, 'aci',
+ str(['(targetattr = "sambaNTPassword")(version 3.0; acl "Samba user can read NT passwords"; allow (read) userdn="ldap:///%s";)' % self.smb_dn]))]
+ try:
+ self.admin_conn.modify_s(self.suffix, mod)
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ logging.debug("samba user aci already exists in suffix %s on %s" % (self.suffix, self.admin_conn.host))
+
+ def __gen_sid_string(self):
+ sub_ids = struct.unpack("<LLL", os.urandom(12))
+ return "S-1-5-21-%d-%d-%d" % (sub_ids[0], sub_ids[1], sub_ids[2])
+
+ def __create_samba_domain_object(self):
+ trust_dn = "cn=trusts,%s" % self.suffix
+ smb_dom_dn = "cn=ad,%s" % trust_dn
+
+ try:
+ self.admin_conn.getEntry(smb_dom_dn, ldap.SCOPE_BASE)
+ print "Samba domain object already exists"
+ return
+ except errors.NotFound:
+ pass
+
+ try:
+ self.admin_conn.getEntry(trust_dn, ldap.SCOPE_BASE)
+ except errors.NotFound:
+ entry = ipaldap.Entry(trust_dn)
+ entry.setValues("objectclass", ["nsContainer"])
+ entry.setValues("cn", "trusts")
+ self.admin_conn.add_s(entry)
+
+ entry = ipaldap.Entry(smb_dom_dn)
+ entry.setValues("objectclass", ["sambaDomain", "nsContainer"])
+ entry.setValues("cn", "ad")
+ entry.setValues("sambaDomainName", self.netbios_name)
+ entry.setValues("sambaSID", self.__gen_sid_string())
+ #TODO: which MAY attributes do we want to set ?
+ self.admin_conn.add_s(entry)
+
+ def __write_smb_conf(self):
+ self.fstore.backup_file(self.smb_conf)
+
+ fd = open(self.smb_conf, "w")
+ fd.write('### Added by IPA Installer ###\n')
+ fd.write('[global]\n')
+ fd.write('config backend = registry\n')
+ fd.close()
+
+ def __write_smb_registry(self):
+ template = os.path.join(ipautil.SHARE_DIR, "smb.conf.template")
+ conf = ipautil.template_file(template, self.sub_dict)
+ [fd, tmp_name] = tempfile.mkstemp()
+ os.write(fd, conf)
+ os.close(fd)
+
+ args = ["/usr/bin/net", "conf", "import", tmp_name]
+
+ try:
+ ipautil.run(args)
+ finally:
+ os.remove(tmp_name)
+
+ def __set_smb_ldap_password(self):
+ args = ["/usr/bin/smbpasswd", "-c", self.smb_conf, "-s", "-W" ]
+
+ ipautil.run(args, stdin = self.smb_dn_pwd + "\n" + self.smb_dn_pwd + "\n" )
+
+ def __setup_principal(self):
+ cifs_principal = "cifs/" + self.fqdn + "@" + self.realm_name
+ installutils.kadmin_addprinc(cifs_principal)
+
+ self.move_service(cifs_principal)
+
+ try:
+ ipautil.run(["ipa-rmkeytab", "--principal", cifs_principal,
+ "-k", "/etc/krb5.keytab"])
+ except ipautil.CalledProcessError, e:
+ if e.returncode != 5:
+ logging.critical("Failed to remove old key for %s" % cifs_principal)
+
+ try:
+ ipautil.run(["ipa-getkeytab", "--server", self.fqdn,
+ "--principal", cifs_principal,
+ "-k", "/etc/krb5.keytab"])
+ except ipautil.CalledProcessError, e:
+ logging.critical("Failed to add key for %s" % cifs_principal)
+
+ def __start(self):
+ try:
+ self.start()
+ except:
+ logging.critical("smbd service failed to start")
+
+ def __stop(self):
+ self.backup_state("running", self.is_running())
+ try:
+ self.stop()
+ except:
+ pass
+
+ def __enable(self):
+ self.backup_state("enabled", self.is_enabled())
+ # We do not let the system start IPA components on its own,
+ # Instead we reply on the IPA init script to start only enabled
+ # components as found in our LDAP configuration tree
+ try:
+ self.ldap_enable('ADTRUST', self.fqdn, self.dm_password, self.suffix)
+ except ldap.ALREADY_EXISTS:
+ logging.critical("ADTRUST Service startup entry already exists.")
+ pass
+
+ def __setup_sub_dict(self):
+ self.sub_dict = dict(REALM = self.realm_name,
+ SUFFIX = self.suffix,
+ NETBIOS_NAME = self.netbios_name,
+ SMB_DN = self.smb_dn,
+ LDAPI_SOCKET = self.ldapi_socket)
+
+ def setup(self, fqdn, ip_address, realm_name, domain_name, netbios_name,
+ smbd_user="samba"):
+ self.fqdn =fqdn
+ self.ip_address = ip_address
+ self.realm_name = realm_name
+ self.domain_name = domain_name
+ self.netbios_name = netbios_name
+ self.smbd_user = smbd_user
+ self.suffix = ipautil.realm_to_suffix(self.realm_name)
+ self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % realm_to_serverid(self.realm_name)
+
+ self.smb_conf = "/etc/samba/smb.conf"
+
+ self.smb_dn = "uid=samba,cn=sysaccounts,cn=etc,%s" % self.suffix
+ self.smb_dn_pwd = ipautil.ipa_generate_password()
+
+ self.__setup_sub_dict()
+
+
+ def create_instance(self):
+
+ self.ldap_connect()
+
+ self.step("stopping smbd", self.__stop)
+ self.step("create samba user", self.__create_samba_user)
+ self.step("create samba domain object", self.__create_samba_domain_object)
+ self.step("create samba config registry", self.__write_smb_registry)
+ self.step("writing samba config file", self.__write_smb_conf)
+ self.step("setting password for the samba user", self.__set_smb_ldap_password)
+ self.step("Adding cifs Kerberos principal", self.__setup_principal)
+ self.step("configuring smbd to start on boot", self.__enable)
+ self.step("starting smbd", self.__start)
+
+ self.start_creation("Configuring smbd:")
+
+ def uninstall(self):
+ if self.is_configured():
+ self.print_msg("Unconfiguring %s" % self.service_name)
+
+ running = self.restore_state("running")
+ enabled = self.restore_state("enabled")
+
+ try:
+ self.stop()
+ except:
+ pass
+
+ for f in [self.smb_conf]:
+ try:
+ self.fstore.restore_file(f)
+ except ValueError, error:
+ logging.debug(error)
+ pass
+
+ if not enabled is None and not enabled:
+ self.disable()
+
+ if not running is None and running:
+ self.start()
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index a1c94dfaa..c9ff793f7 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -38,7 +38,8 @@ SERVICE_LIST = {
'KPASSWD':('kadmin', 20),
'DNS':('named', 30),
'HTTP':('httpd', 40),
- 'CA':('pki-cad', 50)
+ 'CA':('pki-cad', 50),
+ 'ADTRUST':('smb', 60)
}
def print_msg(message, output_fd=sys.stdout):