diff --git a/freeipa-3.0.0.pre1-000-centralize-timeout-for-waiting-for-servers-to-start.patch b/freeipa-3.0.0.pre1-000-centralize-timeout-for-waiting-for-servers-to-start.patch new file mode 100644 index 0000000..c0fdf7a --- /dev/null +++ b/freeipa-3.0.0.pre1-000-centralize-timeout-for-waiting-for-servers-to-start.patch @@ -0,0 +1,681 @@ +From e5b6260008a3a7132fdaef99d800406eb8872316 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Thu, 24 May 2012 11:23:36 -0400 +Subject: [PATCH 00/79] Centralize timeout for waiting for servers to start. + +All service start/restart currently go through ipapython/platform so +move the "wait for service to start" code there as well. + +A dictionary of known services and ports to wait on is defined in base.py +This is referenced by the platforms by instance name to determine what +to wait for. For the case of dirsrv if we get that as a plain name +(no specific instance) it is assumed to be the main IPA service. + +https://fedorahosted.org/freeipa/ticket/2375 +https://fedorahosted.org/freeipa/ticket/2610 +--- + install/tools/ipactl | 28 +++++++++------- + ipalib/constants.py | 2 ++ + ipapython/ipautil.py | 54 +++++++++++++++++++++++++++++ + ipapython/platform/base.py | 56 ++++++++++++++++++++----------- + ipapython/platform/fedora16.py | 4 +-- + ipapython/platform/redhat.py | 22 ++++++++++-- + ipapython/platform/systemd.py | 23 +++++++++++-- + ipaserver/install/cainstance.py | 1 - + ipaserver/install/dsinstance.py | 3 +- + ipaserver/install/installutils.py | 52 ---------------------------- + ipaserver/install/plugins/baseupdate.py | 8 +++++ + ipaserver/install/plugins/updateclient.py | 4 +-- + ipaserver/install/replication.py | 2 -- + ipaserver/install/service.py | 10 +++--- + ipaserver/install/upgradeinstance.py | 5 +++ + ipaserver/ipaldap.py | 7 ++-- + 16 files changed, 176 insertions(+), 105 deletions(-) + +diff --git a/install/tools/ipactl b/install/tools/ipactl +index c4d26b8df150119e0bc84abac020f8989a2a8ad2..22a4f6e03030e9874a533dd9978823dd3505658d 100755 +--- a/install/tools/ipactl ++++ b/install/tools/ipactl +@@ -24,7 +24,8 @@ try: + from ipaserver.install import service, installutils + from ipapython import services as ipaservices + from ipaserver.install.dsinstance import config_dirname, realm_to_serverid +- from ipaserver.install.installutils import is_ipa_configured, wait_for_open_ports, wait_for_open_socket, ScriptError ++ from ipaserver.install.installutils import is_ipa_configured, ScriptError ++ from ipapython.ipautil import wait_for_open_ports, wait_for_open_socket + from ipapython import sysrestore + from ipapython import config + from ipalib import api, errors +@@ -105,22 +106,25 @@ def parse_options(): + def emit_err(err): + sys.stderr.write(err + '\n') + +-def get_config(): ++def get_config(dirsrv): + base = "cn=%s,cn=masters,cn=ipa,cn=etc,%s" % (api.env.host, + api.env.basedn) + srcfilter = '(ipaConfigString=enabledService)' + attrs = ['cn', 'ipaConfigString'] ++ if not dirsrv.is_running(): ++ raise IpactlError("Failed to get list of services to probe status:\n" + ++ "Directory Server is stopped", 3) + + try: +- # systemd services are so fast that we come here before +- # Directory Server actually starts listening. Wait for +- # the socket/port be really available. ++ # The start/restart functions already wait for the server to be ++ # started. What we are doing with this wait is really checking to see ++ # if the server is listening at all. + lurl = ldapurl.LDAPUrl(api.env.ldap_uri) + if lurl.urlscheme == 'ldapi': +- wait_for_open_socket(lurl.hostport, timeout=6) ++ wait_for_open_socket(lurl.hostport, timeout=api.env.startup_timeout) + else: + (host,port) = lurl.hostport.split(':') +- wait_for_open_ports(host, [int(port)], timeout=6) ++ wait_for_open_ports(host, [int(port)], timeout=api.env.startup_timeout) + con = ldap.initialize(api.env.ldap_uri) + con.sasl_interactive_bind_s('', SASL_EXTERNAL) + res = con.search_st(base, +@@ -175,7 +179,7 @@ def ipa_start(options): + + svc_list = [] + try: +- svc_list = get_config() ++ svc_list = get_config(dirsrv) + except Exception, e: + emit_err("Failed to read data from Directory Service: " + str(e)) + emit_err("Shutting down") +@@ -219,14 +223,14 @@ def ipa_stop(options): + dirsrv = ipaservices.knownservices.dirsrv + svc_list = [] + try: +- svc_list = get_config() ++ svc_list = get_config(dirsrv) + except Exception, e: + # ok if dirsrv died this may fail, so let's try to quickly restart it + # and see if we can get anything. If not throw our hands up and just + # exit + try: + dirsrv.start(capture_output=False) +- svc_list = get_config() ++ svc_list = get_config(dirsrv) + except Exception, e: + emit_err("Failed to read data from Directory Service: " + str(e)) + emit_err("Shutting down") +@@ -266,7 +270,7 @@ def ipa_restart(options): + + svc_list = [] + try: +- svc_list = get_config() ++ svc_list = get_config(dirsrv) + except Exception, e: + emit_err("Failed to read data from Directory Service: " + str(e)) + emit_err("Shutting down") +@@ -318,7 +322,7 @@ def ipa_status(options): + + svc_list = [] + try: +- svc_list = get_config() ++ svc_list = get_config(dirsrv) + except IpactlError, e: + raise e + except Exception, e: +diff --git a/ipalib/constants.py b/ipalib/constants.py +index f503472c9b493c6dc4e2ef22281899565d99044d..ad6d188692aa3de70cf29d5662d84672054ab4ef 100644 +--- a/ipalib/constants.py ++++ b/ipalib/constants.py +@@ -111,6 +111,8 @@ DEFAULT_CONFIG = ( + ('xmlrpc_uri', 'http://localhost:8888/ipa/xml'), + ('rpc_json_uri', 'http://localhost:8888/ipa/json'), + ('ldap_uri', 'ldap://localhost:389'), ++ # Time to wait for a service to start, in seconds ++ ('startup_timeout', 120), + + # Web Application mount points + ('mount_ipa', '/ipa/'), +diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py +index 8884e7be92f800f02c4680fb62f5824c50eb0923..e80434cfd31ddb6112e83800aca9cf5440ffaff8 100644 +--- a/ipapython/ipautil.py ++++ b/ipapython/ipautil.py +@@ -41,6 +41,7 @@ import re + import xmlrpclib + import datetime + import netaddr ++import time + from dns import resolver, rdatatype + from dns.exception import DNSException + +@@ -1010,3 +1011,56 @@ def utf8_encode_values(values): + return map(utf8_encode_value, values) + else: + return utf8_encode_value(values) ++ ++def wait_for_open_ports(host, ports, timeout=0): ++ """ ++ Wait until the specified port(s) on the remote host are open. Timeout ++ in seconds may be specified to limit the wait. ++ """ ++ if not isinstance(ports, (tuple, list)): ++ ports = [ports] ++ ++ root_logger.debug('wait_for_open_ports: %s %s timeout %d' % (host, ports, timeout)) ++ op_timeout = time.time() + timeout ++ ipv6_failover = False ++ ++ for port in ports: ++ while True: ++ try: ++ if ipv6_failover: ++ s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) ++ else: ++ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ++ s.connect((host, port)) ++ s.close() ++ break ++ except socket.error, e: ++ if e.errno == 111: # 111: Connection refused ++ if timeout and time.time() > op_timeout: # timeout exceeded ++ raise e ++ time.sleep(1) ++ elif not ipv6_failover: # fallback to IPv6 connection ++ ipv6_failover = True ++ else: ++ raise e ++ ++def wait_for_open_socket(socket_name, timeout=0): ++ """ ++ Wait until the specified socket on the local host is open. Timeout ++ in seconds may be specified to limit the wait. ++ """ ++ op_timeout = time.time() + timeout ++ ++ while True: ++ try: ++ s = socket.socket(socket.AF_UNIX) ++ s.connect(socket_name) ++ s.close() ++ break ++ except socket.error, e: ++ if e.errno in (2,111): # 111: Connection refused, 2: File not found ++ if timeout and time.time() > op_timeout: # timeout exceeded ++ raise e ++ time.sleep(1) ++ else: ++ raise e +diff --git a/ipapython/platform/base.py b/ipapython/platform/base.py +index bf76b76303d221c07c93e7b41e586e06c622696f..6f9d3867ad48360727472f8c5231c030ce9d8bc2 100644 +--- a/ipapython/platform/base.py ++++ b/ipapython/platform/base.py +@@ -18,29 +18,42 @@ + + from ipalib.plugable import MagicDict + +-# Canonical names of services as IPA wants to see them. As we need to have *some* naming, +-# set them as in Red Hat distributions. Actual implementation should make them available +-# through knownservices. and take care of remapping internally, if needed ++# Canonical names of services as IPA wants to see them. As we need to have ++# *some* naming, set them as in Red Hat distributions. Actual implementation ++# should make them available through knownservices. and take care of ++# re-mapping internally, if needed + wellknownservices = ['certmonger', 'dirsrv', 'httpd', 'ipa', 'krb5kdc', + 'messagebus', 'nslcd', 'nscd', 'ntpd', 'portmap', + 'rpcbind', 'kadmin', 'sshd', 'autofs', 'rpcgssd', + 'rpcidmapd'] + + ++# The common ports for these services. This is used to wait for the ++# service to become available. ++wellknownports = { ++ 'dirsrv@PKI-IPA.service': [7389], ++ 'PKI-IPA': [7389], ++ 'dirsrv': [389], # this is only used if the incoming instance name is blank ++ 'pki-cad': [9180], ++} ++ + class AuthConfig(object): + """ + AuthConfig class implements system-independent interface to configure + system authentication resources. In Red Hat systems this is done with + authconfig(8) utility. + +- AuthConfig class is nothing more than a tool to gather configuration options +- and execute their processing. These options then converted by an actual implementation +- to series of a system calls to appropriate utilities performing real configuration. ++ AuthConfig class is nothing more than a tool to gather configuration ++ options and execute their processing. These options then converted by ++ an actual implementation to series of a system calls to appropriate ++ utilities performing real configuration. + +- IPA *expects* names of AuthConfig's options to follow authconfig(8) naming scheme! ++ IPA *expects* names of AuthConfig's options to follow authconfig(8) ++ naming scheme! + +- Actual implementation should be done in ipapython/platform/.py by inheriting from +- platform.AuthConfig and redefining __build_args() and execute() methods. ++ Actual implementation should be done in ipapython/platform/.py ++ by inheriting from platform.AuthConfig and redefining __build_args() ++ and execute() methods. + + from ipapython.platform import platform + class PlatformAuthConfig(platform.AuthConfig): +@@ -53,9 +66,11 @@ class AuthConfig(object): + authconfig = PlatformAuthConfig + .... + +- See ipapython/platform/redhat.py for a sample implementation that uses authconfig(8) as its backend. ++ See ipapython/platform/redhat.py for a sample implementation that uses ++ authconfig(8) as its backend. + +- From IPA code perspective, the authentication configuration should be done with use of ipapython.services.authconfig: ++ From IPA code perspective, the authentication configuration should be ++ done with use of ipapython.services.authconfig: + + from ipapython import services as ipaservices + auth_config = ipaservices.authconfig() +@@ -69,8 +84,8 @@ class AuthConfig(object): + add_parameter("nisdomain","foobar") + auth_config.execute() + +- If you need to re-use existing AuthConfig instance for multiple runs, make sure to +- call 'AuthConfig.reset()' between the runs. ++ If you need to re-use existing AuthConfig instance for multiple runs, ++ make sure to call 'AuthConfig.reset()' between the runs. + """ + + def __init__(self): +@@ -106,21 +121,21 @@ class AuthConfig(object): + + class PlatformService(object): + """ +- PlatformService abstracts out external process running on the system which is possible +- to administer (start, stop, check status, etc). ++ PlatformService abstracts out external process running on the system ++ which is possible to administer (start, stop, check status, etc). + + """ + + def __init__(self, service_name): + self.service_name = service_name + +- def start(self, instance_name="", capture_output=True): ++ def start(self, instance_name="", capture_output=True, wait=True): + return + + def stop(self, instance_name="", capture_output=True): + return + +- def restart(self, instance_name="", capture_output=True): ++ def restart(self, instance_name="", capture_output=True, wait=True): + return + + def is_running(self, instance_name=""): +@@ -149,8 +164,9 @@ class PlatformService(object): + + class KnownServices(MagicDict): + """ +- KnownServices is an abstract class factory that should give out instances of well-known +- platform services. Actual implementation must create these instances as its own attributes +- on first access (or instance creation) and cache them. ++ KnownServices is an abstract class factory that should give out instances ++ of well-known platform services. Actual implementation must create these ++ instances as its own attributes on first access (or instance creation) ++ and cache them. + """ + +diff --git a/ipapython/platform/fedora16.py b/ipapython/platform/fedora16.py +index 985d368f966b0c42222d3af8474e99edbe3477f9..8b730e41cbdd63bbe9d0c9cb7809d0f6d4de8fbb 100644 +--- a/ipapython/platform/fedora16.py ++++ b/ipapython/platform/fedora16.py +@@ -98,7 +98,7 @@ class Fedora16DirectoryService(Fedora16Service): + restore_context(dirsrv_systemd) + ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],raiseonerr=False) + +- def restart(self, instance_name="", capture_output=True): ++ def restart(self, instance_name="", capture_output=True, wait=True): + if len(instance_name) > 0: + elements = self.service_name.split("@") + srv_etc = os.path.join(self.SYSTEMD_ETC_PATH, self.service_name) +@@ -109,7 +109,7 @@ class Fedora16DirectoryService(Fedora16Service): + elif not os.path.samefile(srv_etc, srv_lnk): + os.unlink(srv_lnk) + os.symlink(srv_etc, srv_lnk) +- super(Fedora16DirectoryService, self).restart(instance_name, capture_output=capture_output) ++ super(Fedora16DirectoryService, self).restart(instance_name, capture_output=capture_output, wait=wait) + + # Enforce restart of IPA services when we do enable it + # This gets around the fact that after ipa-server-install systemd thinks +diff --git a/ipapython/platform/redhat.py b/ipapython/platform/redhat.py +index 28a43e588952090007bea979a2cf72d386aa51f9..d3c23ab0debbcfa58eefa9607fe5cac8fcbf592b 100644 +--- a/ipapython/platform/redhat.py ++++ b/ipapython/platform/redhat.py +@@ -26,6 +26,7 @@ import sys + import socket + from ipapython import ipautil + from ipapython.platform import base ++from ipalib import api + + # All what we allow exporting directly from this module + # Everything else is made available through these symbols when they are +@@ -46,14 +47,31 @@ from ipapython.platform import base + __all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status'] + + class RedHatService(base.PlatformService): ++ def __wait_for_open_ports(self, instance_name=""): ++ """ ++ If this is a service we need to wait for do so. ++ """ ++ ports = None ++ if instance_name in base.wellknownports: ++ ports = base.wellknownports[instance_name] ++ else: ++ if self.service_name in base.wellknownports: ++ ports = base.wellknownports[self.service_name] ++ if ports: ++ ipautil.wait_for_open_ports('localhost', ports, api.env.startup_timeout) ++ + def stop(self, instance_name="", capture_output=True): + ipautil.run(["/sbin/service", self.service_name, "stop", instance_name], capture_output=capture_output) + +- def start(self, instance_name="", capture_output=True): ++ def start(self, instance_name="", capture_output=True, wait=True): + ipautil.run(["/sbin/service", self.service_name, "start", instance_name], capture_output=capture_output) ++ if wait and self.is_running(instance_name): ++ self.__wait_for_open_ports(instance_name) + +- def restart(self, instance_name="", capture_output=True): ++ def restart(self, instance_name="", capture_output=True, wait=True): + ipautil.run(["/sbin/service", self.service_name, "restart", instance_name], capture_output=capture_output) ++ if wait and self.is_running(instance_name): ++ self.__wait_for_open_ports(instance_name) + + def is_running(self, instance_name=""): + ret = True +diff --git a/ipapython/platform/systemd.py b/ipapython/platform/systemd.py +index ae06c0227aa59a46b2d4df024fc87577b8bbab29..a233e1045e225718353adbb9bf618a1d0b73c4ac 100644 +--- a/ipapython/platform/systemd.py ++++ b/ipapython/platform/systemd.py +@@ -20,6 +20,7 @@ + from ipapython import ipautil + from ipapython.platform import base + import sys, os, shutil ++from ipalib import api + + class SystemdService(base.PlatformService): + SYSTEMD_ETC_PATH = "/etc/systemd/system/" +@@ -73,16 +74,34 @@ class SystemdService(base.PlatformService): + return (None,None) + return dict(map(lambda x: splitter(x, separator=separator), text.split("\n"))) + ++ def __wait_for_open_ports(self, instance_name=""): ++ """ ++ If this is a service we need to wait for do so. ++ """ ++ ports = None ++ if instance_name in base.wellknownports: ++ ports = base.wellknownports[instance_name] ++ else: ++ elements = self.service_name.split("@") ++ if elements[0] in base.wellknownports: ++ ports = base.wellknownports[elements[0]] ++ if ports: ++ ipautil.wait_for_open_ports('localhost', ports, api.env.startup_timeout) ++ + def stop(self, instance_name="", capture_output=True): + ipautil.run(["/bin/systemctl", "stop", self.service_instance(instance_name)], capture_output=capture_output) + +- def start(self, instance_name="", capture_output=True): ++ def start(self, instance_name="", capture_output=True, wait=True): + ipautil.run(["/bin/systemctl", "start", self.service_instance(instance_name)], capture_output=capture_output) ++ if wait and self.is_running(instance_name): ++ self.__wait_for_open_ports(self.service_instance(instance_name)) + +- def restart(self, instance_name="", capture_output=True): ++ def restart(self, instance_name="", capture_output=True, wait=True): + # Restart command is broken before systemd-36-3.fc16 + # If you have older systemd version, restart of dependent services will hang systemd indefinetly + ipautil.run(["/bin/systemctl", "restart", self.service_instance(instance_name)], capture_output=capture_output) ++ if wait and self.is_running(instance_name): ++ self.__wait_for_open_ports(self.service_instance(instance_name)) + + def is_running(self, instance_name=""): + ret = True +diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py +index af8d39aa524ee801fb1ff5b2b83bee65b1eacb70..62c1dc4d082df740f675d8447a7dd13d69f2ec88 100644 +--- a/ipaserver/install/cainstance.py ++++ b/ipaserver/install/cainstance.py +@@ -681,7 +681,6 @@ class CAInstance(service.Service): + def __restart_instance(self): + try: + self.restart(PKI_INSTANCE_NAME) +- installutils.wait_for_open_ports('localhost', 9180, 300) + except Exception: + # TODO: roll back here? + root_logger.critical("Failed to restart the certificate server. See the installation log for details.") +diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py +index d74ee8987a3387b78ec7203c9b8c70059b35a812..9c137af030e2d86fa3df3e0e987e57d75d53c5d4 100644 +--- a/ipaserver/install/dsinstance.py ++++ b/ipaserver/install/dsinstance.py +@@ -416,7 +416,6 @@ class DsInstance(service.Service): + if not is_ds_running(instance): + root_logger.critical("Failed to restart the directory server. See the installation log for details.") + sys.exit(1) +- installutils.wait_for_open_ports('localhost', self.open_ports, 300) + except SystemExit, e: + raise e + except Exception, e: +@@ -667,7 +666,7 @@ class DsInstance(service.Service): + # (re)start them. + for ds_instance in get_ds_instances(): + try: +- ipaservices.knownservices.dirsrv.restart(ds_instance) ++ ipaservices.knownservices.dirsrv.restart(ds_instance, wait=False) + except Exception, e: + root_logger.error('Unable to restart ds instance %s: %s', ds_instance, e) + +diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py +index 313761777cddcbf5ad9dd134556d72931e51a2b3..b65958eda1b2b6da4db942d77bca63eee1c616f6 100644 +--- a/ipaserver/install/installutils.py ++++ b/ipaserver/install/installutils.py +@@ -414,58 +414,6 @@ def create_keytab(path, principal): + + kadmin("ktadd -k " + path + " " + principal) + +-def wait_for_open_ports(host, ports, timeout=0): +- """ +- Wait until the specified port(s) on the remote host are open. Timeout +- in seconds may be specified to limit the wait. +- """ +- if not isinstance(ports, (tuple, list)): +- ports = [ports] +- +- op_timeout = time.time() + timeout +- ipv6_failover = False +- +- for port in ports: +- while True: +- try: +- if ipv6_failover: +- s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) +- else: +- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +- s.connect((host, port)) +- s.close() +- break; +- except socket.error, e: +- if e.errno == 111: # 111: Connection refused +- if timeout and time.time() > op_timeout: # timeout exceeded +- raise e +- time.sleep(1) +- elif not ipv6_failover: # fallback to IPv6 connection +- ipv6_failover = True +- else: +- raise e +- +-def wait_for_open_socket(socket_name, timeout=0): +- """ +- Wait until the specified socket on the local host is open. Timeout +- in seconds may be specified to limit the wait. +- """ +- op_timeout = time.time() + timeout +- +- while True: +- try: +- s = socket.socket(socket.AF_UNIX) +- s.connect(socket_name) +- s.close() +- break; +- except socket.error, e: +- if e.errno in (2,111): # 111: Connection refused, 2: File not found +- if timeout and time.time() > op_timeout: # timeout exceeded +- raise e +- time.sleep(1) +- else: +- raise e +- + def resolve_host(host_name): + try: + addrinfos = socket.getaddrinfo(host_name, None, +diff --git a/ipaserver/install/plugins/baseupdate.py b/ipaserver/install/plugins/baseupdate.py +index 227dc917aa14ddea898015ef8c16d084860c94df..f91cf5dece314f28bcfb5f4fa8de8716400136ae 100644 +--- a/ipaserver/install/plugins/baseupdate.py ++++ b/ipaserver/install/plugins/baseupdate.py +@@ -34,6 +34,14 @@ class DSRestart(service.Service): + """ + service.Service.__init__(self, "dirsrv") + ++ def start(self, instance_name="", capture_output=True, wait=True): ++ """ ++ During upgrades the server is listening only on the socket so ++ we don't want to wait on ports. The caller is responsible for ++ waiting for the socket to be ready. ++ """ ++ super(DSRestart, self).start(wait=False) ++ + def create_instance(self): + self.step("stopping directory server", self.stop) + self.step("starting directory server", self.start) +diff --git a/ipaserver/install/plugins/updateclient.py b/ipaserver/install/plugins/updateclient.py +index 10d899abcad091a3396d4315d877b5656068775e..e237694711ea5f22d29c0b5ac52f161231951c2d 100644 +--- a/ipaserver/install/plugins/updateclient.py ++++ b/ipaserver/install/plugins/updateclient.py +@@ -18,11 +18,11 @@ + # + + import os +-from ipaserver.install import installutils + from ipaserver.install.plugins import FIRST, MIDDLE, LAST + from ipaserver.install.plugins import POST_UPDATE + from ipaserver.install.plugins.baseupdate import DSRestart + from ipaserver.install.ldapupdate import LDAPUpdate ++from ipapython.ipautil import wait_for_open_socket + from ipalib import api + from ipalib import backend + import ldap as _ldap +@@ -161,7 +161,7 @@ class updateclient(backend.Executioner): + if live_run: + self.destroy_context() + dsrestart.create_instance() +- installutils.wait_for_open_socket(socket_name) ++ wait_for_open_socket(socket_name) + self.create_context(dm_password) + else: + self.log.warn("Test mode, skipping restart") +diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py +index 03758dfcbe302e1d437293f544677fca93e3b21f..417b7a0c5ee29615d2479842efc6862e39a7c3df 100644 +--- a/ipaserver/install/replication.py ++++ b/ipaserver/install/replication.py +@@ -25,7 +25,6 @@ import sys + import ldap + from ipaserver import ipaldap + from ipapython import services as ipaservices +-import installutils + from ldap import modlist + from ipalib import api, util, errors + from ipapython import ipautil +@@ -92,7 +91,6 @@ def enable_replication_version_checking(hostname, realm, dirman_passwd): + conn.unbind() + serverid = "-".join(realm.split(".")) + ipaservices.knownservices.dirsrv.restart(instance_name=serverid) +- installutils.wait_for_open_ports('localhost', [389, 636], 300) + else: + conn.unbind() + +diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py +index 5cc7ae639db3fe2aa3805a90e0902f10f277064c..5c2699e3fa4c115c972528d4c2cc6aa170711837 100644 +--- a/ipaserver/install/service.py ++++ b/ipaserver/install/service.py +@@ -35,6 +35,8 @@ from ipapython.ipa_log_manager import * + + CACERT = "/etc/ipa/ca.crt" + ++# The service name as stored in cn=masters,cn=ipa,cn=etc. In the tuple ++# the first value is the *nix service name, the second the start order. + SERVICE_LIST = { + 'KDC':('krb5kdc', 10), + 'KPASSWD':('kadmin', 20), +@@ -198,11 +200,11 @@ class Service(object): + def stop(self, instance_name="", capture_output=True): + self.service.stop(instance_name, capture_output=capture_output) + +- def start(self, instance_name="", capture_output=True): +- self.service.start(instance_name, capture_output=capture_output) ++ def start(self, instance_name="", capture_output=True, wait=True): ++ self.service.start(instance_name, capture_output=capture_output, wait=wait) + +- def restart(self, instance_name="", capture_output=True): +- self.service.restart(instance_name, capture_output=capture_output) ++ def restart(self, instance_name="", capture_output=True, wait=True): ++ self.service.restart(instance_name, capture_output=capture_output, wait=wait) + + def is_running(self): + return self.service.is_running() +diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py +index b04d92afcb31d66c3f4c98e80b1bc54d4887e518..f1f702b1c51eed0277fd4f02f5c1d4048292d894 100644 +--- a/ipaserver/install/upgradeinstance.py ++++ b/ipaserver/install/upgradeinstance.py +@@ -60,6 +60,11 @@ class IPAUpgrade(service.Service): + self.badsyntax = False + self.upgradefailed = False + ++ def start(self, instance_name="", capture_output=True, wait=True): ++ # Don't wait here because we've turned off port 389. The connection ++ # we make will wait for the socket. ++ super(IPAUpgrade, self).start(instance_name, capture_output, wait=False) ++ + def create_instance(self): + self.step("stopping directory server", self.stop) + self.step("saving configuration", self.__save_config) +diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py +index 8b5451c730f0a4cc72a597f934a940dc2b143a05..e4fa2c644c660e34a1d675497a22837255a36b75 100644 +--- a/ipaserver/ipaldap.py ++++ b/ipaserver/ipaldap.py +@@ -36,10 +36,9 @@ from ldap.controls import LDAPControl + from ldap.ldapobject import SimpleLDAPObject + from ipapython import ipautil + from ipalib import errors +-from ipapython.ipautil import format_netloc ++from ipapython.ipautil import format_netloc, wait_for_open_socket, wait_for_open_ports + from ipapython.entity import Entity + from ipaserver.plugins.ldap2 import IPASimpleLDAPObject +-from ipaserver.install import installutils + + # Global variable to define SASL auth + SASL_AUTH = ldap.sasl.sasl({},'GSSAPI') +@@ -337,10 +336,10 @@ class IPAdmin(IPAEntryLDAPObject): + def __wait_for_connection(self, timeout): + lurl = ldapurl.LDAPUrl(self._uri) + if lurl.urlscheme == 'ldapi': +- installutils.wait_for_open_socket(lurl.hostport, timeout) ++ wait_for_open_socket(lurl.hostport, timeout) + else: + (host,port) = lurl.hostport.split(':') +- installutils.wait_for_open_ports(host, int(port), timeout) ++ wait_for_open_ports(host, int(port), timeout) + + def __bind_with_wait(self, bind_func, timeout, *args, **kwargs): + try: +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-001-ipasam-improve-sasl-bind-callback.patch b/freeipa-3.0.0.pre1-001-ipasam-improve-sasl-bind-callback.patch new file mode 100644 index 0000000..6b07db0 --- /dev/null +++ b/freeipa-3.0.0.pre1-001-ipasam-improve-sasl-bind-callback.patch @@ -0,0 +1,312 @@ +From e88049ecee0bf5ca5741eaf94dd5a7341eec061e Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 4 Jul 2012 20:47:03 +0300 +Subject: [PATCH 01/79] ipasam: improve SASL bind callback + +SASL bind callback due to refactoring was referencing local variable which +didn't exist all the time. Fix that by including a copy of service principals +into ipasam long term private struct. + +Rework ccache handling to avoid re-initing every time callback is called +--- + daemons/ipa-sam/ipa_sam.c | 180 ++++++++++++++++++++++++++++++---------- + install/share/smb.conf.template | 1 - + 2 files changed, 137 insertions(+), 44 deletions(-) + +diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c +index 9baac1b2d35a640c36fe7f95a6154ec8582649d8..1f2d94ed4da552a7f4ede443fe9944839c633e59 100644 +--- a/daemons/ipa-sam/ipa_sam.c ++++ b/daemons/ipa-sam/ipa_sam.c +@@ -177,6 +177,8 @@ struct ipasam_privates { + char *trust_dn; + char *flat_name; + char *fallback_primary_group; ++ char *server_princ; ++ char *client_princ; + }; + + static LDAP *priv2ld(struct ldapsam_privates *priv) +@@ -3125,12 +3127,20 @@ static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *s + return ret; + } + +-static void bind_callback_cleanup(struct ipasam_sasl_interact_priv *data) ++static void bind_callback_cleanup(struct ipasam_sasl_interact_priv *data, krb5_error_code rc) + { ++ const char *errstring = NULL; ++ + if (!data->context) { + return; + } + ++ if (rc) { ++ errstring = krb5_get_error_message(data->context, rc); ++ DEBUG(0,("kerberos error: code=%d, message=%s\n", rc, errstring)); ++ krb5_free_error_message(data->context, errstring); ++ } ++ + krb5_free_cred_contents(data->context, &data->creds); + + if (data->options) { +@@ -3157,22 +3167,27 @@ static void bind_callback_cleanup(struct ipasam_sasl_interact_priv *data) + data->context = NULL; + } + +-extern const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def); +-static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, void* ipasam_principal) ++static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, void* ipasam_priv) + { +- char *ccache_name = NULL; + krb5_error_code rc; ++ krb5_creds *out_creds = NULL; ++ krb5_creds in_creds; + + struct ipasam_sasl_interact_priv data; ++ struct ipasam_privates *ipasam_private = NULL; + int ret; + + memset(&data, 0, sizeof(struct ipasam_sasl_interact_priv)); +- data.name = (const char*)ipasam_principal; +- if (data.name == NULL) { +- DEBUG(0, ("bind_callback: ipasam:principal is not set, cannot use GSSAPI bind\n")); ++ memset(&in_creds, 0, sizeof(krb5_creds)); ++ ++ ipasam_private = (struct ipasam_privates*)ipasam_priv; ++ ++ if ((ipasam_private->client_princ == NULL) || (ipasam_private->server_princ == NULL)) { ++ DEBUG(0, ("bind_callback: ipasam service principals are not set, cannot use GSSAPI bind\n")); + return LDAP_LOCAL_ERROR; + } + ++ data.name = ipasam_private->client_princ; + data.name_len = strlen(data.name); + + rc = krb5_init_context(&data.context); +@@ -3182,60 +3197,60 @@ static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, vo + + rc = krb5_parse_name(data.context, data.name, &data.principal); + if (rc) { +- bind_callback_cleanup(&data); ++ bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; + } + + rc = krb5_cc_default(data.context, &data.ccache); +- if (rc) { +- bind_callback_cleanup(&data); +- return LDAP_LOCAL_ERROR; +- } +- +- rc = krb5_cc_initialize(data.context, data.ccache, data.principal); +- if (rc) { +- bind_callback_cleanup(&data); +- return LDAP_LOCAL_ERROR; +- } +- +- rc = krb5_cc_get_full_name(data.context, data.ccache, &ccache_name); +- if (rc) { +- if (ccache_name) { +- krb5_free_string(data.context, ccache_name); +- } +- bind_callback_cleanup(&data); +- return LDAP_LOCAL_ERROR; +- } + +- rc = krb5_cc_set_default_name(data.context, ccache_name); + if (rc) { +- bind_callback_cleanup(&data); ++ bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; + } + + rc = krb5_kt_resolve(data.context, "FILE:/etc/samba/samba.keytab", &data.keytab); + if (rc) { +- bind_callback_cleanup(&data); ++ bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; + } + +- rc = krb5_get_init_creds_opt_alloc(data.context, &data.options); ++ rc = krb5_parse_name(data.context, ipasam_private->client_princ, &in_creds.client); + if (rc) { +- bind_callback_cleanup(&data); ++ krb5_free_principal(data.context, data.creds.client); ++ bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; + } + +- rc = krb5_get_init_creds_opt_set_out_ccache(data.context, data.options, data.ccache); ++ rc = krb5_parse_name(data.context, ipasam_private->server_princ, &in_creds.server); + if (rc) { +- bind_callback_cleanup(&data); ++ krb5_free_principal(data.context, in_creds.server); ++ bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; + } + +- rc = krb5_get_init_creds_keytab(data.context, &data.creds, data.principal, data.keytab, +- 0, NULL, data.options); ++ rc = krb5_get_credentials(data.context, KRB5_GC_CACHED, data.ccache, &in_creds, &out_creds); ++ krb5_free_principal(data.context, in_creds.server); ++ krb5_free_principal(data.context, in_creds.client); ++ + if (rc) { +- bind_callback_cleanup(&data); +- return LDAP_LOCAL_ERROR; ++ rc = krb5_get_init_creds_opt_alloc(data.context, &data.options); ++ if (rc) { ++ bind_callback_cleanup(&data, rc); ++ return LDAP_LOCAL_ERROR; ++ } ++ ++ rc = krb5_get_init_creds_opt_set_out_ccache(data.context, data.options, data.ccache); ++ if (rc) { ++ bind_callback_cleanup(&data, rc); ++ return LDAP_LOCAL_ERROR; ++ } ++ ++ rc = krb5_get_init_creds_keytab(data.context, &data.creds, data.principal, data.keytab, ++ 0, NULL, data.options); ++ if (rc) { ++ bind_callback_cleanup(&data, rc); ++ return LDAP_LOCAL_ERROR; ++ } + } + + ret = ldap_sasl_interactive_bind_s(ldap_struct, +@@ -3247,10 +3262,90 @@ static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, vo + DEBUG(0, ("bind_callback: cannot perform interactive SASL bind with GSSAPI\n")); + } + +- bind_callback_cleanup(&data); ++ if (out_creds) { ++ krb5_free_creds(data.context, out_creds); ++ } ++ bind_callback_cleanup(&data, 0); + return ret; + } + ++static NTSTATUS ipasam_generate_principals(struct ipasam_privates *privates) { ++ ++ krb5_error_code rc; ++ int ret; ++ krb5_context context; ++ NTSTATUS status = NT_STATUS_UNSUCCESSFUL; ++ char hostname[255]; ++ char *default_realm = NULL; ++ ++ if (!privates) { ++ return status; ++ } ++ ++ rc = krb5_init_context(&context); ++ if (rc) { ++ return status; ++ } ++ ++ ret = gethostname(hostname, sizeof(hostname)); ++ if (ret == -1) { ++ DEBUG(1, ("gethostname failed.\n")); ++ goto done; ++ } ++ hostname[sizeof(hostname)-1] = '\0'; ++ ++ rc = krb5_get_default_realm(context, &default_realm); ++ if (rc) { ++ goto done; ++ }; ++ ++ if (privates->client_princ) { ++ talloc_free(privates->client_princ); ++ privates->client_princ = NULL; ++ } ++ ++ privates->client_princ = talloc_asprintf(privates, ++ "cifs/%s@%s", ++ hostname, ++ default_realm); ++ ++ if (privates->client_princ == NULL) { ++ DEBUG(0, ("Failed to create ipasam client principal.\n")); ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ if (privates->server_princ) { ++ talloc_free(privates->server_princ); ++ privates->server_princ = NULL; ++ } ++ ++ privates->server_princ = talloc_asprintf(privates, ++ "ldap/%s@%s", ++ hostname, ++ default_realm); ++ ++ if (privates->server_princ == NULL) { ++ DEBUG(0, ("Failed to create ipasam server principal.\n")); ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ status = NT_STATUS_OK; ++ ++done: ++ ++ if (default_realm) { ++ krb5_free_default_realm(context, default_realm); ++ } ++ ++ if (context) { ++ krb5_free_context(context); ++ } ++ return status; ++} ++ ++ + static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method, + const char *location) + { +@@ -3263,7 +3358,6 @@ static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method, + struct dom_sid ldap_domain_sid; + char *bind_dn = NULL; + char *bind_secret = NULL; +- const char *service_principal = NULL; + + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; +@@ -3293,9 +3387,9 @@ static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method, + } + trim_char( uri, '\"', '\"' ); + +- service_principal = lp_parm_const_string(-1, "ipasam", "principal", NULL); ++ status = ipasam_generate_principals(ldap_state->ipasam_privates); + +- if (service_principal == NULL) { ++ if (!NT_STATUS_IS_OK(status)) { + if (!fetch_ldap_pw(&bind_dn, &bind_secret)) { + DEBUG(0, ("pdb_init_ipasam: Failed to retrieve LDAP password from secrets.tdb\n")); + return NT_STATUS_NO_MEMORY; +@@ -3310,7 +3404,7 @@ static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method, + &ldap_state->smbldap_state); + if (NT_STATUS_IS_OK(status)) { + ldap_state->smbldap_state->bind_callback = bind_callback; +- ldap_state->smbldap_state->bind_callback_data = service_principal; ++ ldap_state->smbldap_state->bind_callback_data = ldap_state->ipasam_privates; + } + } + +diff --git a/install/share/smb.conf.template b/install/share/smb.conf.template +index 3107350aa6e94514354b73f0152846e1d01e1e68..086b0fcfe5cff2bc3582f2a89962a99c9095b4bb 100644 +--- a/install/share/smb.conf.template ++++ b/install/share/smb.conf.template +@@ -18,7 +18,6 @@ ldap suffix = $SUFFIX + ldap user suffix = cn=users,cn=accounts + ldap group suffix = cn=groups,cn=accounts + ldap machine suffix = cn=computers,cn=accounts +-ipasam:principal = cifs/$FQDN@$REALM + rpc_server:epmapper = external + rpc_server:lsarpc = external + rpc_server:lsass = external +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-002-allow-silent-build-if-available.patch b/freeipa-3.0.0.pre1-002-allow-silent-build-if-available.patch new file mode 100644 index 0000000..3749a35 --- /dev/null +++ b/freeipa-3.0.0.pre1-002-allow-silent-build-if-available.patch @@ -0,0 +1,24 @@ +From 7fb9ca23a1e9f80aca3d23bb4a52a1428f4fb79d Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 4 Jul 2012 12:15:05 +0200 +Subject: [PATCH 02/79] Allow silent build if available + +--- + daemons/configure.ac | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/daemons/configure.ac b/daemons/configure.ac +index b94673026a2c6b71670a67b1f629d9960d8fad31..ebf625ebffd8a92e0a3b050955b9376e002ed6c9 100644 +--- a/daemons/configure.ac ++++ b/daemons/configure.ac +@@ -7,6 +7,7 @@ AC_INIT([ipa-server], + AC_CONFIG_HEADERS([config.h]) + + AM_INIT_AUTOMAKE([foreign]) ++m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) + + AM_MAINTAINER_MODE + AC_PROG_CC +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-003-ipasam-fixes-for-clang-warnings.patch b/freeipa-3.0.0.pre1-003-ipasam-fixes-for-clang-warnings.patch new file mode 100644 index 0000000..efd086b --- /dev/null +++ b/freeipa-3.0.0.pre1-003-ipasam-fixes-for-clang-warnings.patch @@ -0,0 +1,120 @@ +From abe40284cf5dda1e34e3ba73711448f61eea67b9 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 4 Jul 2012 16:18:21 +0200 +Subject: [PATCH 03/79] ipasam: fixes for clang warnings + +--- + daemons/ipa-sam/ipa_sam.c | 48 ++++++++++++++++++++--------------------------- + 1 file changed, 20 insertions(+), 28 deletions(-) + +diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c +index 1f2d94ed4da552a7f4ede443fe9944839c633e59..50d2b0ea7432db262faf867b5a2265a38669e189 100644 +--- a/daemons/ipa-sam/ipa_sam.c ++++ b/daemons/ipa-sam/ipa_sam.c +@@ -100,19 +100,6 @@ bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid + char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s); /* available in libsmbconf.so */ + extern const struct dom_sid global_sid_Builtin; /* available in libsecurity.so */ + bool secrets_store(const char *key, const void *data, size_t size); /* available in libpdb.so */ +-/* from smb_macros.h */ +-#define SMB_REALLOC_ARRAY(p,type,count) (type *)realloc_array((p),sizeof(type),(count),true) /* Always frees p on error or s == 0 */ +-#define ADD_TO_ARRAY(mem_ctx, type, elem, array, num) \ +-do { \ +- *(array) = ((mem_ctx) != NULL) ? \ +- talloc_realloc(mem_ctx, (*(array)), type, (*(num))+1) : \ +- SMB_REALLOC_ARRAY((*(array)), type, (*(num))+1); \ +- SMB_ASSERT((*(array)) != NULL); \ +- (*(array))[*(num)] = (elem); \ +- (*(num)) += 1; \ +-} while (0) +- +- + #define LDAP_SUFFIX "dc=ipa,dc=devel" /* FIXME !!! */ + #define LDAP_PAGE_SIZE 1024 + #define LDAP_OBJ_SAMBASAMACCOUNT "ipaNTUserAttrs" +@@ -1217,8 +1204,6 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods, + return false; + } + +- state->connection = ldap_state->smbldap_state; +- + state->base = talloc_strdup(search, LDAP_SUFFIX); + state->connection = ldap_state->smbldap_state; + state->scope = LDAP_SCOPE_SUBTREE; +@@ -1403,7 +1388,9 @@ static int set_cross_realm_pw(struct ldapsam_privates *ldap_state, + goto done; + } + +- ret = create_keys(krbctx, service_princ, discard_const(pwd), NULL, &keys, &err_msg); ++ ret = create_keys(krbctx, service_princ, discard_const(pwd), NULL, ++ &keys, &err_msg); ++ krb5_free_principal(krbctx, service_princ); + if (!ret) { + if (err_msg != NULL) { + DEBUG(1, ("create_keys returned [%s]\n", err_msg)); +@@ -1438,7 +1425,6 @@ done: + ber_bvfree(reqdata); + } + free_keys_contents(krbctx, &keys); +- krb5_free_principal(krbctx, service_princ); + krb5_free_context(krbctx); + + return ret; +@@ -2246,6 +2232,7 @@ static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods, + int scope = LDAP_SCOPE_SUBTREE; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; ++ struct pdb_trusted_domain **tmp; + + filter = talloc_asprintf(mem_ctx, "(objectClass=%s)", + LDAP_OBJ_TRUSTED_DOMAIN); +@@ -2286,16 +2273,20 @@ static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods, + + if (!fill_pdb_trusted_domain(*domains, ldap_state, entry, + &dom_info)) { ++ talloc_free(*domains); + return NT_STATUS_UNSUCCESSFUL; + } + +- ADD_TO_ARRAY(*domains, struct pdb_trusted_domain *, dom_info, +- domains, num_domains); +- +- if (*domains == NULL) { +- DEBUG(1, ("talloc failed\n")); ++ tmp = talloc_realloc(*domains, *domains, ++ struct pdb_trusted_domain *, ++ (*(num_domains))+1); ++ if (tmp == NULL) { ++ talloc_free(*domains); + return NT_STATUS_NO_MEMORY; + } ++ *domains = tmp; ++ (*(domains))[*(num_domains)] = dom_info; ++ (*(num_domains)) += 1; + } + + DEBUG(5, ("ipasam_enum_trusted_domains: got %d domains\n", *num_domains)); +@@ -2700,14 +2691,15 @@ static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods, + goto done; + } + ++ status = get_trust_pwd(tmp_ctx, &td->trust_auth_incoming, ++ &trustpw, &last_update); ++ if (!NT_STATUS_IS_OK(status)) { ++ ret = false; ++ goto done; ++ } ++ + /* trusteddom_pw routines do not use talloc yet... */ + if (pwd != NULL) { +- status = get_trust_pwd(tmp_ctx, &td->trust_auth_incoming, +- &trustpw, &last_update); +- if (!NT_STATUS_IS_OK(status)) { +- ret = false; +- goto done; +- } + *pwd = strdup(trustpw); + memset(trustpw, 0, strlen(trustpw)); + talloc_free(trustpw); +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-004-ipasam-replace-testing-code.patch b/freeipa-3.0.0.pre1-004-ipasam-replace-testing-code.patch new file mode 100644 index 0000000..02139d2 --- /dev/null +++ b/freeipa-3.0.0.pre1-004-ipasam-replace-testing-code.patch @@ -0,0 +1,50 @@ +From 76d809574bfb43cba2248225870644937546e33e Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 4 Jul 2012 16:19:03 +0200 +Subject: [PATCH 04/79] ipasam: replace testing code + +--- + daemons/ipa-sam/ipa_sam.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c +index 50d2b0ea7432db262faf867b5a2265a38669e189..153733dbfea35cf1426f73827fb83753c259491b 100644 +--- a/daemons/ipa-sam/ipa_sam.c ++++ b/daemons/ipa-sam/ipa_sam.c +@@ -100,7 +100,7 @@ bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid + char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s); /* available in libsmbconf.so */ + extern const struct dom_sid global_sid_Builtin; /* available in libsecurity.so */ + bool secrets_store(const char *key, const void *data, size_t size); /* available in libpdb.so */ +-#define LDAP_SUFFIX "dc=ipa,dc=devel" /* FIXME !!! */ ++ + #define LDAP_PAGE_SIZE 1024 + #define LDAP_OBJ_SAMBASAMACCOUNT "ipaNTUserAttrs" + #define LDAP_OBJ_TRUSTED_DOMAIN "ipaNTTrustedDomain" +@@ -1045,12 +1045,12 @@ static bool ldapsam_search_users(struct pdb_methods *methods, + state->connection = ldap_state->smbldap_state; + + if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0)) +- state->base = LDAP_SUFFIX; ++ state->base = ldap_state->ipasam_privates->base_dn; + else if ((acct_flags != 0) && + ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0)) +- state->base = LDAP_SUFFIX; ++ state->base = ldap_state->ipasam_privates->base_dn; + else +- state->base = LDAP_SUFFIX; ++ state->base = ldap_state->ipasam_privates->base_dn; + + state->acct_flags = acct_flags; + state->base = talloc_strdup(search, state->base); +@@ -1204,7 +1204,7 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods, + return false; + } + +- state->base = talloc_strdup(search, LDAP_SUFFIX); ++ state->base = talloc_strdup(search, ldap_state->ipasam_privates->base_dn); + state->connection = ldap_state->smbldap_state; + state->scope = LDAP_SCOPE_SUBTREE; + state->filter = talloc_asprintf(search, "(&(objectclass=%s)" +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-005-use-smb.conf-dedicated-keytab-file-parameter-instead.patch b/freeipa-3.0.0.pre1-005-use-smb.conf-dedicated-keytab-file-parameter-instead.patch new file mode 100644 index 0000000..b946b2f --- /dev/null +++ b/freeipa-3.0.0.pre1-005-use-smb.conf-dedicated-keytab-file-parameter-instead.patch @@ -0,0 +1,34 @@ +From 75cb9bb0e15f31940576e3a366b58a340c6953d8 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Fri, 6 Jul 2012 12:43:50 +0300 +Subject: [PATCH 05/79] Use smb.conf 'dedicated keytab file' parameter instead + of hard-coded value + +--- + daemons/ipa-sam/ipa_sam.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c +index 153733dbfea35cf1426f73827fb83753c259491b..29fc95e457179716c1c70c6f061b1cde9e3f472b 100644 +--- a/daemons/ipa-sam/ipa_sam.c ++++ b/daemons/ipa-sam/ipa_sam.c +@@ -3159,6 +3159,7 @@ static void bind_callback_cleanup(struct ipasam_sasl_interact_priv *data, krb5_e + data->context = NULL; + } + ++extern const char * lp_dedicated_keytab_file(void); + static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, void* ipasam_priv) + { + krb5_error_code rc; +@@ -3200,7 +3201,7 @@ static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, vo + return LDAP_LOCAL_ERROR; + } + +- rc = krb5_kt_resolve(data.context, "FILE:/etc/samba/samba.keytab", &data.keytab); ++ rc = krb5_kt_resolve(data.context, lp_dedicated_keytab_file(), &data.keytab); + if (rc) { + bind_callback_cleanup(&data, rc); + return LDAP_LOCAL_ERROR; +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-006-reduce-redundant-checks-in-ldapsam_search_users-to-a.patch b/freeipa-3.0.0.pre1-006-reduce-redundant-checks-in-ldapsam_search_users-to-a.patch new file mode 100644 index 0000000..90199a7 --- /dev/null +++ b/freeipa-3.0.0.pre1-006-reduce-redundant-checks-in-ldapsam_search_users-to-a.patch @@ -0,0 +1,35 @@ +From 8c5504d26ac3a2bbbb2cc9112eece70dac22a658 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Fri, 6 Jul 2012 12:48:27 +0300 +Subject: [PATCH 06/79] reduce redundant checks in ldapsam_search_users() to a + single statement + +--- + daemons/ipa-sam/ipa_sam.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c +index 29fc95e457179716c1c70c6f061b1cde9e3f472b..86ed3fbd3e6d1894fd398c3c1c94d34c2b7ec273 100644 +--- a/daemons/ipa-sam/ipa_sam.c ++++ b/daemons/ipa-sam/ipa_sam.c +@@ -1044,16 +1044,9 @@ static bool ldapsam_search_users(struct pdb_methods *methods, + + state->connection = ldap_state->smbldap_state; + +- if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0)) +- state->base = ldap_state->ipasam_privates->base_dn; +- else if ((acct_flags != 0) && +- ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0)) +- state->base = ldap_state->ipasam_privates->base_dn; +- else +- state->base = ldap_state->ipasam_privates->base_dn; ++ state->base = talloc_strdup(search, ldap_state->ipasam_privates->base_dn); + + state->acct_flags = acct_flags; +- state->base = talloc_strdup(search, state->base); + state->scope = LDAP_SCOPE_SUBTREE; + state->filter = get_ldap_filter(search, "*"); + state->attrs = talloc_attrs(search, "uid", LDAP_ATTRIBUTE_SID, +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-007-moved-configuration-to-last-position-in-navigation.patch b/freeipa-3.0.0.pre1-007-moved-configuration-to-last-position-in-navigation.patch new file mode 100644 index 0000000..51e4f72 --- /dev/null +++ b/freeipa-3.0.0.pre1-007-moved-configuration-to-last-position-in-navigation.patch @@ -0,0 +1,32 @@ +From 61c3b86d734389b2cd77b73030bd5293111e2cc5 Mon Sep 17 00:00:00 2001 +From: Petr Vobornik +Date: Wed, 4 Jul 2012 15:15:10 +0200 +Subject: [PATCH 07/79] Moved configuration to last position in navigation + +Configaration was the last navigation item in IPA server tab. Trusts changed it. It was wrong because configuration is like 'other settings' and so it should be last. + +This patch moves configuration navigation item to the last position again. + +https://fedorahosted.org/freeipa/ticket/2900 +--- + install/ui/webui.js | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/install/ui/webui.js b/install/ui/webui.js +index 9b7c31be4c4f5edd2f3bd4bfab3559a5cb2aef4c..0be4b1b630888010f6c0e5dc95307acc335a47f6 100644 +--- a/install/ui/webui.js ++++ b/install/ui/webui.js +@@ -84,8 +84,8 @@ IPA.admin_navigation = function(spec) { + ]}, + {entity: 'selfservice'}, + {entity: 'delegation'}, +- {entity: 'config'}, +- {entity: 'trust'} ++ {entity: 'trust'}, ++ {entity: 'config'} + ]}]; + + var that = IPA.navigation(spec); +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-008-fix-wrong-check-after-allocation.patch b/freeipa-3.0.0.pre1-008-fix-wrong-check-after-allocation.patch new file mode 100644 index 0000000..691c831 --- /dev/null +++ b/freeipa-3.0.0.pre1-008-fix-wrong-check-after-allocation.patch @@ -0,0 +1,25 @@ +From 6ffb35d0f592414226d4ba4fd3620569e77c20ca Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Fri, 6 Jul 2012 16:11:32 -0400 +Subject: [PATCH 08/79] Fix wrong check after allocation. + +--- + daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c +index 5720d3e6e0a7e6b1520e51a5ee319bcc47354fc9..9c1623a3b28932fba48c878dc6084862a2ba7831 100644 +--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c ++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c +@@ -446,7 +446,7 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg, + + if (is_ipant) { + *ntvals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *)); +- if (!svals) { ++ if (!*ntvals) { + LOG_OOM(); + rc = LDAP_OPERATIONS_ERROR; + goto done; +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-009-fix-typo.patch b/freeipa-3.0.0.pre1-009-fix-typo.patch new file mode 100644 index 0000000..d112e2f --- /dev/null +++ b/freeipa-3.0.0.pre1-009-fix-typo.patch @@ -0,0 +1,26 @@ +From 0ffb2022fe2c485fce99c335e6b5f1f8c768152c Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 26 Jun 2012 09:58:01 +0200 +Subject: [PATCH 09/79] Fix typo + +Signed-off-by: Simo Sorce +--- + daemons/ipa-kdb/ipa_kdb_mspac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index f640b545a636a2c58e3eb31951de142e5b0ffbe2..1c7487c3c8f75d02466a2e0746fbef5d36e3d995 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -1267,7 +1267,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context, + + kerr = krb5_encode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, +- &authdata, ++ authdata, + signed_auth_data); + if (kerr != 0) { + goto done; +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-010-do-not-change-ldapobject-objectclass-list.patch b/freeipa-3.0.0.pre1-010-do-not-change-ldapobject-objectclass-list.patch new file mode 100644 index 0000000..6a7332a --- /dev/null +++ b/freeipa-3.0.0.pre1-010-do-not-change-ldapobject-objectclass-list.patch @@ -0,0 +1,35 @@ +From 5ba8eeb970a8a72ec189e80e369bb7f70091e409 Mon Sep 17 00:00:00 2001 +From: Martin Kosek +Date: Mon, 9 Jul 2012 14:27:07 +0200 +Subject: [PATCH 10/79] Do not change LDAPObject objectclass list + +__json__ method of LDAPObject may inadvertently append a list of possible +objectclasses to a list of basic objectclasses and thus change a behavior +of all subsequent LDAPSearch command. The command may only return objects +where all "possible" objectclasses are present and thus returning an +incomplete list. + +Make sure that the LDAPObject object_class list is not modified during +the __json__ method. + +https://fedorahosted.org/freeipa/ticket/2906 +--- + ipalib/plugins/baseldap.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py +index b841435fdcb5e28195fd38a6792233fdc4b7e32a..6a37995c57cd9d57280186d15f209426aa0776f2 100644 +--- a/ipalib/plugins/baseldap.py ++++ b/ipalib/plugins/baseldap.py +@@ -635,7 +635,7 @@ class LDAPObject(Object): + objectclasses = config.get( + self.object_class_config, objectclasses + ) +- objectclasses += self.possible_objectclasses ++ objectclasses = objectclasses + self.possible_objectclasses + # Get list of available attributes for this object for use + # in the ACI UI. + attrs = self.api.Backend.ldap2.schema.attribute_types(objectclasses) +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-011-make-client-server-option-multi-valued-allow-disabli.patch b/freeipa-3.0.0.pre1-011-make-client-server-option-multi-valued-allow-disabli.patch new file mode 100644 index 0000000..0d756a5 --- /dev/null +++ b/freeipa-3.0.0.pre1-011-make-client-server-option-multi-valued-allow-disabli.patch @@ -0,0 +1,319 @@ +From 29fd982f7f3bf4b94a8420fdfb307ed9c43c515c Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 3 Jul 2012 17:37:22 -0400 +Subject: [PATCH 11/79] Make client server option multi-valued, allow + disabling DNS discovery + +Let the --server option be specified multiple times on the command line. +The first one passed in is the one we enroll against. + +Do additional verification before setting dnsok so we can be sure that +the record(s) were actually discovered in DNS. + +If servers are provided on the CLI and --fixed-primary is set then +_srv_ is not added to ipa_server in sssd.conf. + +https://fedorahosted.org/freeipa/ticket/2841 +--- + ipa-client/ipa-install/ipa-client-install | 101 +++++++++++++++++++----------- + ipa-client/ipaclient/ipadiscovery.py | 3 + + ipa-client/man/ipa-client-install.1 | 4 +- + 3 files changed, 70 insertions(+), 38 deletions(-) + +diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install +index 4b8d826ddad4bdee3b352833225768fa8c5f05b5..ef0dc293c994cdf8165a610f0701ade5b14942e6 100755 +--- a/ipa-client/ipa-install/ipa-client-install ++++ b/ipa-client/ipa-install/ipa-client-install +@@ -65,7 +65,7 @@ def parse_options(): + + basic_group = OptionGroup(parser, "basic options") + basic_group.add_option("--domain", dest="domain", help="domain name") +- basic_group.add_option("--server", dest="server", help="IPA server") ++ basic_group.add_option("--server", dest="server", help="IPA server", action="append") + basic_group.add_option("--realm", dest="realm_name", help="realm name") + basic_group.add_option("--fixed-primary", dest="primary", action="store_true", + default=False, help="Configure sssd to use fixed server as primary IPA server") +@@ -487,8 +487,8 @@ def configure_ipa_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server): + defopts = [{'name':'basedn', 'type':'option', 'value':cli_basedn}, + {'name':'realm', 'type':'option', 'value':cli_realm}, + {'name':'domain', 'type':'option', 'value':cli_domain}, +- {'name':'server', 'type':'option', 'value':cli_server}, +- {'name':'xmlrpc_uri', 'type':'option', 'value':'https://%s/ipa/xml' % ipautil.format_netloc(cli_server)}, ++ {'name':'server', 'type':'option', 'value':cli_server[0]}, ++ {'name':'xmlrpc_uri', 'type':'option', 'value':'https://%s/ipa/xml' % ipautil.format_netloc(cli_server[0])}, + {'name':'enable_ra', 'type':'option', 'value':'True'}] + + opts.append({'name':'global', 'type':'section', 'value':defopts}) +@@ -525,7 +525,7 @@ def configure_ldap_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, d + if options.on_master: + opts.append({'name':'uri', 'type':'option', 'value':'ldap://localhost'}) + else: +- opts.append({'name':'uri', 'type':'option', 'value':'ldap://'+ipautil.format_netloc(cli_server)}) ++ opts.append({'name':'uri', 'type':'option', 'value':'ldap://'+ipautil.format_netloc(cli_server[0])}) + else: + opts.append({'name':'nss_srv_domain', 'type':'option', 'value':cli_domain}) + +@@ -564,7 +564,7 @@ def configure_nslcd_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, + if options.on_master: + opts.append({'name':'uri', 'type':'option', 'value':'ldap://localhost'}) + else: +- opts.append({'name':'uri', 'type':'option', 'value':'ldap://'+ipautil.format_netloc(cli_server)}) ++ opts.append({'name':'uri', 'type':'option', 'value':'ldap://'+ipautil.format_netloc(cli_server[0])}) + else: + opts.append({'name':'uri', 'type':'option', 'value':'DNS'}) + +@@ -604,7 +604,7 @@ def configure_openldap_conf(fstore, cli_basedn, cli_server): + + opts = [{'name':'comment', 'type':'comment', 'value':'File modified by ipa-client-install'}, + {'name':'empty', 'type':'empty'}, +- {'name':'URI', 'type':'option', 'value':'ldaps://'+ cli_server}, ++ {'name':'URI', 'type':'option', 'value':'ldaps://'+ cli_server[0]}, + {'name':'BASE', 'type':'option', 'value':cli_basedn}, + {'name':'TLS_CACERT', 'type':'option', 'value':'/etc/ipa/ca.crt'}, + {'name':'empty', 'type':'empty'}] +@@ -625,13 +625,13 @@ def hardcode_ldap_server(cli_server): + ldapconf = ipaclient.ipachangeconf.IPAChangeConf("IPA Installer") + ldapconf.setOptionAssignment(" ") + +- opts = [{'name':'uri', 'type':'option', 'action':'set', 'value':'ldap://'+ipautil.format_netloc(cli_server)}, ++ opts = [{'name':'uri', 'type':'option', 'action':'set', 'value':'ldap://'+ipautil.format_netloc(cli_server[0])}, + {'name':'empty', 'type':'empty'}] + + # Errors raised by this should be caught by the caller + ldapconf.changeConf("/etc/ldap.conf", opts) + root_logger.info("Changed configuration of /etc/ldap.conf to use " + +- "hardcoded server name: %s", cli_server) ++ "hardcoded server name: %s", cli_server[0]) + + return + +@@ -662,13 +662,13 @@ def configure_krb5_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, c + opts.append({'name':'empty', 'type':'empty'}) + + #the following are necessary only if DNS discovery does not work ++ kropts = [] + if not dnsok or not cli_kdc or options.force: + #[realms] +- kropts =[{'name':'kdc', 'type':'option', 'value':ipautil.format_netloc(cli_server, 88)}, +- {'name':'admin_server', 'type':'option', 'value':ipautil.format_netloc(cli_server, 749)}, +- {'name':'default_domain', 'type':'option', 'value':cli_domain}] +- else: +- kropts = [] ++ for server in cli_server: ++ kropts.append({'name':'kdc', 'type':'option', 'value':ipautil.format_netloc(server, 88)}) ++ kropts.append({'name':'admin_server', 'type':'option', 'value':ipautil.format_netloc(server, 749)}) ++ kropts.append({'name':'default_domain', 'type':'option', 'value':cli_domain}) + kropts.append({'name':'pkinit_anchors', 'type':'option', 'value':'FILE:/etc/ipa/ca.crt'}) + ropts = [{'name':cli_realm, 'type':'subsection', 'value':kropts}] + +@@ -814,12 +814,12 @@ def configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server, options, clie + + if not options.on_master: + if options.primary: +- domain.set_option('ipa_server', '%s, _srv_' % cli_server) ++ domain.set_option('ipa_server', ', '.join(cli_server)) + else: +- domain.set_option('ipa_server', '_srv_, %s' % cli_server) ++ domain.set_option('ipa_server', '_srv_, %s' % ', '.join(cli_server)) + else: + # the master should only use itself for Kerberos +- domain.set_option('ipa_server', cli_server) ++ domain.set_option('ipa_server', cli_server[0]) + domain.set_option('ipa_domain', cli_domain) + domain.set_option('ipa_hostname', client_hostname) + if cli_domain.lower() != cli_realm.lower(): +@@ -1169,6 +1169,8 @@ def install(options, env, fstore, statestore): + # Create the discovery instance + ds = ipadiscovery.IPADiscovery() + ++ # Do discovery on the first server passed in, we'll do sanity checking ++ # on any others + ret = ds.search(domain=options.domain, server=options.server, hostname=hostname) + + if ret == ipadiscovery.BAD_HOST_CONFIG: +@@ -1227,21 +1229,37 @@ def install(options, env, fstore, statestore): + return CLIENT_INSTALL_ERROR + else: + root_logger.debug("DNS discovery failed to find the IPA Server") +- cli_server = user_input("Provide your IPA server name (ex: ipa.example.com)", allow_empty = False) ++ cli_server = [user_input("Provide your IPA server name (ex: ipa.example.com)", allow_empty = False)] + cli_server_source = 'Provided interactively' +- root_logger.debug("will use interactively provided server: %s", cli_server) ++ root_logger.debug("will use interactively provided server: %s", cli_server[0]) + ret = ds.search(domain=cli_domain, server=cli_server, hostname=hostname) ++ + else: +- dnsok = True ++ # Only set dnsok to True if we were not passed in one or more servers ++ # and if DNS discovery actually worked. ++ if not options.server: ++ (server, domain) = ds.check_domain(ds.domain, set(), "Validating DNS Discovery") ++ if server and domain: ++ root_logger.debug("DNS validated, enabling discovery") ++ dnsok = True ++ else: ++ root_logger.debug("DNS discovery failed, disabling discovery") ++ else: ++ root_logger.debug("Using servers from command line, disabling DNS discovery") ++ + if not cli_server: +- if ds.server: +- cli_server = ds.server ++ if options.server: ++ cli_server = options.server ++ cli_server_source = 'Provided as option' ++ root_logger.debug("will use provided server: %s", ', '.join(options.server)) ++ elif ds.server: ++ cli_server = [ds.server] + cli_server_source = ds.server_source +- root_logger.debug("will use discovered server: %s", cli_server) ++ root_logger.debug("will use discovered server: %s", cli_server[0]) + + if ret == ipadiscovery.NOT_IPA_SERVER: +- root_logger.error("%s is not an IPA v2 Server.", cli_server) +- root_logger.debug("(%s: %s)", cli_server, cli_server_source) ++ root_logger.error("%s is not an IPA v2 Server.", cli_server[0]) ++ root_logger.debug("(%s: %s)", cli_server[0], cli_server_source) + return CLIENT_INSTALL_ERROR + + if ret == ipadiscovery.NO_ACCESS_TO_LDAP: +@@ -1253,10 +1271,10 @@ def install(options, env, fstore, statestore): + + if ret != 0: + root_logger.error("Failed to verify that %s is an IPA Server.", +- cli_server) ++ cli_server[0]) + root_logger.error("This may mean that the remote server is not up " + + "or is not reachable due to network or firewall settings.") +- root_logger.debug("(%s: %s)", cli_server, cli_server_source) ++ root_logger.debug("(%s: %s)", cli_server[0], cli_server_source) + return CLIENT_INSTALL_ERROR + + cli_kdc = ds.kdc +@@ -1269,8 +1287,10 @@ def install(options, env, fstore, statestore): + if dnsok: + root_logger.info("Discovery was successful!") + elif not options.unattended: +- root_logger.warning("The failure to use DNS to find your IPA server " + +- "indicates that your resolv.conf file is not properly configured.") ++ if not options.server: ++ root_logger.warning("The failure to use DNS to find your IPA" + ++ " server indicates that your resolv.conf file is not properly" + ++ " configured.") + root_logger.info("Autodiscovery of servers for failover cannot work " + + "with this configuration.") + root_logger.info("If you proceed with the installation, services " + +@@ -1296,13 +1316,22 @@ def install(options, env, fstore, statestore): + root_logger.debug("will use discovered basedn: %s", cli_basedn) + subject_base = "O=%s" % cli_realm + ++ # Now do a sanity check on the other servers ++ if options.server and len(options.server) > 1: ++ for server in options.server[1:]: ++ ret = ds.search(domain=cli_domain, server=server, hostname=hostname) ++ if ret == ipadiscovery.NOT_IPA_SERVER: ++ root_logger.error("%s is not an IPA v2 Server.", server) ++ root_logger.debug("(%s: %s)", server, cli_server_source) ++ return CLIENT_INSTALL_ERROR ++ + root_logger.info("Hostname: %s", hostname) + root_logger.debug("Hostname source: %s", hostname_source) + root_logger.info("Realm: %s", cli_realm) + root_logger.debug("Realm source: %s", cli_realm_source) + root_logger.info("DNS Domain: %s", cli_domain) + root_logger.debug("DNS Domain source: %s", cli_domain_source) +- root_logger.info("IPA Server: %s", cli_server) ++ root_logger.info("IPA Server: %s", ', '.join(cli_server)) + root_logger.debug("IPA Server source: %s", cli_server_source) + root_logger.info("BaseDN: %s", cli_basedn) + root_logger.debug("BaseDN source: %s", cli_basedn_source) +@@ -1347,10 +1376,10 @@ def install(options, env, fstore, statestore): + pass + + try: +- run(["/usr/bin/wget", "-O", "/etc/ipa/ca.crt", "http://%s/ipa/config/ca.crt" % ipautil.format_netloc(cli_server)]) ++ run(["/usr/bin/wget", "-O", "/etc/ipa/ca.crt", "http://%s/ipa/config/ca.crt" % ipautil.format_netloc(cli_server[0])]) + except CalledProcessError, e: + root_logger.error( +- 'Retrieving CA from %s failed: %s', cli_server, str(e)) ++ 'Retrieving CA from %s failed: %s', cli_server[0], str(e)) + return CLIENT_INSTALL_ERROR + + if not options.on_master: +@@ -1369,7 +1398,7 @@ def install(options, env, fstore, statestore): + if synced_ntp: + break + if not synced_ntp: +- synced_ntp = ipaclient.ntpconf.synconce_ntp(cli_server, debug=True) ++ synced_ntp = ipaclient.ntpconf.synconce_ntp(cli_server[0], debug=True) + if not synced_ntp: + root_logger.warning("Unable to sync time with IPA NTP " + + "server, assuming the time is in sync.") +@@ -1379,7 +1408,7 @@ def install(options, env, fstore, statestore): + root_logger.error("Test kerberos configuration failed") + return CLIENT_INSTALL_ERROR + env['KRB5_CONFIG'] = krb_name +- join_args = ["/usr/sbin/ipa-join", "-s", cli_server, "-b", realm_to_suffix(cli_realm)] ++ join_args = ["/usr/sbin/ipa-join", "-s", cli_server[0], "-b", realm_to_suffix(cli_realm)] + if options.debug: + join_args.append("-d") + env['XMLRPC_TRACE_CURL'] = 'yes' +@@ -1542,10 +1571,10 @@ def install(options, env, fstore, statestore): + return CLIENT_INSTALL_ERROR + + if not options.on_master: +- client_dns(cli_server, hostname, options.dns_updates) ++ client_dns(cli_server[0], hostname, options.dns_updates) + configure_certmonger(fstore, subject_base, cli_realm, hostname, options) + +- update_ssh_keys(cli_server, hostname, ipaservices.knownservices.sshd.get_config_dir(), options.create_sshfp) ++ update_ssh_keys(cli_server[0], hostname, ipaservices.knownservices.sshd.get_config_dir(), options.create_sshfp) + + try: + os.remove(CCACHE_FILE) +@@ -1677,7 +1706,7 @@ def install(options, env, fstore, statestore): + if options.ntp_server: + ntp_server = options.ntp_server + else: +- ntp_server = cli_server ++ ntp_server = cli_server[0] + ipaclient.ntpconf.config_ntp(ntp_server, fstore, statestore) + root_logger.info("NTP enabled") + +diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py +index f8c8b5c6db14ccbc24b0eb3becad9fa868d8c3aa..ca13d9c1902771bb45aca4f3d2b83720007c1f48 100644 +--- a/ipa-client/ipaclient/ipadiscovery.py ++++ b/ipa-client/ipaclient/ipadiscovery.py +@@ -141,6 +141,9 @@ class IPADiscovery(object): + 'Starting IPA discovery with domain=%s, server=%s, hostname=%s', + domain, server, hostname) + ++ if type(server) in (list, tuple): ++ server = server[0] ++ + if not server: + + if not domain: #domain not provided do full DNS discovery +diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1 +index caf59571926d293d05cf87d6a94746207f04c51f..2ee5a1a04d45ef2e85db708c2ae0786cca363991 100644 +--- a/ipa-client/man/ipa-client-install.1 ++++ b/ipa-client/man/ipa-client-install.1 +@@ -42,13 +42,13 @@ Client must use a \fBstatic hostname\fR. If the machine hostname changes for exa + Set the domain name to DOMAIN + .TP + \fB\-\-server\fR=\fISERVER\fR +-Set the IPA server to connect to ++Set the IPA server to connect to. May be specified multiple times to add multiple servers to ipa_server value in sssd.conf. Only the first value is considered when used with \-\-no\-sssd. + .TP + \fB\-\-realm\fR=\fIREALM_NAME\fR + Set the IPA realm name to REALM_NAME + .TP + \fB\-\-fixed\-primary\fR +-Configure sssd to use a fixed server as the primary IPA server. The default is to use DNS SRV records to determine the primary server to use and fall back to the server the client is enrolled with. ++Configure sssd to use a fixed server as the primary IPA server. The default is to use DNS SRV records to determine the primary server to use and fall back to the server the client is enrolled with. When used in conjunction with \-\-server then no _srv_ value is set in the ipa_server option in sssd.conf. + .TP + \fB\-p\fR, \fB\-\-principal\fR + Authorized kerberos principal to use to join the IPA realm. +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-012-display-loginas-information-only-after-login.patch b/freeipa-3.0.0.pre1-012-display-loginas-information-only-after-login.patch new file mode 100644 index 0000000..a8caefa --- /dev/null +++ b/freeipa-3.0.0.pre1-012-display-loginas-information-only-after-login.patch @@ -0,0 +1,100 @@ +From 05cf7c53a69b7c999ac68c2869db924e2dccc3a0 Mon Sep 17 00:00:00 2001 +From: Petr Vobornik +Date: Thu, 28 Jun 2012 14:42:29 +0200 +Subject: [PATCH 12/79] Display loginas information only after login + +Message 'Logged in as: user@FREEIPA.ORG' was displayed before user was logged in. It was wrong. + +Now 'Logged in as: XXX' is displayed only when user XXX is logged in. So no more user@FREEIPA.ORG :) . + +https://fedorahosted.org/freeipa/ticket/2882 +--- + install/ui/index.html | 6 +++--- + install/ui/ipa.css | 4 ++++ + install/ui/ipa.js | 6 +++++- + install/ui/webui.js | 5 ++++- + 4 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/install/ui/index.html b/install/ui/index.html +index 33c0923c197d53824d79591488b18dda2ea90ad2..cfa7a4c8136639e05f4345352a9bf4188ed2af89 100644 +--- a/install/ui/index.html ++++ b/install/ui/index.html +@@ -71,10 +71,10 @@ + + + +- +- Logged in as: user@FREEIPA.ORG ++ +- ++ + +diff --git a/install/ui/ipa.css b/install/ui/ipa.css +index dac345ac39c92c30aa6b8c9754eb325c41152c28..d6ad5806038f47919404615f224f5ed75a917563 100644 +--- a/install/ui/ipa.css ++++ b/install/ui/ipa.css +@@ -262,6 +262,10 @@ body { + color: #fff; + } + ++.header-loggedinas .login { ++ font-weight: bold; ++} ++ + /* ---- Navigation ---- */ + #navigation { + position: absolute; +diff --git a/install/ui/ipa.js b/install/ui/ipa.js +index aadea8d2af07c1d0c7f5ae1b8168a36966c546c5..2547a24d283a40480660b9b8d22d1c91e5edbbe8 100644 +--- a/install/ui/ipa.js ++++ b/install/ui/ipa.js +@@ -157,7 +157,6 @@ var IPA = function() { + on_success: function(data, text_status, xhr) { + that.whoami = batch ? data.result[0] : data.result.result[0]; + that.principal = that.whoami.krbprincipalname[0]; +- that.update_password_expiration(); + } + }); + }; +@@ -516,6 +515,11 @@ IPA.password_selfservice = function() { + self_service: true, + on_success: function() { + var command = IPA.get_whoami_command(); ++ var orig_on_success = command.on_success; ++ command.on_success = function(data, text_status, xhr) { ++ orig_on_success.call(this, data, text_status, xhr); ++ IPA.update_password_expiration(); ++ }; + command.execute(); + + alert(IPA.messages.password.password_change_complete); +diff --git a/install/ui/webui.js b/install/ui/webui.js +index 0be4b1b630888010f6c0e5dc95307acc335a47f6..66efdb2cf7c90780cb2647ccdbb93ebb5bf79540 100644 +--- a/install/ui/webui.js ++++ b/install/ui/webui.js +@@ -167,7 +167,7 @@ $(function() { + + var whoami = IPA.whoami; + IPA.whoami_pkey = whoami.uid[0]; +- $('#loggedinas strong').text(whoami.cn[0]); ++ $('#loggedinas .login').text(whoami.cn[0]); + $('#loggedinas a').fragment( + {'user-facet': 'details', 'user-pkey': IPA.whoami_pkey}, 2); + +@@ -176,6 +176,9 @@ $(function() { + return false; + }).text(IPA.messages.login.logout); + ++ $('.header-loggedinas').css('visibility','visible'); ++ IPA.update_password_expiration(); ++ + IPA.nav = create_navigation(); + IPA.nav.create(); + IPA.nav.update(); +-- +1.7.11.2 + diff --git a/freeipa-3.0.0.pre1-013-password-policy-measurement-units.patch b/freeipa-3.0.0.pre1-013-password-policy-measurement-units.patch new file mode 100644 index 0000000..929cf23 --- /dev/null +++ b/freeipa-3.0.0.pre1-013-password-policy-measurement-units.patch @@ -0,0 +1,183 @@ +From 848bd0e9e738a4590049a223868dcfe6749a9154 Mon Sep 17 00:00:00 2001 +From: Petr Vobornik +Date: Mon, 9 Jul 2012 16:58:00 +0200 +Subject: [PATCH 13/79] Password policy measurement units. + +When filling password policy it may be unclear what value to enter because user may not remember field's measurement unit. + +This patch adds support for declaring measurement units. It's done in field's/widget's spec by entering key for unit's string (which is in IPA.messages.measurement_units[key]). + +Measurement units in table layout are displayed in parenthesis after label. It is to be consistent with some fields which have measurement unit integrated in label. + +This patch defines measurement units for password policy's 'History size', 'Failure reset interval' and 'Lockout duration' fields. + +https://fedorahosted.org/freeipa/ticket/2437 +--- + install/ui/field.js | 6 ++++-- + install/ui/policy.js | 15 ++++++++++++--- + install/ui/test/data/ipa_init.json | 4 ++++ + install/ui/user.js | 9 ++++++--- + install/ui/widget.js | 15 ++++++++++++++- + ipalib/plugins/internal.py | 4 ++++ + 6 files changed, 44 insertions(+), 9 deletions(-) + +diff --git a/install/ui/field.js b/install/ui/field.js +index 84ec0c4dfa5c77b72da06eb4d2ff64ccac633f65..fb292ff2a6c5fb29b84262236fd5be2c7c7f7e42 100644 +--- a/install/ui/field.js ++++ b/install/ui/field.js +@@ -35,6 +35,7 @@ IPA.field = function(spec) { + that.param = spec.param || spec.name; + that.label = spec.label; + that.tooltip = spec.tooltip; ++ that.measurement_unit = spec.measurement_unit; + that.formatter = spec.formatter; + + that.widget = null; +@@ -348,8 +349,9 @@ IPA.field = function(spec) { + that.set_widget_flags = function() { + + if (that.widget) { +- if(that.label) that.widget.label = that.label; +- if(that.title) that.widget.title = that.title; ++ if (that.label) that.widget.label = that.label; ++ if (that.title) that.widget.title = that.title; ++ if (that.measurement_unit) that.widget.measurement_unit = that.measurement_unit; + that.widget.undo = that.undo; + that.widget.writable = that.writable; + that.widget.read_only = that.read_only; +diff --git a/install/ui/policy.js b/install/ui/policy.js +index 604664f1263e97a7e0007b26b392372fb87b0923..acad0c8c2c2ba6f2f8c26407627b56c75d79dfb5 100644 +--- a/install/ui/policy.js ++++ b/install/ui/policy.js +@@ -48,12 +48,21 @@ IPA.pwpolicy.entity = function(spec) { + }, + 'krbmaxpwdlife', + 'krbminpwdlife', +- 'krbpwdhistorylength', ++ { ++ name: 'krbpwdhistorylength', ++ measurement_unit: 'number_of_passwords' ++ }, + 'krbpwdmindiffchars', + 'krbpwdminlength', + 'krbpwdmaxfailure', +- 'krbpwdfailurecountinterval', +- 'krbpwdlockoutduration', ++ { ++ name: 'krbpwdfailurecountinterval', ++ measurement_unit: 'seconds' ++ }, ++ { ++ name: 'krbpwdlockoutduration', ++ measurement_unit: 'seconds' ++ }, + 'cospriority' + ] + }]}). +diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json +index 85ff9366ce4ad293b95829d864653561a55d6429..527d09163eda854bd779c1362b8272582150e90e 100644 +--- a/install/ui/test/data/ipa_init.json ++++ b/install/ui/test/data/ipa_init.json +@@ -138,6 +138,10 @@ + "password": "Password", + "username": "Username" + }, ++ "measurement_units": { ++ "number_of_passwords": "number of passwords", ++ "seconds": "seconds" ++ }, + "objects": { + "aci": { + "attribute": "Attribute" +diff --git a/install/ui/user.js b/install/ui/user.js +index 02f6f73e45e50b8c5501ccad57209a681100082d..24873ecf55d5e9159d77dc061d73f3d2e318e30d 100644 +--- a/install/ui/user.js ++++ b/install/ui/user.js +@@ -149,7 +149,8 @@ IPA.user.entity = function(spec) { + { + name: 'krbpwdhistorylength', + label: IPA.get_entity_param('pwpolicy', 'krbpwdhistorylength').label, +- read_only: true ++ read_only: true, ++ measurement_unit: 'number_of_passwords' + }, + { + name: 'krbpwdmindiffchars', +@@ -169,12 +170,14 @@ IPA.user.entity = function(spec) { + { + name: 'krbpwdfailurecountinterval', + label: IPA.get_entity_param('pwpolicy', 'krbpwdfailurecountinterval').label, +- read_only: true ++ read_only: true, ++ measurement_unit: 'seconds' + }, + { + name: 'krbpwdlockoutduration', + label: IPA.get_entity_param('pwpolicy', 'krbpwdlockoutduration').label, +- read_only: true ++ read_only: true, ++ measurement_unit: 'seconds' + } + ] + }, +diff --git a/install/ui/widget.js b/install/ui/widget.js +index a55cc347f49cc2e61f00422f12c47ab4c1c70449..64547da7d439cb622c03d6f73afb310be83a6338 100644 +--- a/install/ui/widget.js ++++ b/install/ui/widget.js +@@ -36,6 +36,7 @@ IPA.widget = function(spec) { + that.id = spec.id; + that.label = spec.label; + that.tooltip = spec.tooltip; ++ that.measurement_unit = spec.measurement_unit; + that.entity = IPA.get_entity(spec.entity); //some old widgets still need it + that.facet = spec.facet; + +@@ -2688,10 +2689,12 @@ IPA.table_layout = function(spec) { + title: widget.label + }).appendTo(tr); + ++ var label_text = widget.label + that.get_measurement_unit_text(widget) + ':'; ++ + $('