diff --git a/.gitignore b/.gitignore
index 24c01ff..7ac1e50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
-SOURCES/freeipa-3.3.3.tar.gz
-SOURCES/rh-ipabanner.png
+SOURCES/freeipa-4.1.0.tar.gz
+SOURCES/header-logo.png
+SOURCES/login-screen-background.jpg
+SOURCES/login-screen-logo.png
+SOURCES/product-name.png
diff --git a/.ipa.metadata b/.ipa.metadata
index 65afa93..04fe802 100644
--- a/.ipa.metadata
+++ b/.ipa.metadata
@@ -1,2 +1,5 @@
-32702b534b3f82c141107820283833d54d8287f2 SOURCES/freeipa-3.3.3.tar.gz
-7460c1ae34b05ea659275fe169c19f94a28db2f7 SOURCES/rh-ipabanner.png
+40a07c0e64a696dccb5d377c635db136cbc7c2a5 SOURCES/freeipa-4.1.0.tar.gz
+77c318cf1f4fc25cf847de0692a77859a767c0e3 SOURCES/header-logo.png
+8727245558422bf966d60677568925f081b8e299 SOURCES/login-screen-background.jpg
+24a29d79efbd0906777be4639957abda111fca4b SOURCES/login-screen-logo.png
+af82b7b7d327bd683c7d062a6f15713ea91ebedf SOURCES/product-name.png
diff --git a/SOURCES/0001-Do-not-check-if-port-8443-is-available-in-step-2-of-.patch b/SOURCES/0001-Do-not-check-if-port-8443-is-available-in-step-2-of-.patch
new file mode 100644
index 0000000..ae05dc9
--- /dev/null
+++ b/SOURCES/0001-Do-not-check-if-port-8443-is-available-in-step-2-of-.patch
@@ -0,0 +1,54 @@
+From e22cf5bafc4c862a16bd8ac0b950c7547b048ae9 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 22 Oct 2014 11:18:35 +0200
+Subject: [PATCH] Do not check if port 8443 is available in step 2 of external
+ CA install
+
+The port is never available in step 2 of external CA install, as Dogtag is
+already running.
+
+https://fedorahosted.org/freeipa/ticket/4660
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/tools/ipa-ca-install     | 3 ++-
+ install/tools/ipa-server-install | 9 +++++----
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
+index cb072e6789401f7041cafe926d7f88b2bb7f479d..1bda22dd66729999176c301af2f9b05843eff75c 100755
+--- a/install/tools/ipa-ca-install
++++ b/install/tools/ipa-ca-install
+@@ -301,7 +301,8 @@ def install_master(safe_options, options):
+     domain_name = api.env.domain
+     host_name = api.env.host
+ 
+-    check_ca()
++    if external != 2:
++        check_ca()
+ 
+     dirname = dsinstance.config_dirname(
+         dsinstance.realm_to_serverid(realm_name))
+diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
+index 0394314ee99817f221536136ae1432cc8e92220a..67dd21f302db0eba94d048cb064caf8a1f054b83 100755
+--- a/install/tools/ipa-server-install
++++ b/install/tools/ipa-server-install
+@@ -869,10 +869,11 @@ def main():
+         # Make sure the 389-ds ports are available
+         check_dirsrv(options.unattended)
+ 
+-    if setup_ca:
+-        if not cainstance.check_port():
+-            print "IPA requires port 8443 for PKI but it is currently in use."
+-            sys.exit("Aborting installation")
++        if setup_ca:
++            if not cainstance.check_port():
++                print ("IPA requires port 8443 for PKI but it is currently in "
++                       "use.")
++                sys.exit("Aborting installation")
+ 
+     if options.conf_ntp:
+         try:
+-- 
+1.9.3
+
diff --git a/SOURCES/0001-Guard-import-of-adtrustinstance-for-case-without-tru.patch b/SOURCES/0001-Guard-import-of-adtrustinstance-for-case-without-tru.patch
deleted file mode 100644
index 4202105..0000000
--- a/SOURCES/0001-Guard-import-of-adtrustinstance-for-case-without-tru.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 90ac36c780d6e5d0bcb26f8c7f153d35af1db70f Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Mon, 4 Nov 2013 17:15:23 +0200
-Subject: [PATCH] Guard import of adtrustinstance for case without trusts
-
-https://fedorahosted.org/freeipa/ticket/4011
----
- install/tools/ipa-server-install | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
-index b3dcf6d93a70e2910a3d7fa62139efbf640d1cbe..458ebba550d0fe7675bd874e23c7d730c53297e6 100755
---- a/install/tools/ipa-server-install
-+++ b/install/tools/ipa-server-install
-@@ -40,7 +40,12 @@ import pwd
- import textwrap
- from optparse import OptionGroup, OptionValueError
- 
--from ipaserver.install import adtrustinstance
-+try:
-+    from ipaserver.install import adtrustinstance
-+    _server_trust_ad_installed = True
-+except ImportError:
-+    _server_trust_ad_installed = False
-+
- from ipaserver.install import dsinstance
- from ipaserver.install import krbinstance
- from ipaserver.install import bindinstance
-@@ -493,7 +498,8 @@ def uninstall():
-     httpinstance.HTTPInstance(fstore).uninstall()
-     krbinstance.KrbInstance(fstore).uninstall()
-     dsinstance.DsInstance(fstore=fstore).uninstall()
--    adtrustinstance.ADTRUSTInstance(fstore).uninstall()
-+    if _server_trust_ad_installed:
-+        adtrustinstance.ADTRUSTInstance(fstore).uninstall()
-     memcacheinstance.MemcacheInstance().uninstall()
-     otpdinstance.OtpdInstance().uninstall()
-     ipaservices.restore_network_configuration(fstore, sstore)
--- 
-1.8.3.1
-
diff --git a/SOURCES/0002-Add-ipaSshPubkey-and-gidNumber-to-the-ACI-to-read-ID.patch b/SOURCES/0002-Add-ipaSshPubkey-and-gidNumber-to-the-ACI-to-read-ID.patch
new file mode 100644
index 0000000..cf1764e
--- /dev/null
+++ b/SOURCES/0002-Add-ipaSshPubkey-and-gidNumber-to-the-ACI-to-read-ID.patch
@@ -0,0 +1,42 @@
+From 8e4181b467d4135dccb23400f8afad6141f44b3a Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 24 Oct 2014 15:01:27 +0300
+Subject: [PATCH] Add ipaSshPubkey and gidNumber to the ACI to read ID user
+ overrides
+
+https://fedorahosted.org/freeipa/ticket/4664
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ACI.txt                   | 2 +-
+ ipalib/plugins/idviews.py | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ACI.txt b/ACI.txt
+index 27a5d2f3458ab313437060a9daea470a8f4e5203..6680f658ee1aa0f961b2681f700557ce6b9238f8 100644
+--- a/ACI.txt
++++ b/ACI.txt
+@@ -131,7 +131,7 @@ aci: (targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:S
+ dn: cn=views,cn=accounts,dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || description || entryusn || gidnumber || ipaanchoruuid || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaGroupOverride)")(version 3.0;acl "permission:System: Read Group ID Overrides";allow (compare,read,search) userdn = "ldap:///all";)
+ dn: cn=views,cn=accounts,dc=ipa,dc=example
+-aci: (targetattr = "createtimestamp || description || entryusn || gecos || homedirectory || ipaanchoruuid || ipaoriginaluid || loginshell || modifytimestamp || objectclass || uid || uidnumber")(targetfilter = "(objectclass=ipaUserOverride)")(version 3.0;acl "permission:System: Read User ID Overrides";allow (compare,read,search) userdn = "ldap:///all";)
++aci: (targetattr = "createtimestamp || description || entryusn || gecos || gidnumber || homedirectory || ipaanchoruuid || ipaoriginaluid || ipasshpubkey || loginshell || modifytimestamp || objectclass || uid || uidnumber")(targetfilter = "(objectclass=ipaUserOverride)")(version 3.0;acl "permission:System: Read User ID Overrides";allow (compare,read,search) userdn = "ldap:///all";)
+ dn: cn=ranges,cn=etc,dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || entryusn || ipabaseid || ipabaserid || ipaidrangesize || ipanttrusteddomainsid || iparangetype || ipasecondarybaserid || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaidrange)")(version 3.0;acl "permission:System: Read ID Ranges";allow (compare,read,search) userdn = "ldap:///all";)
+ dn: cn=views,cn=accounts,dc=ipa,dc=example
+diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py
+index bfa8675fb84a1d1e13f44b31e9384c9c783f4c4e..9c8721018325f56e681f168b55c31055bfd07345 100644
+--- a/ipalib/plugins/idviews.py
++++ b/ipalib/plugins/idviews.py
+@@ -659,6 +659,7 @@ class idoverrideuser(baseidoverride):
+             'ipapermdefaultattr': {
+                 'objectClass', 'ipaAnchorUUID', 'uidNumber', 'description',
+                 'homeDirectory', 'uid', 'ipaOriginalUid', 'loginShell', 'gecos',
++                'gidNumber', 'ipaSshPubkey',
+             },
+         },
+     }
+-- 
+2.1.0
+
diff --git a/SOURCES/0002-Server-does-not-detect-different-server-and-IPA-doma.patch b/SOURCES/0002-Server-does-not-detect-different-server-and-IPA-doma.patch
deleted file mode 100644
index 9b81558..0000000
--- a/SOURCES/0002-Server-does-not-detect-different-server-and-IPA-doma.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 8955e9f236ea9ca3ccfd32cb17c6b4baf9d492a2 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Wed, 6 Nov 2013 10:14:40 +0100
-Subject: [PATCH] Server does not detect different server and IPA domain
-
-Server installer does not properly recognize a situation when server
-fqdn is not in a subdomain of the IPA domain, but shares the same
-suffix.
-
-For example, if server FQDN is ipa-idm.example.com and domain
-is idm.example.com, server's FQDN is not in the main domain, but
-installer does not recognize that. proper Kerberos realm-domain
-mapping is not created in this case and server does not work
-(httpd reports gssapi errors).
-
-https://fedorahosted.org/freeipa/ticket/4012
----
- ipaserver/install/krbinstance.py | 18 +++++++++++-------
- 1 file changed, 11 insertions(+), 7 deletions(-)
-
-diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
-index a16e4d5f0cb3b70c6c69aac3251785ef3e8fa7f2..98687a4002cd7b19faea03acc552759e962d8832 100644
---- a/ipaserver/install/krbinstance.py
-+++ b/ipaserver/install/krbinstance.py
-@@ -24,6 +24,7 @@
- import os
- import pwd
- import socket
-+import dns.name
- 
- import service
- import installutils
-@@ -237,15 +238,18 @@ def __setup_sub_dict(self):
- 
-         # IPA server/KDC is not a subdomain of default domain
-         # Proper domain-realm mapping needs to be specified
--        dr_map = ''
--        if not self.fqdn.endswith(self.domain):
--            root_logger.debug("IPA FQDN '%s' is not located in default domain '%s'" \
--                    % (self.fqdn, self.domain))
--            server_host, dot, server_domain = self.fqdn.partition('.')
--            root_logger.debug("Domain '%s' needs additional mapping in krb5.conf" \
--                    % server_domain)
-+        domain = dns.name.from_text(self.domain)
-+        fqdn = dns.name.from_text(self.fqdn)
-+        if not fqdn.is_subdomain(domain):
-+            root_logger.debug("IPA FQDN '%s' is not located in default domain '%s'",
-+                    fqdn, domain)
-+            server_domain = fqdn.parent().to_unicode(omit_final_dot=True)
-+            root_logger.debug("Domain '%s' needs additional mapping in krb5.conf",
-+                server_domain)
-             dr_map = " .%(domain)s = %(realm)s\n %(domain)s = %(realm)s\n" \
-                         % dict(domain=server_domain, realm=self.realm)
-+        else:
-+            dr_map = ""
-         self.sub_dict['OTHER_DOMAIN_REALM_MAPS'] = dr_map
- 
-     def __configure_sasl_mappings(self):
--- 
-1.8.3.1
-
diff --git a/SOURCES/0003-Allow-kernel-keyring-CCACHE-when-supported.patch b/SOURCES/0003-Allow-kernel-keyring-CCACHE-when-supported.patch
deleted file mode 100644
index d205d06..0000000
--- a/SOURCES/0003-Allow-kernel-keyring-CCACHE-when-supported.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 7726ddeb7506b9b68720f55c410d7c53b7098d91 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Fri, 29 Nov 2013 13:29:20 +0100
-Subject: [PATCH 03/10] Allow kernel keyring CCACHE when supported
-
-Server and client installer should allow kernel keyring ccache when
-supported.
-
-https://fedorahosted.org/freeipa/ticket/4013
----
- install/share/krb5.conf.template          |  2 +-
- ipa-client/ipa-install/ipa-client-install |  7 +++++++
- ipapython/kernel_keyring.py               | 17 +++++++++++++++++
- ipaserver/install/krbinstance.py          | 10 ++++++++++
- 4 files changed, 35 insertions(+), 1 deletion(-)
-
-diff --git a/install/share/krb5.conf.template b/install/share/krb5.conf.template
-index 01e66881b0a38e342886727ec205ea9b7c057ad2..7c82083e3331cfacccc1995cd9dfa6ddd88edd1f 100644
---- a/install/share/krb5.conf.template
-+++ b/install/share/krb5.conf.template
-@@ -12,7 +12,7 @@ includedir /var/lib/sss/pubconf/krb5.include.d/
-  rdns = false
-  ticket_lifetime = 24h
-  forwardable = yes
--
-+$OTHER_LIBDEFAULTS
- [realms]
-  $REALM = {
-   kdc = $FQDN:88
-diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
-index 8e4695b42e9178725353dee2a4797a8da9b635b3..a898d388ee039752044008f8525424370098580a 100755
---- a/ipa-client/ipa-install/ipa-client-install
-+++ b/ipa-client/ipa-install/ipa-client-install
-@@ -43,6 +43,7 @@ try:
-         run, user_input, CalledProcessError, file_exists, realm_to_suffix)
-     import ipapython.services as ipaservices
-     from ipapython import ipautil, sysrestore, version, certmonger, ipaldap
-+    from ipapython import kernel_keyring
-     from ipapython.config import IPAOptionParser
-     from ipalib import api, errors
-     from ipalib import x509
-@@ -926,6 +927,12 @@ def configure_krb5_conf(cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
-     libopts.append({'name':'ticket_lifetime', 'type':'option', 'value':'24h'})
-     libopts.append({'name':'forwardable', 'type':'option', 'value':'yes'})
- 
-+    # Configure KEYRING CCACHE if supported
-+    if kernel_keyring.is_persistent_keyring_supported():
-+        root_logger.debug("Enabling persistent keyring CCACHE")
-+        libopts.append({'name':'default_ccache_name', 'type':'option',
-+            'value':'KEYRING:persistent:%{uid}'})
-+
-     opts.append({'name':'libdefaults', 'type':'section', 'value':libopts})
-     opts.append({'name':'empty', 'type':'empty'})
- 
-diff --git a/ipapython/kernel_keyring.py b/ipapython/kernel_keyring.py
-index 547dd3de6b45295910b66982e99886135c06335b..d30531cabaee5c12376f0821a21a6f63cd60397c 100644
---- a/ipapython/kernel_keyring.py
-+++ b/ipapython/kernel_keyring.py
-@@ -17,6 +17,8 @@
- # along with this program.  If not, see <http://www.gnu.org/licenses/>.
- #
- 
-+import os
-+
- from ipapython.ipautil import run
- 
- # NOTE: Absolute path not required for keyctl since we reset the environment
-@@ -47,6 +49,21 @@ def get_real_key(key):
-         raise ValueError('key %s not found' % key)
-     return stdout.rstrip()
- 
-+def get_persistent_key(key):
-+    (stdout, stderr, rc) = run(['keyctl', 'get_persistent', KEYRING, key], raiseonerr=False)
-+    if rc:
-+        raise ValueError('persistent key %s not found' % key)
-+    return stdout.rstrip()
-+
-+def is_persistent_keyring_supported():
-+    uid = os.geteuid()
-+    try:
-+        get_persistent_key(str(uid))
-+    except ValueError:
-+        return False
-+
-+    return True
-+
- def has_key(key):
-     """
-     Returns True/False whether the key exists in the keyring.
-diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
-index 98687a4002cd7b19faea03acc552759e962d8832..f1fa827d89a31f9d6d4cb7f7a78a2680f983565a 100644
---- a/ipaserver/install/krbinstance.py
-+++ b/ipaserver/install/krbinstance.py
-@@ -31,6 +31,7 @@
- from ipapython import sysrestore
- from ipapython import ipautil
- from ipapython import services as ipaservices
-+from ipapython import kernel_keyring
- from ipalib import errors
- from ipapython.ipa_log_manager import *
- from ipapython.dn import DN
-@@ -252,6 +253,15 @@ def __setup_sub_dict(self):
-             dr_map = ""
-         self.sub_dict['OTHER_DOMAIN_REALM_MAPS'] = dr_map
- 
-+        # Configure KEYRING CCACHE if supported
-+        if kernel_keyring.is_persistent_keyring_supported():
-+            root_logger.debug("Enabling persistent keyring CCACHE")
-+            self.sub_dict['OTHER_LIBDEFAULTS'] = \
-+                " default_ccache_name = KEYRING:persistent:%{uid}\n"
-+        else:
-+            root_logger.debug("Persistent keyring CCACHE is not enabled")
-+            self.sub_dict['OTHER_LIBDEFAULTS'] = ''
-+
-     def __configure_sasl_mappings(self):
-         # we need to remove any existing SASL mappings in the directory as otherwise they
-         # they may conflict.
--- 
-1.8.3.1
-
diff --git a/SOURCES/0003-Fix-dns-zonemgr-validation-regression.patch b/SOURCES/0003-Fix-dns-zonemgr-validation-regression.patch
new file mode 100644
index 0000000..1698d87
--- /dev/null
+++ b/SOURCES/0003-Fix-dns-zonemgr-validation-regression.patch
@@ -0,0 +1,27 @@
+From 142a1ee40666a08006ac084eb182908d8def94af Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Fri, 24 Oct 2014 12:15:17 +0200
+Subject: [PATCH] Fix dns zonemgr validation regression
+
+https://fedorahosted.org/freeipa/ticket/4663
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipalib/util.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ipalib/util.py b/ipalib/util.py
+index fcb2bab96bcf5669de444846d8dea572eefce793..7a283106d70ba6a3e25cc7129d57b44b80876882 100644
+--- a/ipalib/util.py
++++ b/ipalib/util.py
+@@ -277,6 +277,7 @@ def validate_zonemgr(zonemgr):
+ 
+ def validate_zonemgr_str(zonemgr):
+     zonemgr = normalize_zonemgr(zonemgr)
++    zonemgr = DNSName(zonemgr)
+     return validate_zonemgr(zonemgr)
+ 
+ def validate_hostname(hostname, check_fqdn=True, allow_underscore=False, allow_slash=False):
+-- 
+2.1.0
+
diff --git a/SOURCES/0004-Fix-regression-which-prevents-creating-a-winsync-agr.patch b/SOURCES/0004-Fix-regression-which-prevents-creating-a-winsync-agr.patch
deleted file mode 100644
index 5839449..0000000
--- a/SOURCES/0004-Fix-regression-which-prevents-creating-a-winsync-agr.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 2f3c2538595664796d673517eb1c91edf5712d80 Mon Sep 17 00:00:00 2001
-From: Ana Krivokapic <akrivoka@redhat.com>
-Date: Tue, 12 Nov 2013 14:50:57 +0100
-Subject: [PATCH] Fix regression which prevents creating a winsync agreement
-
-A regression, which prevented creation of a winsync agreement,
-was introduced in the original fix for ticket #3989.
-
-https://fedorahosted.org/freeipa/ticket/3989
----
- ipaserver/install/replication.py | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
-index 4d8a4687e162155d7855e11ba5048bed2ff13fa5..c4e62fc91b4fb33c37b9f18ce167149ccd3bd54f 100644
---- a/ipaserver/install/replication.py
-+++ b/ipaserver/install/replication.py
-@@ -626,8 +626,9 @@ def setup_agreement(self, a_conn, b_hostname, port=389,
- 
-         if iswinsync:
-             self.setup_winsync_agmt(entry, win_subtree)
-+        else:
-+            entry['nsds5ReplicaStripAttrs'] = [" ".join(STRIP_ATTRS)]
- 
--        entry['nsds5ReplicaStripAttrs'] = [" ".join(STRIP_ATTRS)]
-         a_conn.add_entry(entry)
- 
-         try:
--- 
-1.8.3.1
-
diff --git a/SOURCES/0004-Handle-profile-changes-in-dogtag-ipa-ca-renew-agent.patch b/SOURCES/0004-Handle-profile-changes-in-dogtag-ipa-ca-renew-agent.patch
new file mode 100644
index 0000000..6def83a
--- /dev/null
+++ b/SOURCES/0004-Handle-profile-changes-in-dogtag-ipa-ca-renew-agent.patch
@@ -0,0 +1,181 @@
+From b82f0b1bc483fe265f3e2d2089b65185cafffd74 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 14 Oct 2014 10:30:07 +0200
+Subject: [PATCH] Handle profile changes in dogtag-ipa-ca-renew-agent
+
+To update the CA certificate in the Dogtag NSS database, the
+"ipa-cacert-manage renew" and "ipa-certupdate" commands temporarily change
+the profile of the CA certificate certmonger request, resubmit it and
+change the profile back to the original one.
+
+When something goes wrong while resubmitting the request, it needs to be
+modified and resubmitted again manually. This might fail with invalid
+cookie error, because changing the profile does not change the internal
+state of the request.
+
+Detect this in dogtag-ipa-ca-renew-agent and reset the internal state when
+profile is changed.
+
+https://fedorahosted.org/freeipa/ticket/4627
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ .../certmonger/dogtag-ipa-ca-renew-agent-submit    | 87 ++++++++++++++++++++--
+ 1 file changed, 80 insertions(+), 7 deletions(-)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index 4f0b78accac6840471f8b2e9f17288b3b4e82105..ca4380c331cc417c0a89eca17e987920118337d7 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -31,6 +31,7 @@ import tempfile
+ import shutil
+ import base64
+ import contextlib
++import json
+ 
+ from ipapython import ipautil
+ from ipapython.dn import DN
+@@ -64,6 +65,78 @@ def ldap_connect():
+         if conn is not None and conn.isconnected():
+             conn.disconnect()
+ 
++def call_handler(_handler, *args, **kwargs):
++    """
++    Request handler call wrapper
++
++    Before calling the handler, get the original profile name and cookie from
++    the provided cookie, if there is one. If the profile name does not match
++    the requested profile name, drop the cookie and restart the request.
++
++    After calling the handler, put the requested profile name and cookie
++    returned by the handler in a new cookie and return it.
++    """
++    operation = os.environ['CERTMONGER_OPERATION']
++    if operation == 'POLL':
++        cookie = os.environ.pop('CERTMONGER_CA_COOKIE', None)
++        if cookie is not None:
++            try:
++                context = json.loads(cookie)
++                if not isinstance(context, dict):
++                    raise TypeError
++            except (TypeError, ValueError):
++                return (UNCONFIGURED, "Invalid cookie: %r" % cookie)
++        else:
++            return (UNCONFIGURED, "Cookie not provided")
++
++        if 'profile' in context:
++            profile = context.pop('profile')
++            try:
++                if profile is not None:
++                    if not isinstance(profile, unicode):
++                        raise TypeError
++                    profile = profile.encode('raw_unicode_escape')
++            except (TypeError, UnicodeEncodeError):
++                return (UNCONFIGURED,
++                        "Invalid 'profile' in cookie: %r" % profile)
++        else:
++            return (UNCONFIGURED, "No 'profile' in cookie")
++
++        # If profile has changed between SUBMIT and POLL, restart request
++        if os.environ.get('CERTMONGER_CA_PROFILE') != profile:
++            os.environ['CERTMONGER_OPERATION'] = 'SUBMIT'
++            context = {}
++
++        if 'cookie' in context:
++            cookie = context.pop('cookie')
++            try:
++                if not isinstance(cookie, unicode):
++                    raise TypeError
++                cookie = cookie.encode('raw_unicode_escape')
++            except (TypeError, UnicodeEncodeError):
++                return (UNCONFIGURED,
++                        "Invalid 'cookie' in cookie: %r" % cookie)
++            os.environ['CERTMONGER_CA_COOKIE'] = cookie
++    else:
++        context = {}
++
++    result = _handler(*args, **kwargs)
++
++    if result[0] in (WAIT, WAIT_WITH_DELAY):
++        context['cookie'] = result[-1].decode('raw_unicode_escape')
++
++    profile = os.environ.get('CERTMONGER_CA_PROFILE')
++    if profile is not None:
++        profile = profile.decode('raw_unicode_escape')
++    context['profile'] = profile
++
++    cookie = json.dumps(context)
++    os.environ['CERTMONGER_CA_COOKIE'] = cookie
++    if result[0] in (WAIT, WAIT_WITH_DELAY):
++        result = result[:-1] + (cookie,)
++
++    return result
++
+ def request_cert():
+     """
+     Request certificate from IPA CA.
+@@ -144,7 +217,7 @@ def store_cert():
+             syslog.syslog(
+                 syslog.LOG_ERR,
+                 "Updating renewal certificate failed: %s. Sleeping 30s" % e)
+-            return (WAIT_WITH_DELAY, 30, attempts)
++            return (WAIT_WITH_DELAY, 30, str(attempts))
+         else:
+             syslog.syslog(
+                 syslog.LOG_ERR,
+@@ -179,7 +252,7 @@ def request_and_store_cert():
+         else:
+             os.environ['CERTMONGER_CA_COOKIE'] = cookie
+ 
+-        result = request_cert()
++        result = call_handler(request_cert)
+         if result[0] == WAIT:
+             return (result[0], 'request:%s' % result[1])
+         elif result[0] == WAIT_WITH_DELAY:
+@@ -198,7 +271,7 @@ def request_and_store_cert():
+         os.environ['CERTMONGER_CA_COOKIE'] = cookie
+     os.environ['CERTMONGER_CERTIFICATE'] = cert
+ 
+-    result = store_cert()
++    result = call_handler(store_cert)
+     if result[0] == WAIT:
+         return (result[0], 'store:%s:%s' % (cert, result[1]))
+     elif result[0] == WAIT_WITH_DELAY:
+@@ -258,7 +331,7 @@ def retrieve_cert():
+                     syslog.LOG_INFO,
+                     "Updated certificate for %s not available" % nickname)
+                 # No cert available yet, tell certmonger to wait another 8 hours
+-                return (WAIT_WITH_DELAY, 8 * 60 * 60, attempts)
++                return (WAIT_WITH_DELAY, 8 * 60 * 60, str(attempts))
+ 
+         cert = base64.b64encode(cert)
+         cert = x509.make_pem(cert)
+@@ -323,14 +396,14 @@ def renew_ca_cert():
+         return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
+ 
+     if state == 'retrieve':
+-        result = retrieve_cert()
++        result = call_handler(retrieve_cert)
+         if result[0] == WAIT_WITH_DELAY and not is_self_signed:
+             syslog.syslog(syslog.LOG_ALERT,
+                           "IPA CA certificate is about to expire, "
+                           "use ipa-cacert-manage to renew it")
+     elif state == 'request':
+         os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
+-        result = request_and_store_cert()
++        result = call_handler(request_and_store_cert)
+ 
+     if result[0] == WAIT:
+         return (result[0], '%s:%s' % (state, result[1]))
+@@ -369,7 +442,7 @@ def main():
+             else:
+                 handler = retrieve_cert
+ 
+-        res = handler()
++        res = call_handler(handler)
+         for item in res[1:]:
+             print item
+         return res[0]
+-- 
+2.1.0
+
diff --git a/SOURCES/0005-Do-not-wait-for-new-CA-certificate-to-appear-in-LDAP.patch b/SOURCES/0005-Do-not-wait-for-new-CA-certificate-to-appear-in-LDAP.patch
new file mode 100644
index 0000000..07ade9e
--- /dev/null
+++ b/SOURCES/0005-Do-not-wait-for-new-CA-certificate-to-appear-in-LDAP.patch
@@ -0,0 +1,170 @@
+From 5fa2b9d411c7c35266fa1c9726d91243ba2b02d6 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 14 Oct 2014 11:12:55 +0200
+Subject: [PATCH] Do not wait for new CA certificate to appear in LDAP in
+ ipa-certupdate
+
+If new certificate is not available, reuse the old one, instead of waiting
+indefinitely for the new certificate to appear.
+
+https://fedorahosted.org/freeipa/ticket/4628
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ .../certmonger/dogtag-ipa-ca-renew-agent-submit    | 87 ++++++++++++----------
+ ipa-client/ipaclient/ipa_certupdate.py             |  6 +-
+ 2 files changed, 53 insertions(+), 40 deletions(-)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index ca4380c331cc417c0a89eca17e987920118337d7..9a01eb3a08900a5c8d04953b41f4493f30c2b56f 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -279,25 +279,11 @@ def request_and_store_cert():
+     else:
+         return result
+ 
+-def retrieve_cert():
++def retrieve_or_reuse_cert():
+     """
+-    Retrieve new certificate from LDAP.
++    Retrieve certificate from LDAP. If the certificate is not available, reuse
++    the old certificate.
+     """
+-    operation = os.environ.get('CERTMONGER_OPERATION')
+-    if operation == 'SUBMIT':
+-        attempts = 0
+-    elif operation == 'POLL':
+-        cookie = os.environ.get('CERTMONGER_CA_COOKIE')
+-        if not cookie:
+-            return (UNCONFIGURED, "Cookie not provided")
+-
+-        try:
+-            attempts = int(cookie)
+-        except ValueError:
+-            return (UNCONFIGURED, "Invalid cookie: %r" % cookie)
+-    else:
+-        return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
+-
+     csr = os.environ.get('CERTMONGER_CSR')
+     if not csr:
+         return (UNCONFIGURED, "Certificate request not provided")
+@@ -306,12 +292,9 @@ def retrieve_cert():
+     if not nickname:
+         return (REJECTED, "No friendly name in the certificate request")
+ 
+-    old_cert = os.environ.get('CERTMONGER_CERTIFICATE')
+-    if not old_cert:
++    cert = os.environ.get('CERTMONGER_CERTIFICATE')
++    if not cert:
+         return (REJECTED, "New certificate requests not supported")
+-    old_cert = x509.normalize_certificate(old_cert)
+-
+-    syslog.syslog(syslog.LOG_NOTICE, "Updating certificate for %s" % nickname)
+ 
+     with ldap_connect() as conn:
+         try:
+@@ -320,23 +303,50 @@ def retrieve_cert():
+                    ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn),
+                 ['usercertificate'])
+         except errors.NotFound:
+-            cert = old_cert
++            pass
+         else:
+             cert = entry.single_value['usercertificate']
++            cert = base64.b64encode(cert)
++            cert = x509.make_pem(cert)
++
++    return (ISSUED, cert)
++
++def retrieve_cert():
++    """
++    Retrieve new certificate from LDAP.
++    """
++    operation = os.environ.get('CERTMONGER_OPERATION')
++    if operation == 'SUBMIT':
++        attempts = 0
++    elif operation == 'POLL':
++        cookie = os.environ.get('CERTMONGER_CA_COOKIE')
++        if not cookie:
++            return (UNCONFIGURED, "Cookie not provided")
++
++        try:
++            attempts = int(cookie)
++        except ValueError:
++            return (UNCONFIGURED, "Invalid cookie: %r" % cookie)
++    else:
++        return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
+ 
+-        if cert == old_cert:
+-            attempts += 1
+-            if attempts < 4:
+-                syslog.syslog(
+-                    syslog.LOG_INFO,
+-                    "Updated certificate for %s not available" % nickname)
+-                # No cert available yet, tell certmonger to wait another 8 hours
+-                return (WAIT_WITH_DELAY, 8 * 60 * 60, str(attempts))
++    old_cert = os.environ.get('CERTMONGER_CERTIFICATE')
++    if old_cert:
++        old_cert = x509.normalize_certificate(old_cert)
+ 
+-        cert = base64.b64encode(cert)
+-        cert = x509.make_pem(cert)
++    result = call_handler(retrieve_or_reuse_cert)
++    if result[0] != ISSUED:
++        return result
+ 
+-    return (ISSUED, cert)
++    new_cert = x509.normalize_certificate(result[1])
++    if new_cert == old_cert:
++        attempts += 1
++        if attempts < 4:
++            syslog.syslog(syslog.LOG_INFO, "Updated certificate not available")
++            # No cert available yet, tell certmonger to wait another 8 hours
++            return (WAIT_WITH_DELAY, 8 * 60 * 60, str(attempts))
++
++    return result
+ 
+ def export_csr():
+     """
+@@ -414,10 +424,11 @@ def renew_ca_cert():
+ 
+ def main():
+     handlers = {
+-        'ipaStorage':       store_cert,
+-        'ipaRetrieval':     retrieve_cert,
+-        'ipaCSRExport':     export_csr,
+-        'ipaCACertRenewal': renew_ca_cert,
++        'ipaStorage':           store_cert,
++        'ipaRetrievalOrReuse':  retrieve_or_reuse_cert,
++        'ipaRetrieval':         retrieve_cert,
++        'ipaCSRExport':         export_csr,
++        'ipaCACertRenewal':     renew_ca_cert,
+     }
+ 
+     api.bootstrap(context='renew')
+diff --git a/ipa-client/ipaclient/ipa_certupdate.py b/ipa-client/ipaclient/ipa_certupdate.py
+index 7ef11d058eeeb47dc47d46aa7cbe73578c42d131..031a34c3a54a02d43978eedcb794678a1550702b 100644
+--- a/ipa-client/ipaclient/ipa_certupdate.py
++++ b/ipa-client/ipaclient/ipa_certupdate.py
+@@ -143,14 +143,16 @@ class CertUpdate(admintool.AdminTool):
+             timeout = api.env.startup_timeout + 60
+ 
+             self.log.debug("resubmitting certmonger request '%s'", request_id)
+-            certmonger.resubmit_request(request_id, profile='ipaRetrieval')
++            certmonger.resubmit_request(
++                request_id, profile='ipaRetrievalOrReuse')
+             try:
+                 state = certmonger.wait_for_request(request_id, timeout)
+             except RuntimeError:
+                 raise admintool.ScriptError(
+                     "Resubmitting certmonger request '%s' timed out, "
+                     "please check the request manually" % request_id)
+-            if state != 'MONITORING':
++            ca_error = certmonger.get_request_value(request_id, 'ca-error')
++            if state != 'MONITORING' or ca_error:
+                 raise admintool.ScriptError(
+                     "Error resubmitting certmonger request '%s', "
+                     "please check the request manually" % request_id)
+-- 
+2.1.0
+
diff --git a/SOURCES/0005-trusts-Do-not-pass-base-id-to-the-subdomain-ranges.patch b/SOURCES/0005-trusts-Do-not-pass-base-id-to-the-subdomain-ranges.patch
deleted file mode 100644
index 29e4c01..0000000
--- a/SOURCES/0005-trusts-Do-not-pass-base-id-to-the-subdomain-ranges.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From bcf89f59d86f4031f3b2ea39dc1dff9484d81e67 Mon Sep 17 00:00:00 2001
-From: Tomas Babej <tbabej@redhat.com>
-Date: Thu, 21 Nov 2013 14:44:42 +0100
-Subject: [PATCH 5/6] trusts: Do not pass base-id to the subdomain ranges
-
-For trusted domains base id is calculated using a murmur3 hash of the
-domain Security Identifier (SID). During trust-add we create ranges for
-forest root domain and other forest domains. Since --base-id explicitly
-overrides generated base id for forest root domain, its value should not
-be passed to other forest domains' ranges -- their base ids must be
-calculated based on their SIDs.
-
-In case base id change for non-root forest domains is required, it can
-be done manually through idrange-mod command after the trust is
-established.
-
-https://fedorahosted.org/freeipa/ticket/4041
----
- ipalib/plugins/trust.py | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 32a93834394273c9f896ff5fd17bfcc753fe7b8e..5ba0905030c700c7f63003eef25891c52330934b 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -375,6 +375,11 @@ def execute(self, *keys, **options):
-                     passed_options = options
-                     passed_options.update(range_type=created_range_type)
- 
-+                    # Do not pass the base id to the subdomains since it would
-+                    # clash with the root level domain
-+                    if 'base_id' in passed_options:
-+                        del passed_options['base_id']
-+
-                     # Try to add the range for each subdomain
-                     try:
-                         self.add_range(range_name, dom_sid, *keys,
--- 
-1.8.3.1
-
diff --git a/SOURCES/0006-Fail-if-certmonger-can-t-see-new-CA-certificate-in-L.patch b/SOURCES/0006-Fail-if-certmonger-can-t-see-new-CA-certificate-in-L.patch
new file mode 100644
index 0000000..cd83510
--- /dev/null
+++ b/SOURCES/0006-Fail-if-certmonger-can-t-see-new-CA-certificate-in-L.patch
@@ -0,0 +1,101 @@
+From ccaacaaf054e9d597159e14714ab41069173da10 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 14 Oct 2014 11:26:15 +0200
+Subject: [PATCH] Fail if certmonger can't see new CA certificate in LDAP in
+ ipa-cacert-manage
+
+This should not normally happen, but if it does, report an error instead of
+waiting idefinitely for the certificate to appear.
+
+https://fedorahosted.org/freeipa/ticket/4629
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ .../certmonger/dogtag-ipa-ca-renew-agent-submit    | 40 +++++++++-------------
+ ipaserver/install/ipa_cacert_manage.py             |  3 +-
+ 2 files changed, 19 insertions(+), 24 deletions(-)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index 9a01eb3a08900a5c8d04953b41f4493f30c2b56f..e5ad9639b03b95e6e265214067a985f6c3ca0b2a 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -311,25 +311,11 @@ def retrieve_or_reuse_cert():
+ 
+     return (ISSUED, cert)
+ 
+-def retrieve_cert():
++def retrieve_cert_continuous():
+     """
+-    Retrieve new certificate from LDAP.
++    Retrieve new certificate from LDAP. Repeat every eight hours until the
++    certificate is available.
+     """
+-    operation = os.environ.get('CERTMONGER_OPERATION')
+-    if operation == 'SUBMIT':
+-        attempts = 0
+-    elif operation == 'POLL':
+-        cookie = os.environ.get('CERTMONGER_CA_COOKIE')
+-        if not cookie:
+-            return (UNCONFIGURED, "Cookie not provided")
+-
+-        try:
+-            attempts = int(cookie)
+-        except ValueError:
+-            return (UNCONFIGURED, "Invalid cookie: %r" % cookie)
+-    else:
+-        return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
+-
+     old_cert = os.environ.get('CERTMONGER_CERTIFICATE')
+     if old_cert:
+         old_cert = x509.normalize_certificate(old_cert)
+@@ -340,11 +326,19 @@ def retrieve_cert():
+ 
+     new_cert = x509.normalize_certificate(result[1])
+     if new_cert == old_cert:
+-        attempts += 1
+-        if attempts < 4:
+-            syslog.syslog(syslog.LOG_INFO, "Updated certificate not available")
+-            # No cert available yet, tell certmonger to wait another 8 hours
+-            return (WAIT_WITH_DELAY, 8 * 60 * 60, str(attempts))
++        syslog.syslog(syslog.LOG_INFO, "Updated certificate not available")
++        # No cert available yet, tell certmonger to wait another 8 hours
++        return (WAIT_WITH_DELAY, 8 * 60 * 60, '')
++
++    return result
++
++def retrieve_cert():
++    """
++    Retrieve new certificate from LDAP.
++    """
++    result = call_handler(retrieve_cert_continuous)
++    if result[0] == WAIT_WITH_DELAY:
++        return (REJECTED, "Updated certificate not available")
+ 
+     return result
+ 
+@@ -451,7 +445,7 @@ def main():
+             if ca.is_renewal_master():
+                 handler = request_and_store_cert
+             else:
+-                handler = retrieve_cert
++                handler = retrieve_cert_continuous
+ 
+         res = call_handler(handler)
+         for item in res[1:]:
+diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
+index a521e3965321d3345075d7fc4a55fb9c6904a652..2a8d95fdbebecf543a05afd47275c32684cad970 100644
+--- a/ipaserver/install/ipa_cacert_manage.py
++++ b/ipaserver/install/ipa_cacert_manage.py
+@@ -297,7 +297,8 @@ class CACertManage(admintool.AdminTool):
+             raise admintool.ScriptError(
+                 "Resubmitting certmonger request '%s' timed out, "
+                 "please check the request manually" % self.request_id)
+-        if state != 'MONITORING':
++        ca_error = certmonger.get_request_value(self.request_id, 'ca-error')
++        if state != 'MONITORING' or ca_error:
+             raise admintool.ScriptError(
+                 "Error resubmitting certmonger request '%s', "
+                 "please check the request manually" % self.request_id)
+-- 
+2.1.0
+
diff --git a/SOURCES/0006-Map-NT_STATUS_INVALID_PARAMETER-to-most-likely-error.patch b/SOURCES/0006-Map-NT_STATUS_INVALID_PARAMETER-to-most-likely-error.patch
deleted file mode 100644
index 52c1290..0000000
--- a/SOURCES/0006-Map-NT_STATUS_INVALID_PARAMETER-to-most-likely-error.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From f3292de4abee43c35c25d7ecd8b3638173fb24b8 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 12 Nov 2013 11:36:22 +0200
-Subject: [PATCH 6/6] Map NT_STATUS_INVALID_PARAMETER to most likely error
- cause: clock skew
-
-When we get NT_STATUS_INVALID_PARAMETER in response to establish
-DCE RPC pipe with Kerberos, the most likely reason is clock skew.
-Suggest that it is so in the error message.
-
-https://fedorahosted.org/freeipa/ticket/4024
----
- ipaserver/dcerpc.py | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index 86bb42884067ec91477d8efb37a5e7729ad50315..0dde3473b12b857ff269a936ad9a07d098405c45 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -82,6 +82,9 @@ def is_sid_valid(sid):
-     -1073741614: access_denied_error,
-     -1073741603:
-         errors.ValidationError(name=_('AD domain controller'), error=_('unsupported functional level')),
-+    -1073741811: # NT_STATUS_INVALID_PARAMETER
-+        errors.RemoteRetrieveError(
-+            reason=_('AD domain controller complains about communication sequence. It may mean unsynchronized time on both sides, for example')),
- }
- 
- dcerpc_error_messages = {
--- 
-1.8.3.1
-
diff --git a/SOURCES/0007-Fix-possible-NULL-dereference-in-ipa-kdb.patch b/SOURCES/0007-Fix-possible-NULL-dereference-in-ipa-kdb.patch
new file mode 100644
index 0000000..01e8b44
--- /dev/null
+++ b/SOURCES/0007-Fix-possible-NULL-dereference-in-ipa-kdb.patch
@@ -0,0 +1,34 @@
+From 73aa4b8a8b7352679a9c1e5ef900824be7b8f37c Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:44:05 +0000
+Subject: [PATCH] Fix possible NULL dereference in ipa-kdb
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-kdb/ipa_kdb_mspac.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
+index 084b689d459f27e72d679d37e24650149973df61..c8f6c76fb5b3bc7d47ec8a1551579d53d226027e 100644
+--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
+@@ -1888,9 +1888,11 @@ void get_authz_data_types(krb5_context context, krb5_db_entry *entry,
+         }
+ 
+         ipactx = ipadb_get_context(context);
+-        gcfg = ipadb_get_global_config(ipactx);
+-        if (gcfg != NULL)
+-            tmp = gcfg->authz_data;
++        if (ipactx != NULL) {
++            gcfg = ipadb_get_global_config(ipactx);
++            if (gcfg != NULL)
++                tmp = gcfg->authz_data;
++        }
+         if (ipactx == NULL || tmp == NULL) {
+             krb5_klog_syslog(LOG_ERR, "No default authorization data types " \
+                                       "available, no authorization data will " \
+-- 
+2.1.0
+
diff --git a/SOURCES/0007-Remove-mod_ssl-port-workaround.patch b/SOURCES/0007-Remove-mod_ssl-port-workaround.patch
deleted file mode 100644
index 020ca87..0000000
--- a/SOURCES/0007-Remove-mod_ssl-port-workaround.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From 940afde411eb9ba52252ae80188f4fdbb87a9554 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Tue, 26 Nov 2013 08:53:34 +0000
-Subject: [PATCH 07/10] Remove mod_ssl port workaround.
-
-https://fedorahosted.org/freeipa/ticket/4021
----
- freeipa.spec.in                   |  8 ++++++--
- install/tools/ipa-upgradeconfig   |  2 +-
- ipaserver/install/httpinstance.py | 17 ++++++++---------
- 3 files changed, 15 insertions(+), 12 deletions(-)
-
-diff --git a/freeipa.spec.in b/freeipa.spec.in
-index a091164907735d659be61fe29221cbce6934c77d..69ec29d9ff58bf3a25e25b35d5f3ba1d43741124 100644
---- a/freeipa.spec.in
-+++ b/freeipa.spec.in
-@@ -114,14 +114,14 @@ Requires: krb5-server >= 1.10
- Requires: krb5-pkinit-openssl
- Requires: cyrus-sasl-gssapi%{?_isa}
- Requires: ntp
--Requires: httpd
-+Requires: httpd >= 2.4.6-6
- Requires: mod_wsgi
- %if 0%{?fedora} >= 18
- Requires: mod_auth_kerb >= 5.4-16
- %else
- Requires: mod_auth_kerb >= 5.4-8
- %endif
--Requires: mod_nss >= 1.0.8-24
-+Requires: mod_nss >= 1.0.8-26
- Requires: python-ldap
- Requires: python-krbV
- Requires: acl
-@@ -832,6 +832,10 @@ fi
- %endif # ONLY_CLIENT
- 
- %changelog
-+* Tue Nov 26 2013 Jan Cholasta <jcholast@redhat.com> - 3.3.2-2
-+- Set minimum version of httpd to 2.4.6-6
-+- Set minimum version of mod_nss to 1.0.8-26
-+
- * Fri Oct 25 2013 Martin Kosek <mkosek@redhat.com> - 3.3.2-1
- - Remove mod_ssl conflict, it can now live with mod_nss installed
- 
-diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
-index 41c51263d5fc8b3a0e2f28bab89fc9d2d184fdca..10526f226798c78ae75972b82a2f72b200a8aacf 100644
---- a/install/tools/ipa-upgradeconfig
-+++ b/install/tools/ipa-upgradeconfig
-@@ -1047,7 +1047,7 @@ def main():
-     http.remove_httpd_ccache()
-     http.configure_selinux_for_httpd()
-     http.configure_httpd_ccache()
--    http.change_mod_nss_port_to_http()
-+    http.change_mod_nss_port_from_http()
- 
-     ds = dsinstance.DsInstance()
-     ds.configure_dirsrv_ccache()
-diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
-index 689e657e291b93d90038937a61f67915c0d582ec..e61a0c6d1526f29acb4647710e559a5bb32a58c0 100644
---- a/ipaserver/install/httpinstance.py
-+++ b/ipaserver/install/httpinstance.py
-@@ -253,25 +253,24 @@ def __configure_http(self):
-         http_fd.close()
-         os.chmod(target_fname, 0644)
- 
--    def change_mod_nss_port_to_http(self):
-+    def change_mod_nss_port_from_http(self):
-         # mod_ssl enforces SSLEngine on for vhost on 443 even though
-         # the listener is mod_nss. This then crashes the httpd as mod_nss
-         # listened port obviously does not match mod_ssl requirements.
-         #
--        # Change port to http to workaround the mod_ssl check, the SSL is
--        # enforced in the vhost later, so it is benign.
-+        # The workaround for this was to change port to http. It is no longer
-+        # necessary, as mod_nss now ships with default configuration which
-+        # sets SSLEngine off when mod_ssl is installed.
-         #
--        # Remove when https://bugzilla.redhat.com/show_bug.cgi?id=1023168
--        # is fixed.
--        if not sysupgrade.get_upgrade_state('nss.conf', 'listen_port_updated'):
--            installutils.set_directive(NSS_CONF, 'Listen', '443 http', quotes=False)
--            sysupgrade.set_upgrade_state('nss.conf', 'listen_port_updated', True)
-+        # Remove the workaround.
-+        if sysupgrade.get_upgrade_state('nss.conf', 'listen_port_updated'):
-+            installutils.set_directive(NSS_CONF, 'Listen', '443', quotes=False)
-+            sysupgrade.set_upgrade_state('nss.conf', 'listen_port_updated', False)
- 
-     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
--        self.change_mod_nss_port_to_http()
- 
-     def __set_mod_nss_nickname(self, nickname):
-         installutils.set_directive(NSS_CONF, 'NSSNickname', nickname)
--- 
-1.8.3.1
-
diff --git a/SOURCES/0008-Fix-memory-leaks-in-ipa-extdom-extop.patch b/SOURCES/0008-Fix-memory-leaks-in-ipa-extdom-extop.patch
new file mode 100644
index 0000000..39a260e
--- /dev/null
+++ b/SOURCES/0008-Fix-memory-leaks-in-ipa-extdom-extop.patch
@@ -0,0 +1,57 @@
+From 57ce6c99123854da69ce07fb8305d102b8e9d271 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:46:19 +0000
+Subject: [PATCH] Fix memory leaks in ipa-extdom-extop
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ .../ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c   | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
+index df04347e3d36b33ca0a4ea2391f60d97b75a97bf..20fdd62b20f28f5384cf83b8be5819f721c6c3db 100644
+--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
++++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
+@@ -340,7 +340,8 @@ static int pack_ber_user(enum response_types response_type,
+ 
+     ber = ber_alloc_t( LBER_USE_DER );
+     if (ber == NULL) {
+-        return LDAP_OPERATIONS_ERROR;
++        ret = LDAP_OPERATIONS_ERROR;
++        goto done;
+     }
+ 
+     ret = ber_printf(ber,"{e{ssii", response_type, domain_name, short_user_name,
+@@ -449,14 +450,15 @@ static int pack_ber_group(enum response_types response_type,
+ 
+     ber = ber_alloc_t( LBER_USE_DER );
+     if (ber == NULL) {
+-        return LDAP_OPERATIONS_ERROR;
++        ret = LDAP_OPERATIONS_ERROR;
++        goto done;
+     }
+ 
+     ret = ber_printf(ber,"{e{ssi", response_type, domain_name, short_group_name,
+                                    gid);
+     if (ret == -1) {
+-        ber_free(ber, 1);
+-        return LDAP_OPERATIONS_ERROR;
++        ret = LDAP_OPERATIONS_ERROR;
++        goto done;
+     }
+ 
+     if (response_type == RESP_GROUP_MEMBERS) {
+@@ -716,7 +718,7 @@ static int handle_sid_request(enum request_types request_type, const char *sid,
+ 
+     ret = get_buffer(&buf_len, &buf);
+     if (ret != LDAP_SUCCESS) {
+-        return ret;
++        goto done;
+     }
+ 
+     switch(id_type) {
+-- 
+2.1.0
+
diff --git a/SOURCES/0008-subdomains-Use-AD-admin-credentials-when-trust-is-be.patch b/SOURCES/0008-subdomains-Use-AD-admin-credentials-when-trust-is-be.patch
deleted file mode 100644
index f2f1a4e..0000000
--- a/SOURCES/0008-subdomains-Use-AD-admin-credentials-when-trust-is-be.patch
+++ /dev/null
@@ -1,147 +0,0 @@
-From 7c4828f3eb0e7b1f246f6263bdf22592d51824df Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 27 Nov 2013 12:17:43 +0200
-Subject: [PATCH 08/10] subdomains: Use AD admin credentials when trust is
- being established
-
-When AD administrator credentials passed, they stored in realm_passwd,
-not realm_password in the options.
-
-When passing credentials to ipaserver.dcerpc.fetch_domains(), make sure
-to normalize them.
-
-Additionally, force Samba auth module to use NTLMSSP in case we have
-credentials because at the point when trust is established, KDC is not
-yet ready to issue tickets to a service in the other realm due to
-MS-PAC information caching effects. The logic is a bit fuzzy because
-credentials code makes decisions on what to use based on the smb.conf
-parameters and Python bindings to set parameters to smb.conf make it so
-that auth module believes these parameters were overidden by the user
-through the command line and ignore some of options. We have to do calls
-in the right order to force NTLMSSP use instead of Kerberos.
-
-Fixes https://fedorahosted.org/freeipa/ticket/4046
----
- ipalib/plugins/trust.py | 13 ++++++++++---
- ipaserver/dcerpc.py     | 42 ++++++++++++++++++++++++++++--------------
- 2 files changed, 38 insertions(+), 17 deletions(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 5ba0905030c700c7f63003eef25891c52330934b..3b1b2fc67ce333751556a5c3a59a7f89efc608f9 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -1231,10 +1231,17 @@ def execute(self, *keys, **options):
- def fetch_domains_from_trust(self, trustinstance, trust_entry, **options):
-     trust_name = trust_entry['cn'][0]
-     creds = None
--    password = options.get('realm_password', None)
-+    password = options.get('realm_passwd', None)
-     if password:
--        creds = u"%s%%%s" % (options.get('realm_admin'), password)
--    domains = ipaserver.dcerpc.fetch_domains(self.api, trustinstance.local_flatname, trust_name, creds=creds)
-+        admin_name = options.get('realm_admin')
-+        sp = admin_name.split('\\')
-+        if len(sp) == 1:
-+            sp.insert(0, trustinstance.remote_domain.info['name'])
-+        creds = u"{name}%{password}".format(name="\\".join(sp),
-+                                            password=password)
-+    domains = ipaserver.dcerpc.fetch_domains(self.api,
-+                                             trustinstance.local_flatname,
-+                                             trust_name, creds=creds)
-     result = []
-     if not domains:
-         return None
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index 0dde3473b12b857ff269a936ad9a07d098405c45..d809c416baac072a2489fbd3c167f08665b7a24e 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -655,7 +655,7 @@ def __gen_lsa_connection(self, binding):
-        except RuntimeError, (num, message):
-            raise assess_dcerpc_exception(num=num, message=message)
- 
--    def __init_lsa_pipe(self, remote_host):
-+    def init_lsa_pipe(self, remote_host):
-         """
-         Try to initialize connection to the LSA pipe at remote host.
-         This method tries consequently all possible transport options
-@@ -692,7 +692,7 @@ def __gen_lsa_bindings(self, remote_host):
-         """
-         There are multiple transports to issue LSA calls. However, depending on a
-         system in use they may be blocked by local operating system policies.
--        Generate all we can use. __init_lsa_pipe() will try them one by one until
-+        Generate all we can use. init_lsa_pipe() will try them one by one until
-         there is one working.
- 
-         We try NCACN_NP before NCACN_IP_TCP and signed sessions before unsigned.
-@@ -753,7 +753,7 @@ def parse_naming_context(self, context):
-         return naming_ref.match(context).group(1)
- 
-     def retrieve(self, remote_host):
--        self.__init_lsa_pipe(remote_host)
-+        self.init_lsa_pipe(remote_host)
- 
-         objectAttribute = lsa.ObjectAttribute()
-         objectAttribute.sec_qos = lsa.QosInfo()
-@@ -964,34 +964,48 @@ def fetch_domains(api, mydomain, trustdomain, creds=None):
-                 NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL  = 0x00000040)
- 
-     def communicate(td):
--        td.creds.guess(td.parm)
--        netrc = net.Net(creds=td.creds, lp=td.parm)
--        try:
--            result = netrc.finddc(domain=trustdomain, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
--        except RuntimeError, e:
--            raise assess_dcerpc_exception(message=str(e))
--        if not result:
--            return None
--        td.retrieve(unicode(result.pdc_dns_name))
--
-+        td.init_lsa_pipe(td.info['dc'])
-         netr_pipe = netlogon.netlogon(td.binding, td.parm, td.creds)
-         domains = netr_pipe.netr_DsrEnumerateDomainTrusts(td.binding, 1)
-         return domains
- 
-     domains = None
-+    domain_validator = DomainValidator(api)
-+    configured = domain_validator.is_configured()
-+    if not configured:
-+        return None
-+
-     td = TrustDomainInstance('')
-     td.parm.set('workgroup', mydomain)
--    td.creds = credentials.Credentials()
-+    cr = credentials.Credentials()
-+    cr.set_kerberos_state(credentials.DONT_USE_KERBEROS)
-+    cr.guess(td.parm)
-+    cr.set_anonymous()
-+    cr.set_workstation(domain_validator.flatname)
-+    netrc = net.Net(creds=cr, lp=td.parm)
-+    try:
-+        result = netrc.finddc(domain=trustdomain,
-+                              flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
-+    except RuntimeError, e:
-+        raise assess_dcerpc_exception(message=str(e))
-+
-+    td.info['dc'] = unicode(result.pdc_dns_name)
-     if creds is None:
-         domval = DomainValidator(api)
-         (ccache_name, principal) = domval.kinit_as_http(trustdomain)
-+        td.creds = credentials.Credentials()
-         td.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS)
-         if ccache_name:
-             with installutils.private_ccache(path=ccache_name):
-+                td.creds.guess(td.parm)
-+                td.creds.set_workstation(domain_validator.flatname)
-                 domains = communicate(td)
-     else:
-+        td.creds = credentials.Credentials()
-         td.creds.set_kerberos_state(credentials.DONT_USE_KERBEROS)
-+        td.creds.guess(td.parm)
-         td.creds.parse_string(creds)
-+        td.creds.set_workstation(domain_validator.flatname)
-         domains = communicate(td)
- 
-     if domains is None:
--- 
-1.8.3.1
-
diff --git a/SOURCES/0009-Fix-various-bugs-in-ipa-opt-counter-and-ipa-otp-last.patch b/SOURCES/0009-Fix-various-bugs-in-ipa-opt-counter-and-ipa-otp-last.patch
new file mode 100644
index 0000000..a9dd4a4
--- /dev/null
+++ b/SOURCES/0009-Fix-various-bugs-in-ipa-opt-counter-and-ipa-otp-last.patch
@@ -0,0 +1,102 @@
+From f4574e1764e56a3a281bfc0e5aba886c46cadf95 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:50:26 +0000
+Subject: [PATCH] Fix various bugs in ipa-opt-counter and ipa-otp-lasttoken
+
+Fixes a wrong sizeof argument and unchecked return values.
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-slapi-plugins/ipa-otp-counter/berval.c         |  2 +-
+ .../ipa-slapi-plugins/ipa-otp-counter/ipa_otp_counter.c    | 14 +++++++++++---
+ .../ipa-otp-lasttoken/ipa_otp_lasttoken.c                  |  6 +++++-
+ 3 files changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-counter/berval.c b/daemons/ipa-slapi-plugins/ipa-otp-counter/berval.c
+index 884e1a21004c5440f3bbad9da57d43bba8649d5f..a2fe592f07746423b12d9a531d7860615b729afa 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-counter/berval.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-counter/berval.c
+@@ -48,7 +48,7 @@ berval_new_longlong(long long value)
+ {
+     struct berval *bv;
+ 
+-    bv = (struct berval*) slapi_ch_malloc(sizeof(struct berval*));
++    bv = (struct berval*) slapi_ch_malloc(sizeof(struct berval));
+     bv->bv_val = slapi_ch_smprintf("%lld", value);
+     bv->bv_len = strlen(bv->bv_val);
+ 
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-counter/ipa_otp_counter.c b/daemons/ipa-slapi-plugins/ipa-otp-counter/ipa_otp_counter.c
+index 24ef9e2401d62d7d63b55afb9aa3ba2f41642839..da047d7dc58e27b37ad29c39bde44e33602ab4c5 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-counter/ipa_otp_counter.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-counter/ipa_otp_counter.c
+@@ -50,6 +50,7 @@
+ 
+ #include "berval.h"
+ #include "ldapmod.h"
++#include "util.h"
+ 
+ #include <limits.h>
+ 
+@@ -140,6 +141,7 @@ normalize_input(LDAPMod ***mods, const char *attr, long long ctr)
+         case LDAP_MOD_REPLACE:
+         case LDAP_MOD_INCREMENT:
+             e++;
++            /* fall through */
+         default:
+             c++;
+         }
+@@ -284,8 +286,12 @@ preop_mod(Slapi_PBlock *pb)
+     cpre = get_counter(epre, attr);
+ 
+     if (repl == 0) {
+-        if (normalize_input(&mods, attr, cpre) != 0)
+-            slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
++        if (normalize_input(&mods, attr, cpre) != 0) {
++            if (slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods)) {
++                LOG_FATAL("slapi_pblock_set failed!\n");
++                goto error;
++            }
++        }
+     }
+ 
+     if (!simulate(mods, attr, cpre, &cpost) && repl == 0) {
+@@ -316,7 +322,9 @@ preop_mod(Slapi_PBlock *pb)
+ error:
+     rc = LDAP_UNWILLING_TO_PERFORM;
+     slapi_send_ldap_result(pb, rc, NULL, msg, 0, NULL);
+-    slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
++    if (slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc)) {
++        LOG_FATAL("slapi_pblock_set failed!\n");
++    }
+ 
+     slapi_ch_free_string(&msg);
+     return rc;
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+index 94d24ae0f0383c090e1207c6f4552ea29601f26e..d20fca1e705f7406362a3ba2def9ba102bd1622d 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+@@ -44,6 +44,8 @@
+ #include <libotp.h>
+ #include <time.h>
+ 
++#include "util.h"
++
+ #define PLUGIN_NAME               "ipa-otp-lasttoken"
+ #define LOG(sev, ...) \
+     slapi_log_error(SLAPI_LOG_ ## sev, PLUGIN_NAME, \
+@@ -100,7 +102,9 @@ static inline int
+ send_error(Slapi_PBlock *pb, int rc, char *errstr)
+ {
+     slapi_send_ldap_result(pb, rc, NULL, errstr, 0, NULL);
+-    slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
++    if (slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc)) {
++        LOG_FATAL("slapi_pblock_set failed!\n");
++    }
+     return rc;
+ }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0009-trusts-Always-stop-and-disable-smb-service-on-uninst.patch b/SOURCES/0009-trusts-Always-stop-and-disable-smb-service-on-uninst.patch
deleted file mode 100644
index d5a4486..0000000
--- a/SOURCES/0009-trusts-Always-stop-and-disable-smb-service-on-uninst.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From a7fffdc2685b82546c620c19fbbda545ba1b8e90 Mon Sep 17 00:00:00 2001
-From: Tomas Babej <tomasbabej@gmail.com>
-Date: Thu, 21 Nov 2013 15:25:27 +0100
-Subject: [PATCH 09/10] trusts: Always stop and disable smb service on
- uninstall
-
-https://fedorahosted.org/freeipa/ticket/4042
----
- ipaserver/install/adtrustinstance.py | 15 +++++++--------
- 1 file changed, 7 insertions(+), 8 deletions(-)
-
-diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
-index 6a1ede0d7eb46a824d6e9eaf7ad1226120d08809..4aa8322e3e2cfb6fbc07696097c3e6e21fc7f665 100644
---- a/ipaserver/install/adtrustinstance.py
-+++ b/ipaserver/install/adtrustinstance.py
-@@ -881,11 +881,16 @@ 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")
-+        # Call restore_state so that we do not leave mess in the statestore
-+        # Otherwise this does nothing
-+        self.restore_state("running")
-+        self.restore_state("enabled")
- 
-+        # Always try to stop and disable smb service, since we do not leave
-+        # working configuration after uninstall
-         try:
-             self.stop()
-+            self.disable()
-         except:
-             pass
- 
-@@ -917,9 +922,3 @@ def uninstall(self):
- 
-         # Remove our keys from samba's keytab
-         self.clean_samba_keytab()
--
--        if not enabled is None and not enabled:
--            self.disable()
--
--        if not running is None and running:
--            self.start()
--- 
-1.8.3.1
-
diff --git a/SOURCES/0010-Fix-memory-leak-in-ipa-pwd-extop.patch b/SOURCES/0010-Fix-memory-leak-in-ipa-pwd-extop.patch
new file mode 100644
index 0000000..a98caa9
--- /dev/null
+++ b/SOURCES/0010-Fix-memory-leak-in-ipa-pwd-extop.patch
@@ -0,0 +1,60 @@
+From 8ab479e0fdaa509775255005400b214736c3308c Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:53:41 +0000
+Subject: [PATCH] Fix memory leak in ipa-pwd-extop
+
+Also remove dead code and explicitly mark an ignored return value to prevent
+false positives in static code analysis.
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c | 3 +--
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c       | 2 +-
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+index ca021cac71da690a498fe3003fae1babb30456c1..f0346a343188930dfc90e19d2e5d38cb30741b90 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+@@ -1393,6 +1393,7 @@ done:
+     if (rc != LDAP_SUCCESS) {
+         free(password);
+         free(svcname);
++        free(enctypes);
+         *_err_msg = err_msg;
+     } else {
+         *_password = password;
+@@ -1639,7 +1640,6 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
+     krb5_context krbctx = NULL;
+     krb5_error_code krberr;
+     struct berval *extop_value = NULL;
+-    BerElement *ber = NULL;
+     char *service_name = NULL;
+     char *svcname;
+     Slapi_Entry *target_entry = NULL;
+@@ -1827,7 +1827,6 @@ free_and_return:
+         }
+         free(svals);
+     }
+-    if (ber) ber_free(ber, 1);
+     if (bvp) ber_bvfree(bvp);
+ 
+     return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+index 2bfcf10a271a497741f08bb519020cd159eb4aeb..cbb4536e7d119f4550e4b523eb02e34d058ae7a1 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+@@ -86,7 +86,7 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
+         }
+ 
+         /* Decode the optional token DN. */
+-        ber_scanf(ber, "a", &token_dn);
++        (void)ber_scanf(ber, "a", &token_dn);
+ 
+         /* Process the synchronization. */
+         success = false;
+-- 
+2.1.0
+
diff --git a/SOURCES/0010-Use-hardening-flags-for-ipa-optd.patch b/SOURCES/0010-Use-hardening-flags-for-ipa-optd.patch
deleted file mode 100644
index 68e1c3c..0000000
--- a/SOURCES/0010-Use-hardening-flags-for-ipa-optd.patch
+++ /dev/null
@@ -1,277 +0,0 @@
-From d55551c763d29ddd92156829fb2ae6b4f89b5184 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Wed, 27 Nov 2013 13:13:16 +0000
-Subject: [PATCH 10/11] Use hardening flags for ipa-optd.
-
-https://fedorahosted.org/freeipa/ticket/4010
-
-Martin Kosek: note that this patch contains both Jan's original work
-and squashed additional patches 206.2, 207.2, 208.2, 209.2, 212.2
-implemented to fix some of the problems introduced by the original
-patch.
----
- Makefile                                               | 3 +++
- daemons/ipa-otpd/Makefile.am                           | 4 ++--
- daemons/ipa-sam/Makefile.am                            | 1 -
- daemons/ipa-slapi-plugins/ipa-cldap/Makefile.am        | 1 -
- daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.c        | 4 +++-
- daemons/ipa-slapi-plugins/ipa-dns/Makefile.am          | 1 -
- daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am   | 1 -
- daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am | 1 -
- daemons/ipa-slapi-plugins/ipa-lockout/Makefile.am      | 1 -
- daemons/ipa-slapi-plugins/ipa-modrdn/Makefile.am       | 1 -
- daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am    | 3 +--
- daemons/ipa-slapi-plugins/ipa-range-check/Makefile.am  | 1 -
- daemons/ipa-slapi-plugins/ipa-sidgen/Makefile.am       | 1 -
- daemons/ipa-slapi-plugins/ipa-uuid/Makefile.am         | 1 -
- daemons/ipa-slapi-plugins/ipa-version/Makefile.am      | 1 -
- daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am      | 1 -
- freeipa.spec.in                                        | 8 ++++++--
- ipa-client/Makefile.am                                 | 1 -
- 18 files changed, 15 insertions(+), 20 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index a21cf7e33275fd1a783e89baf237c8dcd8db6508..9ed3bb59a0f1d52e1b40430bb9516d9438b0fcb4 100644
---- a/Makefile
-+++ b/Makefile
-@@ -52,6 +52,9 @@ endif
- 
- PYTHON ?= $(shell rpm -E %__python)
- 
-+CFLAGS := -g -O2 -Werror -Wall -Wextra -Wformat-security -Wno-unused-parameter -Wno-sign-compare -Wno-missing-field-initializers $(CFLAGS)
-+export CFLAGS
-+
- all: bootstrap-autogen server tests
- 	@for subdir in $(SUBDIRS); do \
- 		(cd $$subdir && $(MAKE) $@) || exit 1; \
-diff --git a/daemons/ipa-otpd/Makefile.am b/daemons/ipa-otpd/Makefile.am
-index ed99c3ecbdf6507d18243a665daa1418f978eea1..af82a5fe08856573d2d245608ba1dbaad171c7fe 100644
---- a/daemons/ipa-otpd/Makefile.am
-+++ b/daemons/ipa-otpd/Makefile.am
-@@ -1,5 +1,5 @@
--AM_CFLAGS := $(CFLAGS) @LDAP_CFLAGS@ @LIBVERTO_CFLAGS@
--AM_LDFLAGS := $(LDFLAGS) @LDAP_LIBS@ @LIBVERTO_LIBS@ @KRAD_LIBS@
-+AM_CFLAGS := @LDAP_CFLAGS@ @LIBVERTO_CFLAGS@
-+AM_LDFLAGS := @LDAP_LIBS@ @LIBVERTO_LIBS@ @KRAD_LIBS@
- 
- noinst_HEADERS = internal.h
- libexec_PROGRAMS = ipa-otpd
-diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
-index e8e22503a4d8e3821d6f455bac337feae8b34bfc..d55a187708eb5dda8ffc4c87abb2fcc854940ade 100644
---- a/daemons/ipa-sam/Makefile.am
-+++ b/daemons/ipa-sam/Makefile.am
-@@ -20,7 +20,6 @@ AM_CPPFLAGS =						\
- 	-DLDAPIDIR=\""$(localstatedir)/run"\"		\
- 	-DHAVE_LDAP					\
- 	-I $(KRB5_UTIL_DIR)				\
--	$(AM_CFLAGS)					\
- 	$(LDAP_CFLAGS)					\
- 	$(KRB5_CFLAGS)					\
- 	$(WARN_CFLAGS)					\
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/Makefile.am b/daemons/ipa-slapi-plugins/ipa-cldap/Makefile.am
-index f669d6b561482e165bedc1c1b2904b7f67a49a95..70b08835e5629026c80c21c83e0c749a387b73a4 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
- 	$(NDRNBT_CFLAGS)					\
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.c b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.c
-index 54d44ebf64b1efa0dda06773736d3413a6b70977..64ec80665de5f5b0c5c1a8605e05e34e7199a23d 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.c
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.c
-@@ -82,7 +82,9 @@ static int ipa_cldap_stop(Slapi_PBlock *pb)
-     }
- 
-     /* send stop signal to terminate worker thread */
--    write(ctx->stopfd[1], "", 1);
-+    do {
-+        ret = write(ctx->stopfd[1], "", 1);
-+    } while (ret == -1 && errno == EINTR);
-     close(ctx->stopfd[1]);
- 
-     ret = pthread_join(ctx->tid, &retval);
-diff --git a/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am b/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am
-index 6d09c8d9c73755e89d91fea83ac66f088d9be553..31b7485e39af30224d97e4a759dbc5779bd61373 100644
---- a/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am b/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
-index 7ba754a48269f5c4ad9d2f08bc8cd7a0f8e6243c..3ce37ac10ad7d1ee077caa55a2f128f688388561 100644
---- a/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
-@@ -11,7 +11,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(KRB5_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
-diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
-index df0c30562f09bf0e29464c9bb05f7befbd3997e1..7099a988878e2bc0cf840eab0b14fa9f40805a51 100644
---- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
-@@ -13,7 +13,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
- 	$(SSSIDMAP_CFLAGS)					\
-diff --git a/daemons/ipa-slapi-plugins/ipa-lockout/Makefile.am b/daemons/ipa-slapi-plugins/ipa-lockout/Makefile.am
-index 0c69f4d7fd79a08d98c3b967e5ed35e3668cccc2..6e4c31aa591c37d3b7fdd7110f66303af3005605 100644
---- a/daemons/ipa-slapi-plugins/ipa-lockout/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-lockout/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-modrdn/Makefile.am b/daemons/ipa-slapi-plugins/ipa-modrdn/Makefile.am
-index 9fbd03397cf36097e3c38280330cdeda1bf5950e..a3f8d4f7b0886fd7e03f425d27fb1ee98d868913 100644
---- a/daemons/ipa-slapi-plugins/ipa-modrdn/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-modrdn/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
-index b53b2e1e445ccc9e756aa1ecb2656f19980cd001..8bd89653de51ab33e295fc6b1f1d6d93576d3c64 100644
---- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
-@@ -18,13 +18,12 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(KRB5_CFLAGS)						\
- 	$(SSL_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
--	
-+
- AM_LDFLAGS = \
- 	$(KRB5_LIBS)	\
- 	$(SSL_LIBS)	\
-diff --git a/daemons/ipa-slapi-plugins/ipa-range-check/Makefile.am b/daemons/ipa-slapi-plugins/ipa-range-check/Makefile.am
-index f23a24ed8b2c8845e7bddbce86abe5a4a2fcd8cd..5aa9b5485211dc5ac699692d8c46cf59c53a9546 100644
---- a/daemons/ipa-slapi-plugins/ipa-range-check/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-range-check/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/Makefile.am b/daemons/ipa-slapi-plugins/ipa-sidgen/Makefile.am
-index 4bfb0185ec589797125df747cc02dcf8a7ef30cd..642fdd599b9a3e8204232199e1cc4a5ee8b013ba 100644
---- a/daemons/ipa-slapi-plugins/ipa-sidgen/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-sidgen/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-uuid/Makefile.am b/daemons/ipa-slapi-plugins/ipa-uuid/Makefile.am
-index 738290170da587b0bbee96d8abcda2762264ee0e..061d8483310b686db844059deb82b1465d498652 100644
---- a/daemons/ipa-slapi-plugins/ipa-uuid/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-uuid/Makefile.am
-@@ -12,7 +12,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/daemons/ipa-slapi-plugins/ipa-version/Makefile.am b/daemons/ipa-slapi-plugins/ipa-version/Makefile.am
-index 5396bda99c64e66428a15a17a520227f790bff00..afce915a0d76ff607c116e18ea98f959aed46d32 100644
---- a/daemons/ipa-slapi-plugins/ipa-version/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-version/Makefile.am
-@@ -13,7 +13,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(KRB5_CFLAGS)						\
- 	$(WARN_CFLAGS)						\
-diff --git a/daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am b/daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am
-index c41692864557e890d388e42c404c23e91ae8b1e9..3108f3c152c08d8b9883974a4c999f7bb89acc8e 100644
---- a/daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am
-+++ b/daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am
-@@ -11,7 +11,6 @@ AM_CPPFLAGS =							\
- 	-DLIBDIR=\""$(libdir)"\" 				\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(LDAP_CFLAGS)					\
- 	$(WARN_CFLAGS)						\
- 	$(NULL)
-diff --git a/freeipa.spec.in b/freeipa.spec.in
-index 69ec29d9ff58bf3a25e25b35d5f3ba1d43741124..ae8ee57f3ba2c0746bb0f7a1e65dab1da83cca22 100644
---- a/freeipa.spec.in
-+++ b/freeipa.spec.in
-@@ -5,6 +5,10 @@
- %global POLICYCOREUTILSVER 2.1.12-5
- %global gettext_domain ipa
- 
-+%if (0%{?fedora} > 15 || 0%{?rhel} >= 7)
-+%define _hardened_build 1
-+%endif
-+
- Name:           freeipa
- Version:        __VERSION__
- Release:        __RELEASE__%{?dist}
-@@ -316,8 +320,8 @@ This package contains tests that verify IPA functionality.
- %setup -n freeipa-%{version} -q
- 
- %build
--export CFLAGS="$CFLAGS %{optflags}"
--export CPPFLAGS="$CPPFLAGS %{optflags}"
-+export CFLAGS="%{optflags} $CFLAGS"
-+export LDFLAGS="%{__global_ldflags} $LDFLAGS"
- %if 0%{?fedora} >= 18
- # use fedora18 platform which is based on fedora16 platform with systemd
- # support + fedora18 changes
-diff --git a/ipa-client/Makefile.am b/ipa-client/Makefile.am
-index b7d70fd8d0d4383cac497b2978196e25893f9fe1..73076315d496d8f2be47ed18f726e5c9a6cb572f 100644
---- a/ipa-client/Makefile.am
-+++ b/ipa-client/Makefile.am
-@@ -25,7 +25,6 @@ AM_CPPFLAGS =							\
- 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
- 	-DDATADIR=\""$(datadir)"\"				\
- 	-DLOCALEDIR=\""$(localedir)"\"				\
--	$(AM_CFLAGS)						\
- 	$(KRB5_CFLAGS)						\
- 	$(OPENLDAP_CFLAGS)					\
- 	$(SASL_CFLAGS)						\
--- 
-1.8.3.1
-
diff --git a/SOURCES/0011-Fix-memory-leaks-in-ipa-join.patch b/SOURCES/0011-Fix-memory-leaks-in-ipa-join.patch
new file mode 100644
index 0000000..274c2d7
--- /dev/null
+++ b/SOURCES/0011-Fix-memory-leaks-in-ipa-join.patch
@@ -0,0 +1,107 @@
+From 211bc475034488f20bfe74fe158bb8b7720fd534 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:59:08 +0000
+Subject: [PATCH] Fix memory leaks in ipa-join
+
+Also remove dead code in ipa-join and add initializer to a variable in
+ipa-getkeytab to prevent false positives in static code analysis.
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipa-client/ipa-getkeytab.c |  2 +-
+ ipa-client/ipa-join.c      | 18 ++++++++----------
+ 2 files changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
+index 7861e4e508ce956a92d80d2e91294215854a2a32..bb43c333dca6560807a120103a1cb535fa87b76a 100644
+--- a/ipa-client/ipa-getkeytab.c
++++ b/ipa-client/ipa-getkeytab.c
+@@ -794,7 +794,7 @@ int main(int argc, const char *argv[])
+ 	char *password = NULL;
+ 	krb5_context krbctx;
+ 	krb5_ccache ccache;
+-	krb5_principal uprinc;
++	krb5_principal uprinc = NULL;
+ 	krb5_principal sprinc;
+ 	krb5_error_code krberr;
+ 	struct keys_container keys = { 0 };
+diff --git a/ipa-client/ipa-join.c b/ipa-client/ipa-join.c
+index df33d3b08cf69a37ae9de76266a071825a95871f..46f64572dcaeb3be61dadf87a07520ad21fb4f47 100644
+--- a/ipa-client/ipa-join.c
++++ b/ipa-client/ipa-join.c
+@@ -463,14 +463,12 @@ static int
+ join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bindpw, const char *basedn, const char **princ, const char **subject, int quiet)
+ {
+     LDAP *ld;
+-    char *filter = NULL;
+     int rval = 0;
+     char *oidresult = NULL;
+     struct berval valrequest;
+     struct berval *valresult = NULL;
+     int rc, ret;
+     char *ldap_base = NULL;
+-    char *search_base = NULL;
+ 
+     *binddn = NULL;
+     *princ = NULL;
+@@ -542,16 +540,12 @@ join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bin
+     *princ = strdup(valresult->bv_val);
+ 
+ ldap_done:
+-
+-    free(filter);
+-    free(search_base);
+-    free(ldap_base);
+-
+     if (ld != NULL) {
+         ldap_unbind_ext(ld, NULL, NULL);
+     }
+ 
+ done:
++    free(ldap_base);
+     if (valresult) ber_bvfree(valresult);
+     if (oidresult) free(oidresult);
+     return rval;
+@@ -815,7 +809,8 @@ unenroll_host(const char *server, const char *hostname, const char *ktname, int
+         if (!quiet)
+             fprintf(stderr, _("Error parsing \"%1$s\": %2$s.\n"),
+                             principal, error_message(krberr));
+-        return krberr;
++        rval = 4;
++        goto cleanup;
+     }
+     strcpy(tgs, KRB5_TGS_NAME);
+     snprintf(tgs + strlen(tgs), sizeof(tgs) - strlen(tgs), "/%.*s",
+@@ -833,7 +828,8 @@ unenroll_host(const char *server, const char *hostname, const char *ktname, int
+         if (!quiet)
+             fprintf(stderr, _("Error obtaining initial credentials: %s.\n"),
+                     error_message(krberr));
+-        return krberr;
++        rval = 19;
++        goto cleanup;
+     }
+ 
+     krberr = krb5_cc_resolve(krbctx, "MEMORY:ipa-join", &ccache);
+@@ -852,7 +848,8 @@ unenroll_host(const char *server, const char *hostname, const char *ktname, int
+             fprintf(stderr,
+                     _("Error storing creds in credential cache: %s.\n"),
+                     error_message(krberr));
+-        return krberr;
++        rval = 19;
++        goto cleanup;
+     }
+     krb5_cc_close(krbctx, ccache);
+     ccache = NULL;
+@@ -914,6 +911,7 @@ cleanup:
+ 
+     free(user_agent);
+     if (keytab) krb5_kt_close(krbctx, keytab);
++    free(host);
+     free((char *)principal);
+     free((char *)ipaserver);
+     if (princ) krb5_free_principal(krbctx, princ);
+-- 
+2.1.0
+
diff --git a/SOURCES/0011-test_integration-Support-external-names-for-hosts.patch b/SOURCES/0011-test_integration-Support-external-names-for-hosts.patch
deleted file mode 100644
index 202b024..0000000
--- a/SOURCES/0011-test_integration-Support-external-names-for-hosts.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 36c14bf16eba793f37585b697bd1cb2750d68e36 Mon Sep 17 00:00:00 2001
-From: Petr Viktorin <pviktori@redhat.com>
-Date: Thu, 24 Oct 2013 12:14:58 +0200
-Subject: [PATCH 11/11] test_integration: Support external names for hosts
-
-The framework had a concept of external hostnames,
-which the controller uses to contact the test machines,
-but they were not loaded from configuration.
-
-Load external names from configuration.
-
-This makes tests pass in setups where internal and external
-hostnames are different, and the internal hostnames are not
-initially resolvable from the controller.
-
-Martin Kosek:  this patch also contains squashed patch
-"test_integration: Log external hostname in Host.ldap_connect" from
-Petr Viktorin aiming for better debugability of the beaker tests.
----
- ipatests/test_integration/config.py | 14 ++++++++++----
- ipatests/test_integration/host.py   | 11 +++++++----
- 2 files changed, 17 insertions(+), 8 deletions(-)
-
-diff --git a/ipatests/test_integration/config.py b/ipatests/test_integration/config.py
-index 3aa4d05d6cb5758cd0d6be64a1ac582adcc971b4..b8c5fdc7f9ce1877e34491964418a8d806168e73 100644
---- a/ipatests/test_integration/config.py
-+++ b/ipatests/test_integration/config.py
-@@ -236,8 +236,10 @@ def env_normalize(env):
-     """Fill env variables from alternate variable names
- 
-     MASTER_env1 <- MASTER
--    REPLICA_env1 <- REPLICA
--    CLIENT_env1 <- CLIENT, SLAVE
-+    REPLICA_env1 <- REPLICA, SLAVE
-+    CLIENT_env1 <- CLIENT
-+    similarly for BEAKER* variants: BEAKERMASTER1_env1 <- BEAKERMASTER, etc.
-+
-     CLIENT_env1 gets extended with CLIENT2 or CLIENT2_env1
-     """
-     def coalesce(name, *other_names):
-@@ -253,8 +255,12 @@ def coalesce(name, *other_names):
-             else:
-                 env[name] = ''
-     coalesce('MASTER_env1', 'MASTER')
--    coalesce('REPLICA_env1', 'REPLICA')
--    coalesce('CLIENT_env1', 'CLIENT', 'SLAVE')
-+    coalesce('REPLICA_env1', 'REPLICA', 'SLAVE')
-+    coalesce('CLIENT_env1', 'CLIENT')
-+
-+    coalesce('BEAKERMASTER1_env1', 'BEAKERMASTER')
-+    coalesce('BEAKERREPLICA1_env1', 'BEAKERREPLICA', 'BEAKERSLAVE')
-+    coalesce('BEAKERCLIENT1_env1', 'BEAKERCLIENT')
- 
-     def extend(name, name2):
-         value = env.get(name2)
-diff --git a/ipatests/test_integration/host.py b/ipatests/test_integration/host.py
-index 02c82b372ce2805c0ca922319f5de1cd29b0ed82..507e19ed62b3d0a76e6e2ff6286fd83f17a68627 100644
---- a/ipatests/test_integration/host.py
-+++ b/ipatests/test_integration/host.py
-@@ -32,7 +32,8 @@ class BaseHost(object):
-     """Representation of a remote IPA host"""
-     transport_class = None
- 
--    def __init__(self, domain, hostname, role, index, ip=None):
-+    def __init__(self, domain, hostname, role, index, ip=None,
-+                 external_hostname=None):
-         self.domain = domain
-         self.role = role
-         self.index = index
-@@ -40,7 +41,7 @@ def __init__(self, domain, hostname, role, index, ip=None):
-         shortname, dot, ext_domain = hostname.partition('.')
-         self.shortname = shortname
-         self.hostname = shortname + '.' + self.domain.name
--        self.external_hostname = hostname
-+        self.external_hostname = external_hostname or hostname
- 
-         self.netbios = self.domain.name.split('.')[0].upper()
- 
-@@ -96,6 +97,8 @@ def remove_log_collector(self, collector):
-     def from_env(cls, env, domain, hostname, role, index):
-         ip = env.get('BEAKER%s%s_IP_env%s' %
-                         (role.upper(), index, domain.index), None)
-+        external_hostname = env.get(
-+            'BEAKER%s%s_env%s' % (role.upper(), index, domain.index), None)
- 
-         # We need to determine the type of the host, this depends on the domain
-         # type, as we assume all Unix machines are in the Unix domain and
-@@ -106,7 +109,7 @@ def from_env(cls, env, domain, hostname, role, index):
-         else:
-             cls = Host
- 
--        self = cls(domain, hostname, role, index, ip)
-+        self = cls(domain, hostname, role, index, ip, external_hostname)
-         return self
- 
-     @property
-@@ -157,7 +160,7 @@ def put_file_contents(self, filename, contents):
-     def ldap_connect(self):
-         """Return an LDAPClient authenticated to this host as directory manager
-         """
--        self.log.info('Connecting to LDAP')
-+        self.log.info('Connecting to LDAP at %s', self.external_hostname)
-         ldap = IPAdmin(self.external_hostname)
-         binddn = self.config.dirman_dn
-         self.log.info('LDAP bind as %s' % binddn)
--- 
-1.8.3.1
-
diff --git a/SOURCES/0012-Fix-various-bugs-in-ipap11helper.patch b/SOURCES/0012-Fix-various-bugs-in-ipap11helper.patch
new file mode 100644
index 0000000..5e570e3
--- /dev/null
+++ b/SOURCES/0012-Fix-various-bugs-in-ipap11helper.patch
@@ -0,0 +1,108 @@
+From 39b02dae37106eba8e3204048ca5dc3c9040c11f Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 5 Nov 2014 08:59:57 +0000
+Subject: [PATCH] Fix various bugs in ipap11helper
+
+Fixes a memory leak, a library handle leak and a double free.
+
+Also remove some redundant NULL checks before free to prevent false positives
+in static code analysis.
+
+https://fedorahosted.org/freeipa/ticket/4651
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipapython/ipap11helper/p11helper.c | 25 ++++++++++---------------
+ 1 file changed, 10 insertions(+), 15 deletions(-)
+
+diff --git a/ipapython/ipap11helper/p11helper.c b/ipapython/ipap11helper/p11helper.c
+index df5302a7f867a38596d8fbb3001a8796659fb706..038c26c4520cc8f71edbee15b0ccd9bf292d7588 100644
+--- a/ipapython/ipap11helper/p11helper.c
++++ b/ipapython/ipap11helper/p11helper.c
+@@ -334,8 +334,7 @@ int _find_key(P11_Helper* self, CK_ATTRIBUTE_PTR template,
+             if (tmp_objects_ptr == NULL) {
+                 *objects_count = 0;
+                 PyErr_SetString(ipap11helperError, "_find_key realloc failed");
+-                if (result_objects != NULL)
+-                    free(result_objects);
++                free(result_objects);
+                 return 0;
+             } else {
+                 result_objects = tmp_objects_ptr;
+@@ -346,16 +345,14 @@ int _find_key(P11_Helper* self, CK_ATTRIBUTE_PTR template,
+         rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+                 &objectCount);
+         if (!check_return_value(rv, "Check for duplicated key")) {
+-            if (result_objects != NULL)
+-                free(result_objects);
++            free(result_objects);
+             return 0;
+         }
+     }
+ 
+     rv = self->p11->C_FindObjectsFinal(self->session);
+     if (!check_return_value(rv, "Find objects final")) {
+-        if (result_objects != NULL)
+-            free(result_objects);
++        free(result_objects);
+         return 0;
+     }
+ 
+@@ -499,6 +496,8 @@ static int P11_Helper_init(P11_Helper *self, PyObject *args, PyObject *kwds) {
+     CK_C_GetFunctionList pGetFunctionList = loadLibrary(library_path,
+             &module_handle);
+     if (!pGetFunctionList) {
++        if (module_handle != NULL)
++            unloadLibrary(module_handle);
+         PyErr_SetString(ipap11helperError, "Could not load the library.");
+         return -1;
+     }
+@@ -933,9 +932,7 @@ P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) {
+     if (result_list == NULL) {
+         PyErr_SetString(ipap11helperError,
+                 "Unable to create list with results");
+-        if (objects != NULL) {
+-            free(objects);
+-        }
++        free(objects);
+         return NULL;
+     }
+     Py_INCREF(result_list);
+@@ -944,13 +941,12 @@ P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) {
+                 == -1) {
+             PyErr_SetString(ipap11helperError,
+                     "Unable to add to value to result list");
+-            if (objects != NULL) {
+-                free(objects);
+-            }
++            free(objects);
+             return NULL;
+         }
+     }
+ 
++    free(objects);
+     return result_list;
+ }
+ 
+@@ -1193,7 +1189,6 @@ P11_Helper_import_RSA_public_key(P11_Helper* self, CK_UTF8CHAR *label,
+     if (rsa == NULL) {
+         PyErr_SetString(ipap11helperError,
+                 "import_RSA_public_key: EVP_PKEY_get1_RSA error");
+-        free(pkey);
+         return NULL;
+     }
+ 
+@@ -1379,8 +1374,8 @@ P11_Helper_export_wrapped_key(P11_Helper* self, PyObject *args, PyObject *kwds)
+     wrapped_key = malloc(wrapped_key_len);
+     if (wrapped_key == NULL) {
+         rv = CKR_HOST_MEMORY;
+-        check_return_value(rv, "key wrapping: buffer allocation");
+-        return 0;
++        if (!check_return_value(rv, "key wrapping: buffer allocation"))
++            return 0;
+     }
+     rv = self->p11->C_WrapKey(self->session, &wrapping_mech,
+             object_wrapping_key, object_key, wrapped_key, &wrapped_key_len);
+-- 
+2.1.0
+
diff --git a/SOURCES/0012-ipa-client-install-Always-pass-hostname-to-the-ipa-j.patch b/SOURCES/0012-ipa-client-install-Always-pass-hostname-to-the-ipa-j.patch
deleted file mode 100644
index cf4e3e1..0000000
--- a/SOURCES/0012-ipa-client-install-Always-pass-hostname-to-the-ipa-j.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From ab33d06556e607b4477500f77d97f6ec7ee536c3 Mon Sep 17 00:00:00 2001
-From: Tomas Babej <tbabej@redhat.com>
-Date: Tue, 26 Nov 2013 12:15:33 +0100
-Subject: [PATCH] ipa-client-install: Always pass hostname to the ipa-join
-
-The ipa-client-install script and ipa-join use different methods
-of resolving the hostname, the former uses gethostbyaddr() call,
-while the latter reads the "uinfo.nodename".
-
-This can result ipa-client-install failures in case of broken PTR
-records.
-
-https://fedorahosted.org/freeipa/ticket/4027
----
- ipa-client/ipa-install/ipa-client-install | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
-index a898d388ee039752044008f8525424370098580a..5e966a3ae9fb9d5881d0fd4e8c2509f92e665d44 100755
---- a/ipa-client/ipa-install/ipa-client-install
-+++ b/ipa-client/ipa-install/ipa-client-install
-@@ -2119,13 +2119,13 @@ def install(options, env, fstore, statestore):
-             (ccache_fd, ccache_name) = tempfile.mkstemp()
-             os.close(ccache_fd)
-             env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name
--            join_args = ["/usr/sbin/ipa-join", "-s", cli_server[0], "-b", str(realm_to_suffix(cli_realm))]
-+            join_args = ["/usr/sbin/ipa-join",
-+                         "-s", cli_server[0],
-+                         "-b", str(realm_to_suffix(cli_realm)),
-+                         "-h", hostname]
-             if options.debug:
-                 join_args.append("-d")
-                 env['XMLRPC_TRACE_CURL'] = 'yes'
--            if options.hostname:
--                join_args.append("-h")
--                join_args.append(options.hostname)
-             if options.force_join:
-                 join_args.append("-f")
-             if options.principal is not None:
--- 
-1.8.3.1
-
diff --git a/SOURCES/0013-Deadlock-in-schema-compat-plugin-between-automember_.patch b/SOURCES/0013-Deadlock-in-schema-compat-plugin-between-automember_.patch
new file mode 100644
index 0000000..63ccb08
--- /dev/null
+++ b/SOURCES/0013-Deadlock-in-schema-compat-plugin-between-automember_.patch
@@ -0,0 +1,83 @@
+From f91b6dd2ac7ee2d3444929e0d8649c9f355bdcd2 Mon Sep 17 00:00:00 2001
+From: "Thierry bordaz (tbordaz)" <tbordaz@redhat.com>
+Date: Wed, 29 Oct 2014 16:23:03 +0100
+Subject: [PATCH] Deadlock in schema compat plugin (between
+ automember_update_membership task and dse update)
+
+	Defining schema-compat-ignore-subtree values for schema compat plugin config entries removes the
+	default value (ignore: cn=tasks,cn=config). This default value prevented deadlocks.
+	Schema plugin needs to scope the $SUFFIX and also any updates to its configuration.
+	This change restrict the schema compat to those subtrees. It replaces the definition of ignored subtrees
+	that would be too long for cn=config (tasks, mapping tree, replication, snmp..)
+
+https://fedorahosted.org/freeipa/ticket/4635
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ install/updates/10-schema_compat.update | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+diff --git a/install/updates/10-schema_compat.update b/install/updates/10-schema_compat.update
+index 7b75ba532612bbdaf9c85f8c88b0c8b8454e5969..b8c79012d121116f9cf53908fbe4eeeebe9d3d82 100644
+--- a/install/updates/10-schema_compat.update
++++ b/install/updates/10-schema_compat.update
+@@ -18,15 +18,19 @@ add: schema-compat-entry-attribute: 'sudoRunAsUser=%ifeq("ipaSudoRunAsUserCatego
+ add: schema-compat-entry-attribute: 'sudoRunAsUser=%ifeq("ipaSudoRunAsUserCategory","all","ALL","%deref_f(\"ipaSudoRunAs\",\"(objectclass=posixAccount)\",\"uid\")")'
+ add: schema-compat-entry-attribute: 'sudoRunAsGroup=%ifeq("ipaSudoRunAsGroupCategory","all","ALL","%{ipaSudoRunAsExtGroup}")'
+ add: schema-compat-entry-attribute: 'sudoRunAsGroup=%ifeq("ipaSudoRunAsGroupCategory","all","ALL","%deref_f(\"ipaSudoRunAsGroup\",\"(objectclass=posixGroup)\",\"cn\")")'
+-add: schema-compat-ignore-subtree: cn=changelog
+-add: schema-compat-ignore-subtree: o=ipaca
++remove: schema-compat-ignore-subtree: cn=changelog
++remove: schema-compat-ignore-subtree: o=ipaca
++add: schema-compat-restrict-subtree: '$SUFFIX'
++add: schema-compat-restrict-subtree: 'cn=Schema Compatibility,cn=plugins,cn=config'
+ 
+ # Change padding for host and userCategory so the pad returns the same value
+ # as the original, '' or -.
+ dn: cn=ng,cn=Schema Compatibility,cn=plugins,cn=config
+ replace: schema-compat-entry-attribute:'nisNetgroupTriple=(%link("%ifeq(\"hostCategory\",\"all\",\"\",\"%collect(\\\"%{externalHost}\\\",\\\"%deref(\\\\\\\"memberHost\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberHost\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\")\")","-",",","%ifeq(\"userCategory\",\"all\",\"\",\"%collect(\\\"%deref(\\\\\\\"memberUser\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberUser\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\")\")","-"),%{nisDomainName:-})::nisNetgroupTriple=(%link("%ifeq(\"hostCategory\",\"all\",\"\",\"%collect(\\\"%{externalHost}\\\",\\\"%deref(\\\\\\\"memberHost\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberHost\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"fqdn\\\\\\\")\\\")\")","%ifeq(\"hostCategory\",\"all\",\"\",\"-\")",",","%ifeq(\"userCategory\",\"all\",\"\",\"%collect(\\\"%deref(\\\\\\\"memberUser\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberUser\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\")\")","%ifeq(\"userCategory\",\"all\",\"\",\"-\")"),%{nisDomainName:-})'
+-add: schema-compat-ignore-subtree: cn=changelog
+-add: schema-compat-ignore-subtree: o=ipaca
++remove: schema-compat-ignore-subtree: cn=changelog
++remove: schema-compat-ignore-subtree: o=ipaca
++add: schema-compat-restrict-subtree: '$SUFFIX'
++add: schema-compat-restrict-subtree: 'cn=Schema Compatibility,cn=plugins,cn=config'
+ 
+ dn: cn=computers, cn=Schema Compatibility, cn=plugins, cn=config
+ default:objectClass: top
+@@ -41,19 +45,25 @@ default:schema-compat-entry-attribute: objectclass=device
+ default:schema-compat-entry-attribute: objectclass=ieee802Device
+ default:schema-compat-entry-attribute: cn=%{fqdn}
+ default:schema-compat-entry-attribute: macAddress=%{macAddress}
+-add: schema-compat-ignore-subtree: cn=changelog
+-add: schema-compat-ignore-subtree: o=ipaca
++remove: schema-compat-ignore-subtree: cn=changelog
++remove: schema-compat-ignore-subtree: o=ipaca
++add: schema-compat-restrict-subtree: '$SUFFIX'
++add: schema-compat-restrict-subtree: 'cn=Schema Compatibility,cn=plugins,cn=config'
+ 
+ dn: cn=sudoers,cn=Schema Compatibility,cn=plugins,cn=config
+ add:schema-compat-entry-attribute: sudoOrder=%{sudoOrder}
+ 
+ dn: cn=users,cn=Schema Compatibility,cn=plugins,cn=config
+-add: schema-compat-ignore-subtree: cn=changelog
+-add: schema-compat-ignore-subtree: o=ipaca
++remove: schema-compat-ignore-subtree: cn=changelog
++remove: schema-compat-ignore-subtree: o=ipaca
++add: schema-compat-restrict-subtree: '$SUFFIX'
++add: schema-compat-restrict-subtree: 'cn=Schema Compatibility,cn=plugins,cn=config'
+ 
+ dn: cn=groups,cn=Schema Compatibility,cn=plugins,cn=config
+-add: schema-compat-ignore-subtree: cn=changelog
+-add: schema-compat-ignore-subtree: o=ipaca
++remove: schema-compat-ignore-subtree: cn=changelog
++remove: schema-compat-ignore-subtree: o=ipaca
++add: schema-compat-restrict-subtree: '$SUFFIX'
++add: schema-compat-restrict-subtree: 'cn=Schema Compatibility,cn=plugins,cn=config'
+ 
+ dn: cn=Schema Compatibility,cn=plugins,cn=config
+ # We need to run schema-compat pre-bind callback before
+-- 
+2.1.0
+
diff --git a/SOURCES/0013-trust-fix-get_dn-to-distinguish-creating-and-re-addi.patch b/SOURCES/0013-trust-fix-get_dn-to-distinguish-creating-and-re-addi.patch
deleted file mode 100644
index 434f2b5..0000000
--- a/SOURCES/0013-trust-fix-get_dn-to-distinguish-creating-and-re-addi.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 51f46b7acd00b324e66e5fffd8646a48dc70aa2d Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Thu, 5 Dec 2013 13:47:37 +0200
-Subject: [PATCH 13/14] trust: fix get_dn() to distinguish creating and
- re-adding trusts
-
-Latest support for subdomains introduced regression that masked
-difference between newly added trust and re-added one.
-
-Additionally, in case no new subdomains were found, the code was
-returning None instead of an empty list which later could confuse
-trustdomain-find command.
-
-https://fedorahosted.org/freeipa/ticket/4067
----
- ipalib/plugins/trust.py | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 3b1b2fc67ce333751556a5c3a59a7f89efc608f9..76d609fd4de33edd96715deaaf7842c1de3ddaf4 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -262,7 +262,7 @@ def get_dn(self, *keys, **kwargs):
-                 result = ldap.get_entries(DN(self.container_dn, self.env.basedn),
-                                           ldap.SCOPE_SUBTREE, filter, [''])
-             except errors.NotFound:
--                trust_type = u'ad'
-+                return None
-             else:
-                 if len(result) > 1:
-                     raise errors.OnlyOneValueAllowed(attr='trust domain')
-@@ -1244,7 +1244,7 @@ def fetch_domains_from_trust(self, trustinstance, trust_entry, **options):
-                                              trust_name, creds=creds)
-     result = []
-     if not domains:
--        return None
-+        return result
- 
-     for dom in domains:
-         dom['trust_type'] = u'ad'
--- 
-1.8.4.2
-
diff --git a/SOURCES/0014-Stop-dirsrv-last-in-ipactl-stop.patch b/SOURCES/0014-Stop-dirsrv-last-in-ipactl-stop.patch
new file mode 100644
index 0000000..b6b9e1f
--- /dev/null
+++ b/SOURCES/0014-Stop-dirsrv-last-in-ipactl-stop.patch
@@ -0,0 +1,47 @@
+From 788b0ac5d9ae805f46321d50531ed5baf80eee1e Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Tue, 4 Nov 2014 03:22:59 -0500
+Subject: [PATCH] Stop dirsrv last in ipactl stop.
+
+Other services may depend on directory server.
+
+https://fedorahosted.org/freeipa/ticket/4632
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ install/tools/ipactl | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/install/tools/ipactl b/install/tools/ipactl
+index 7a1e41b01a80eeea85c417399dcf4666f70d4b26..b1b0b6e26fa97cdc953c86eee22e160782b57379 100755
+--- a/install/tools/ipactl
++++ b/install/tools/ipactl
+@@ -291,12 +291,6 @@ def ipa_stop(options):
+             finally:
+                 raise IpactlError()
+ 
+-    try:
+-        print "Stopping Directory Service"
+-        dirsrv.stop(capture_output=False)
+-    except:
+-        raise IpactlError("Failed to stop Directory Service")
+-
+     for svc in reversed(svc_list):
+         svchandle = services.service(svc)
+         try:
+@@ -305,6 +299,12 @@ def ipa_stop(options):
+         except:
+             emit_err("Failed to stop %s Service" % svc)
+ 
++    try:
++        print "Stopping Directory Service"
++        dirsrv.stop(capture_output=False)
++    except:
++        raise IpactlError("Failed to stop Directory Service")
++
+     # remove file with list of started services
+     try:
+         os.unlink(paths.SVC_LIST_FILE)
+-- 
+2.1.0
+
diff --git a/SOURCES/0014-ipa-cldap-Cut-NetBIOS-name-after-15-characters.patch b/SOURCES/0014-ipa-cldap-Cut-NetBIOS-name-after-15-characters.patch
deleted file mode 100644
index ad174dc..0000000
--- a/SOURCES/0014-ipa-cldap-Cut-NetBIOS-name-after-15-characters.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 03bfce26c944e2bf4d3073d959ed1e26d8f390a1 Mon Sep 17 00:00:00 2001
-From: Tomas Babej <tbabej@redhat.com>
-Date: Tue, 26 Nov 2013 12:14:39 +0100
-Subject: [PATCH 14/14] ipa-cldap: Cut NetBIOS name after 15 characters
-
-The CLDAP DS plugin uses the uppercased first segment of the fully
-qualified hostname as the NetBIOS name. We need to limit its size
-to 15 characters.
-
-https://fedorahosted.org/freeipa/ticket/4028
----
- daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h          | 1 +
- daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c | 6 +++++-
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-index 7b0c2aad1991f5f5958db62844f5777f71534794..3f420ff2c5acc7bd75bff7f042f76b9c61144461 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-@@ -59,6 +59,7 @@
- #define IPA_PLUGIN_NAME IPA_CLDAP_PLUGIN_NAME
- #define CLDAP_PORT 389
- #define MAX_DG_SIZE 4096
-+#define NETBIOS_NAME_MAX 15
- 
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 64
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-index 7d29fe559be55607fcb6b83fa521372e5197b848..9ba05829418a0d1de46f2c7776cc15c54a9eab1c 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-@@ -161,8 +161,12 @@ static int ipa_cldap_encode_netlogon(char *fq_hostname, char *domain,
-     nlr->dns_domain = domain;
-     nlr->pdc_dns_name = fq_hostname;
-     nlr->domain_name = name;
--    pdc_name = talloc_asprintf(nlr, "\\\\%s", fq_hostname);
-+
-+    /* copy the first 15 characters of the fully qualified hostname*/
-+    pdc_name = talloc_asprintf(nlr, "\\\\%.*s", NETBIOS_NAME_MAX, fq_hostname);
-+
-     for (p = pdc_name; *p; p++) {
-+        /* Create the NetBIOS name from the first segment of the hostname */
-         if (*p == '.') {
-             *p = '\0';
-             break;
--- 
-1.8.4.2
-
diff --git a/SOURCES/0015-Fix-upgrade-do-not-use-invalid-ldap-connection.patch b/SOURCES/0015-Fix-upgrade-do-not-use-invalid-ldap-connection.patch
new file mode 100644
index 0000000..334f889
--- /dev/null
+++ b/SOURCES/0015-Fix-upgrade-do-not-use-invalid-ldap-connection.patch
@@ -0,0 +1,43 @@
+From 925904b8724c50b6336c0cd17f5dbb2eb85be8a4 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Tue, 4 Nov 2014 15:59:50 +0100
+Subject: [PATCH] Fix upgrade: do not use invalid ldap connection
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4670
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/ldapupdate.py           | 6 ++++++
+ ipaserver/install/plugins/updateclient.py | 3 +++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
+index 6bed046d2661f48218b66c11e6f6a43c6dc0f6bf..47f0399b928b3b0da3954592d56750450454aac7 100644
+--- a/ipaserver/install/ldapupdate.py
++++ b/ipaserver/install/ldapupdate.py
+@@ -889,3 +889,9 @@ class LDAPUpdate:
+         self._run_updates(updates)
+ 
+         return self.modified
++
++    def close_connection(self):
++        """Close ldap connection"""
++        if self.conn:
++            self.conn.unbind()
++            self.conn = None
+diff --git a/ipaserver/install/plugins/updateclient.py b/ipaserver/install/plugins/updateclient.py
+index 7566b6cd807dafc3af5e7b51a1dfa68847ca91c2..8f5c5b5fdbc2b7bfec8be342ee267425c93b47cf 100644
+--- a/ipaserver/install/plugins/updateclient.py
++++ b/ipaserver/install/plugins/updateclient.py
+@@ -122,6 +122,9 @@ class updateclient(backend.Executioner):
+         for update in self.order(updatetype):
+             (restart, apply_now, res) = self.run(update.name, **kw)
+             if restart:
++                # connection has to be closed before restart, otherwise
++                # ld instance will try to reuse old non-valid connection
++                ld.close_connection()
+                 self.restart(dm_password, live_run)
+ 
+             if apply_now:
+-- 
+2.1.0
+
diff --git a/SOURCES/0015-Prevent-garbage-from-readline-on-standard-output-of-.patch b/SOURCES/0015-Prevent-garbage-from-readline-on-standard-output-of-.patch
deleted file mode 100644
index f35e96a..0000000
--- a/SOURCES/0015-Prevent-garbage-from-readline-on-standard-output-of-.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 57bf3ea34f2b727ffe1977de1010fdf0f62c354a Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Tue, 10 Dec 2013 16:32:08 +0100
-Subject: [PATCH] Prevent garbage from readline on standard output of
- dogtag-ipa-retrieve-agent.
-
-https://fedorahosted.org/freeipa/ticket/4064
----
- install/certmonger/dogtag-ipa-retrieve-agent-submit | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/install/certmonger/dogtag-ipa-retrieve-agent-submit b/install/certmonger/dogtag-ipa-retrieve-agent-submit
-index 3781fc5d01da12ce2dc01e17fc60143e82fbedc6..70cbd82d7d5cc392a2877e7478f459cc8b4a570f 100644
---- a/install/certmonger/dogtag-ipa-retrieve-agent-submit
-+++ b/install/certmonger/dogtag-ipa-retrieve-agent-submit
-@@ -23,6 +23,10 @@
- # retrieve the updated certificate from IPA.
- 
- import os
-+# Prevent garbage from readline on standard output
-+# (see https://fedorahosted.org/freeipa/ticket/4064)
-+if not os.isatty(1):
-+    os.environ['TERM'] = 'dumb'
- import sys
- import shutil
- import tempfile
--- 
-1.8.4.2
-
diff --git a/SOURCES/0016-Do-not-build-tests.patch b/SOURCES/0016-Do-not-build-tests.patch
deleted file mode 100644
index 3717767..0000000
--- a/SOURCES/0016-Do-not-build-tests.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 0c1c338accaf23b993781535c68bdaf93ba05430 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Mon, 6 Jan 2014 10:47:19 +0100
-Subject: [PATCH] Do not build tests
-
-Tests have been moved to other SRPM.
----
- Makefile | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 9ed3bb59a0f1d52e1b40430bb9516d9438b0fcb4..7a1e7fd9dcf916d2a238c44ec34bd33fe8989c03 100644
---- a/Makefile
-+++ b/Makefile
-@@ -55,7 +55,7 @@ PYTHON ?= $(shell rpm -E %__python)
- CFLAGS := -g -O2 -Werror -Wall -Wextra -Wformat-security -Wno-unused-parameter -Wno-sign-compare -Wno-missing-field-initializers $(CFLAGS)
- export CFLAGS
- 
--all: bootstrap-autogen server tests
-+all: bootstrap-autogen server
- 	@for subdir in $(SUBDIRS); do \
- 		(cd $$subdir && $(MAKE) $@) || exit 1; \
- 	done
-@@ -77,7 +77,7 @@ client-autogen: version-update
- tests-man-autogen: version-update
- 	cd ipatests/man; if [ ! -e Makefile ]; then ../../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
- 
--install: all server-install tests-install
-+install: all server-install
- 	@for subdir in $(SUBDIRS); do \
- 		(cd $$subdir && $(MAKE) $@) || exit 1; \
- 	done
--- 
-1.8.4.2
-
diff --git a/SOURCES/0016-Ensure-that-a-password-exists-after-OTP-validation.patch b/SOURCES/0016-Ensure-that-a-password-exists-after-OTP-validation.patch
new file mode 100644
index 0000000..f74ac1e
--- /dev/null
+++ b/SOURCES/0016-Ensure-that-a-password-exists-after-OTP-validation.patch
@@ -0,0 +1,73 @@
+From a4505caea4e4905e1756f31779c315de979f8f2c Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Wed, 5 Nov 2014 13:50:41 -0500
+Subject: [PATCH] Ensure that a password exists after OTP validation
+
+Before this patch users could log in using only the OTP value. This
+arose because ipapwd_authentication() successfully determined that
+an empty password was invalid, but 389 itself would see this as an
+anonymous bind. An anonymous bind would never even get this far in
+this code, so we simply deny requests with empty passwords.
+
+This patch resolves CVE-2014-7828.
+
+https://fedorahosted.org/freeipa/ticket/4690
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 26 ++++++++++++-----------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+index 60ceaaa7ab0cd282efb45f1a89de9dbd240a452c..1f595d01d986ca2950672d796d62f5f78b05c212 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+@@ -1446,12 +1446,12 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
+ 
+     /* Try to do OTP first. */
+     syncreq = sync_request_present(pb);
+-    if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials)) {
+-        slapi_entry_free(entry);
+-        slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
+-                               NULL, NULL, 0, NULL);
+-        return 1;
+-    }
++    if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials))
++        goto invalid_creds;
++
++    /* Ensure that there is a password. */
++    if (credentials->bv_len == 0)
++        goto invalid_creds;
+ 
+     /* Authenticate the user. */
+     ret = ipapwd_authenticate(dn, entry, credentials);
+@@ -1461,18 +1461,20 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
+     }
+ 
+     /* Attempt to handle a token synchronization request. */
+-    if (syncreq && !sync_request_handle(ipapwd_get_plugin_id(), pb, dn)) {
+-        slapi_entry_free(entry);
+-        slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
+-                               NULL, NULL, 0, NULL);
+-        return 1;
+-    }
++    if (syncreq && !sync_request_handle(ipapwd_get_plugin_id(), pb, dn))
++        goto invalid_creds;
+ 
+     /* Attempt to write out kerberos keys for the user. */
+     ipapwd_write_krb_keys(pb, dn, entry, credentials);
+ 
+     slapi_entry_free(entry);
+     return 0;
++
++invalid_creds:
++    slapi_entry_free(entry);
++    slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
++                           NULL, NULL, 0, NULL);
++    return 1;
+ }
+ 
+ /* Init pre ops */
+-- 
+2.1.0
+
diff --git a/SOURCES/0017-PKI-service-restart-after-CA-renewal-failed.patch b/SOURCES/0017-PKI-service-restart-after-CA-renewal-failed.patch
deleted file mode 100644
index 947e53a..0000000
--- a/SOURCES/0017-PKI-service-restart-after-CA-renewal-failed.patch
+++ /dev/null
@@ -1,198 +0,0 @@
-From 34c054ea9203ffa804bafb20afa236af867ce572 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Tue, 15 Oct 2013 17:47:12 +0000
-Subject: [PATCH] PKI service restart after CA renewal failed
-
-Fix both the service restart procedure and registration of old
-pki-cad well known service name.
-
-This patch was adapted from original patch of Jan Cholasta 178 to
-fix ticket 4092.
-
-https://fedorahosted.org/freeipa/ticket/4092
----
- install/restart_scripts/renew_ca_cert  | 16 +++++++++-------
- install/restart_scripts/restart_pkicad | 30 ++++++++++++++++++------------
- install/restart_scripts/stop_pkicad    | 16 ++++++++--------
- ipapython/dogtag.py                    |  4 ++++
- ipapython/platform/base/__init__.py    |  2 +-
- ipaserver/install/cainstance.py        |  4 ++--
- 6 files changed, 42 insertions(+), 30 deletions(-)
-
-diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert
-index ab394b970eaee28bc386d4d1ba737643414e2680..b10e4b842f3b9a54962402cddce8710eae4538b8 100644
---- a/install/restart_scripts/renew_ca_cert
-+++ b/install/restart_scripts/renew_ca_cert
-@@ -49,6 +49,7 @@ api.finalize()
- 
- configured_constants = dogtag.configured_constants(api)
- alias_dir = configured_constants.ALIAS_DIR
-+dogtag_service = ipaservices.knownservices[configured_constants.SERVICE_NAME]
- dogtag_instance = configured_constants.PKI_INSTANCE_NAME
- 
- # Fetch the new certificate
-@@ -106,12 +107,13 @@ if nickname == 'auditSigningCert cert-pki-ca':
- # off the servlet to verify that the CA is actually up and responding so
- # when this returns it should be good-to-go. The CA was stopped in the
- # pre-save state.
--syslog.syslog(syslog.LOG_NOTICE, 'Starting %sd' % dogtag_instance)
-+syslog.syslog(syslog.LOG_NOTICE, 'Starting %s' % dogtag_service.service_name)
- try:
--    if configured_constants.DOGTAG_VERSION == 9:
--        ipaservices.knownservices.pki_cad.start(dogtag_instance)
--    else:
--        ipaservices.knownservices.pki_tomcatd.start(dogtag_instance)
-+    dogtag_service.start(dogtag_instance)
- except Exception, e:
--    syslog.syslog(syslog.LOG_ERR, "Cannot start %sd: %s" %
--                  (dogtag_instance, str(e)))
-+    syslog.syslog(
-+        syslog.LOG_ERR,
-+        "Cannot start %s: %s" % (dogtag_service.service_name, e))
-+else:
-+    syslog.syslog(
-+        syslog.LOG_NOTICE, "Started %s" % dogtag_service.service_name)
-diff --git a/install/restart_scripts/restart_pkicad b/install/restart_scripts/restart_pkicad
-index a58c3f31e1bd288587842ba5fc4335c967b9405e..f840aeb1a228aee88b1c498700f733f1b90686f0 100644
---- a/install/restart_scripts/restart_pkicad
-+++ b/install/restart_scripts/restart_pkicad
-@@ -33,18 +33,25 @@ api.finalize()
- 
- configured_constants = dogtag.configured_constants(api)
- alias_dir = configured_constants.ALIAS_DIR
-+dogtag_service = ipaservices.knownservices[configured_constants.SERVICE_NAME]
- dogtag_instance = configured_constants.PKI_INSTANCE_NAME
- 
- # dogtag opens its NSS database in read/write mode so we need it
- # shut down so certmonger can open it read/write mode. This avoids
- # database corruption. It should already be stopped by the pre-command
- # but lets be sure.
--if ipaservices.knownservices.pki_cad.is_running(dogtag_instance):
-+if dogtag_service.is_running(dogtag_instance):
-+    syslog.syslog(
-+        syslog.LOG_NOTICE, "Stopping %s" % dogtag_service.service_name)
-     try:
--        ipaservices.knownservices.pki_cad.stop(dogtag_instance)
-+        dogtag_service.stop(dogtag_instance)
-     except Exception, e:
--        syslog.syslog(syslog.LOG_ERR, "Cannot stop %sd: %s" %
--                      (dogtag_instance, str(e)))
-+        syslog.syslog(
-+            syslog.LOG_ERR,
-+            "Cannot stop %s: %s" % (dogtag_service.service_name, e))
-+    else:
-+        syslog.syslog(
-+            syslog.LOG_NOTICE, "Stopped %s" % dogtag_service.service_name)
- 
- # Fix permissions on the audit cert if we're updating it
- if nickname == 'auditSigningCert cert-pki-ca':
-@@ -55,14 +62,13 @@ if nickname == 'auditSigningCert cert-pki-ca':
-            ]
-     db.run_certutil(args)
- 
-+syslog.syslog(syslog.LOG_NOTICE, 'Starting %s' % dogtag_service.service_name)
- try:
--    if configured_constants.DOGTAG_VERSION == 9:
--        ipaservices.knownservices.pki_cad.start(dogtag_instance)
--    else:
--        ipaservices.knownservices.pki_tomcatd.start(dogtag_instance)
-+    dogtag_service.start(dogtag_instance)
- except Exception, e:
--    syslog.syslog(syslog.LOG_ERR, "Cannot start %sd: %s" %
--                  (dogtag_instance, str(e)))
-+    syslog.syslog(
-+        syslog.LOG_ERR,
-+        "Cannot start %s: %s" % (dogtag_service.service_name, e))
- else:
--    syslog.syslog(syslog.LOG_NOTICE, "certmonger started %sd, nickname '%s'" %
--                  (dogtag_instance, nickname))
-+    syslog.syslog(
-+        syslog.LOG_NOTICE, "Started %s" % dogtag_service.service_name)
-diff --git a/install/restart_scripts/stop_pkicad b/install/restart_scripts/stop_pkicad
-index c8589b286eefbe1c3d79e2a6dab7adfd3ff56b2a..bbaf8895e3a86899ee5bd794eb595fd43316028b 100644
---- a/install/restart_scripts/stop_pkicad
-+++ b/install/restart_scripts/stop_pkicad
-@@ -29,15 +29,15 @@ api.bootstrap(context='restart')
- api.finalize()
- 
- configured_constants = dogtag.configured_constants(api)
-+dogtag_service = ipaservices.knownservices[configured_constants.SERVICE_NAME]
- dogtag_instance = configured_constants.PKI_INSTANCE_NAME
- 
--syslog.syslog(syslog.LOG_NOTICE, "certmonger stopping %sd" % dogtag_instance)
--
-+syslog.syslog(syslog.LOG_NOTICE, "Stopping %s" % dogtag_service.service_name)
- try:
--    if configured_constants.DOGTAG_VERSION == 9:
--        ipaservices.knownservices.pki_cad.stop(dogtag_instance)
--    else:
--        ipaservices.knownservices.pki_tomcatd.stop(dogtag_instance)
-+    dogtag_service.stop(dogtag_instance)
- except Exception, e:
--    syslog.syslog(syslog.LOG_ERR, "Cannot stop %sd: %s" %
--                  (dogtag_instance, str(e)))
-+    syslog.syslog(
-+        syslog.LOG_ERR, "Cannot stop %s: %s" % (dogtag_service.service_name, e))
-+else:
-+    syslog.syslog(
-+        syslog.LOG_NOTICE, "Stopped %s" % dogtag_service.service_name)
-diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py
-index ea769b0275c4642d5da457996165e5a348cb7299..f829b9340d1ce55b2adae4817018de11b894c92d 100644
---- a/ipapython/dogtag.py
-+++ b/ipapython/dogtag.py
-@@ -62,6 +62,8 @@ class Dogtag10Constants(object):
-     SERVICE_PROFILE_DIR = '%s/ca/profiles/ca' % PKI_ROOT
-     ALIAS_DIR = '/etc/pki/pki-tomcat/alias'
- 
-+    SERVICE_NAME = 'pki_tomcatd'
-+
-     RACERT_LINE_SEP = '\n'
- 
-     IPA_SERVICE_PROFILE = '%s/caIPAserviceCert.cfg' % SERVICE_PROFILE_DIR
-@@ -92,6 +94,8 @@ class Dogtag9Constants(object):
-     SERVICE_PROFILE_DIR = '%s/profiles/ca' % PKI_ROOT
-     ALIAS_DIR = '%s/alias' % PKI_ROOT
- 
-+    SERVICE_NAME = 'pki-cad'
-+
-     RACERT_LINE_SEP = '\r\n'
- 
-     ADMIN_SECURE_PORT = 9445
-diff --git a/ipapython/platform/base/__init__.py b/ipapython/platform/base/__init__.py
-index e2aa33faf9ccf182c778dfdbd8fd68d3686deae0..d76bc73a7d159c2dd43e281fa9916f245d88aaf3 100644
---- a/ipapython/platform/base/__init__.py
-+++ b/ipapython/platform/base/__init__.py
-@@ -27,7 +27,7 @@
- wellknownservices = ['certmonger', 'dirsrv', 'httpd', 'ipa', 'krb5kdc',
-                      'messagebus', 'nslcd', 'nscd', 'ntpd', 'portmap',
-                      'rpcbind', 'kadmin', 'sshd', 'autofs', 'rpcgssd',
--                     'rpcidmapd', 'pki_tomcatd', 'pki-cad', 'chronyd']
-+                     'rpcidmapd', 'pki_tomcatd', 'pki_cad', 'chronyd']
- 
- # System may support more time&date services. FreeIPA supports ntpd only, other
- # services will be disabled during IPA installation
-diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
-index ac5c81de8c57194160cbfd2fa79c776bf2f39625..52c91b68c2d073a9b1c6aedc1811aa26db046e6b 100644
---- a/ipaserver/install/cainstance.py
-+++ b/ipaserver/install/cainstance.py
-@@ -1283,7 +1283,7 @@ def enable_client_auth_to_db(self):
-         """
-         caconfig = dogtag.install_constants.CS_CFG_PATH
- 
--        with stopped_service('pki_tomcatd',
-+        with stopped_service(self.dogtag_constants.SERVICE_NAME,
-                         instance_name=self.dogtag_constants.PKI_INSTANCE_NAME):
- 
-             # Enable file publishing, disable LDAP
-@@ -1723,7 +1723,7 @@ def update_cert_config(nickname, cert, dogtag_constants=None):
-                   'subsystemCert cert-pki-ca': 'ca.subsystem.cert',
-                   'Server-Cert cert-pki-ca': 'ca.sslserver.cert'}
- 
--    with stopped_service('pki_tomcatd',
-+    with stopped_service(dogtag_constants.SERVICE_NAME,
-                          instance_name=dogtag_constants.PKI_INSTANCE_NAME):
- 
-         installutils.set_directive(dogtag.configured_constants().CS_CFG_PATH,
--- 
-1.8.4.2
-
diff --git a/SOURCES/0017-ipa-restore-Don-t-crash-if-AD-trust-is-not-installed.patch b/SOURCES/0017-ipa-restore-Don-t-crash-if-AD-trust-is-not-installed.patch
new file mode 100644
index 0000000..022c014
--- /dev/null
+++ b/SOURCES/0017-ipa-restore-Don-t-crash-if-AD-trust-is-not-installed.patch
@@ -0,0 +1,53 @@
+From d693ffd819a2016c6cc871107d5f66353c999888 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <pviktori@redhat.com>
+Date: Mon, 10 Nov 2014 13:29:58 +0100
+Subject: [PATCH] ipa-restore: Don't crash if AD trust is not installed
+
+https://fedorahosted.org/freeipa/ticket/4668
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 239de99c462639854e8e25c6b9278cb94b6fc6b8..352a1ca2bf283c0beb8c95925c6eb9c9984b3338 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -37,7 +37,6 @@ from ipaserver.install.replication import (wait_for_task, ReplicationManager,
+                                            get_cs_replication_manager)
+ from ipaserver.install import installutils
+ from ipaserver.install import httpinstance
+-from ipaserver.install import adtrustinstance
+ from ipapython import ipaldap
+ import ipapython.errors
+ from ipaplatform.tasks import tasks
+@@ -45,6 +44,11 @@ from ipaserver.install.ipa_backup import BACKUP_DIR
+ from ipaplatform import services
+ from ipaplatform.paths import paths
+ 
++try:
++    from ipaserver.install import adtrustinstance
++except ImportError:
++    adtrustinstance = None
++
+ 
+ def recursive_chown(path, uid, gid):
+     '''
+@@ -646,7 +650,12 @@ class Restore(admintool.AdminTool):
+     def restore_selinux_booleans(self):
+         bools = dict(httpinstance.SELINUX_BOOLEAN_SETTINGS)
+         if 'ADTRUST' in self.backup_services:
+-            bools.update(adtrustinstance.SELINUX_BOOLEAN_SETTINGS)
++            if adtrustinstance:
++                bools.update(adtrustinstance.SELINUX_BOOLEAN_SETTINGS)
++            else:
++                self.log.error(
++                    'The AD trust package was not found, '
++                    'not setting SELinux booleans.')
+         try:
+             tasks.set_selinux_booleans(bools)
+         except ipapython.errors.SetseboolError as e:
+-- 
+2.1.0
+
diff --git a/SOURCES/0018-hbactest-does-not-work-for-external-users.patch b/SOURCES/0018-hbactest-does-not-work-for-external-users.patch
deleted file mode 100644
index 4961b8b..0000000
--- a/SOURCES/0018-hbactest-does-not-work-for-external-users.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 01e98be318caa921302726b48f05166b0ce00f21 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Fri, 10 Jan 2014 12:41:29 +0100
-Subject: [PATCH] hbactest does not work for external users
-
-Original patch for ticket #3803 implemented support to resolve SIDs
-through SSSD. However, it also broke hbactest for external users. The
-result of the updated external member group search must be local
-non-external groups, not the external ones. Otherwise the rule is not
-matched.
-
-https://fedorahosted.org/freeipa/ticket/3803
----
- ipalib/plugins/hbactest.py | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/ipalib/plugins/hbactest.py b/ipalib/plugins/hbactest.py
-index fed39b05d8ac75254575cf211d338ab85b093cb8..cc18890ce3ca589a0d086aa263795f9c4ff61cb6 100644
---- a/ipalib/plugins/hbactest.py
-+++ b/ipalib/plugins/hbactest.py
-@@ -400,14 +400,16 @@ def execute(self, *args, **options):
-                 ldap = self.api.Backend.ldap2
-                 group_container = DN(api.env.container_group, api.env.basedn)
-                 try:
--                    entries, truncated = ldap.find_entries(filter_sids, ['cn'], group_container)
-+                    entries, truncated = ldap.find_entries(filter_sids, ['memberof'], group_container)
-                 except errors.NotFound:
-                     request.user.groups = []
-                 else:
-                     groups = []
-                     for dn, entry in entries:
--                        if dn.endswith(group_container):
--                            groups.append(dn[0][0].value)
-+                        memberof_dns = entry.get('memberof', [])
-+                        for memberof_dn in memberof_dns:
-+                            if memberof_dn.endswith(group_container):
-+                                groups.append(memberof_dn[0][0].value)
-                     request.user.groups = sorted(set(groups))
-             else:
-                 # try searching for a local user
--- 
-1.8.4.2
-
diff --git a/SOURCES/0018-ranges-prohibit-setting-rid-base-with-ipa-trust-ad-p.patch b/SOURCES/0018-ranges-prohibit-setting-rid-base-with-ipa-trust-ad-p.patch
new file mode 100644
index 0000000..c37297e
--- /dev/null
+++ b/SOURCES/0018-ranges-prohibit-setting-rid-base-with-ipa-trust-ad-p.patch
@@ -0,0 +1,159 @@
+From 77af6877a855c6dd738d03376464197ac3a938f8 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 13 Oct 2014 14:57:45 +0200
+Subject: [PATCH] ranges: prohibit setting --rid-base with ipa-trust-ad-posix
+ type
+
+We should not allow setting --rid-base for ranges of ipa-trust-ad-posix since we do not perform any RID -> UID/GID mappings for these ranges (objects have UID/GID set in AD). Thus, setting RID base makes no sense.
+
+Since ipaBaseRID is a MUST in ipaTrustedADDomainRange object class, value '0' is allowed and used internally for 'ipa-trust-ad-posix' range type.
+
+No schema change is done.
+
+https://fedorahosted.org/freeipa/ticket/4221
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ ipalib/plugins/idrange.py | 61 ++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 47 insertions(+), 14 deletions(-)
+
+diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
+index 9e0481e94048c465f9a86112378a47390de0d494..6c3be6e69595127e346969e41703dc98e783282e 100644
+--- a/ipalib/plugins/idrange.py
++++ b/ipalib/plugins/idrange.py
+@@ -248,6 +248,12 @@ class idrange(LDAPObject):
+             if not options.get('all', False) or options.get('pkey_only', False):
+                 entry_attrs.pop('objectclass', None)
+ 
++    def handle_ipabaserid(self, entry_attrs, options):
++        if any((options.get('pkey_only', False), options.get('raw', False))):
++            return
++        if entry_attrs['iparangetype'][0] == u'ipa-ad-trust-posix':
++            entry_attrs.pop('ipabaserid', None)
++
+     def check_ids_in_modified_range(self, old_base, old_size, new_base,
+                                     new_size):
+         if new_base is None and new_size is None:
+@@ -414,6 +420,7 @@ class idrange_add(LDAPCreate):
+ 
+         rid_base = kw.get('ipabaserid', None)
+         secondary_rid_base = kw.get('ipasecondarybaserid', None)
++        range_type = kw.get('iparangetype', None)
+ 
+         def set_from_prompt(param):
+             value = self.prompt_param(self.params[param])
+@@ -424,7 +431,7 @@ class idrange_add(LDAPCreate):
+             # This is a trusted range
+ 
+             # Prompt for RID base if domain SID / name was given
+-            if rid_base is None:
++            if rid_base is None and range_type != u'ipa-ad-trust-posix':
+                 set_from_prompt('ipabaserid')
+ 
+         else:
+@@ -486,23 +493,33 @@ class idrange_add(LDAPCreate):
+             if not is_set('iparangetype'):
+                 entry_attrs['iparangetype'] = u'ipa-ad-trust'
+ 
+-            if entry_attrs['iparangetype'] not in (u'ipa-ad-trust',
+-                                                   u'ipa-ad-trust-posix'):
++            if entry_attrs['iparangetype'] == u'ipa-ad-trust':
++                if not is_set('ipabaserid'):
++                    raise errors.ValidationError(
++                        name='ID Range setup',
++                        error=_('Options dom-sid/dom-name and rid-base must '
++                                'be used together')
++                    )
++            elif entry_attrs['iparangetype'] == u'ipa-ad-trust-posix':
++                if is_set('ipabaserid') and entry_attrs['ipabaserid'] != 0:
++                    raise errors.ValidationError(
++                        name='ID Range setup',
++                        error=_('Option rid-base must not be used when IPA '
++                                'range type is ipa-ad-trust-posix')
++                    )
++                else:
++                    entry_attrs['ipabaserid'] = 0
++            else:
+                 raise errors.ValidationError(name='ID Range setup',
+                     error=_('IPA Range type must be one of ipa-ad-trust '
+                             'or ipa-ad-trust-posix when SID of the trusted '
+-                            'domain is specified.'))
++                            'domain is specified'))
+ 
+             if is_set('ipasecondarybaserid'):
+                 raise errors.ValidationError(name='ID Range setup',
+                     error=_('Options dom-sid/dom-name and secondary-rid-base '
+                             'cannot be used together'))
+ 
+-            if not is_set('ipabaserid'):
+-                raise errors.ValidationError(name='ID Range setup',
+-                    error=_('Options dom-sid/dom-name and rid-base must '
+-                            'be used together'))
+-
+             # Validate SID as the one of trusted domains
+             self.obj.validate_trusted_domain_sid(
+                                         entry_attrs['ipanttrusteddomainsid'])
+@@ -557,6 +574,7 @@ class idrange_add(LDAPCreate):
+ 
+     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+         assert isinstance(dn, DN)
++        self.obj.handle_ipabaserid(entry_attrs, options)
+         self.obj.handle_iparangetype(entry_attrs, options,
+                                      keep_objectclass=True)
+         return dn
+@@ -628,6 +646,7 @@ class idrange_find(LDAPSearch):
+ 
+     def post_callback(self, ldap, entries, truncated, *args, **options):
+         for entry in entries:
++            self.obj.handle_ipabaserid(entry, options)
+             self.obj.handle_iparangetype(entry, options)
+         return truncated
+ 
+@@ -643,6 +662,7 @@ class idrange_show(LDAPRetrieve):
+ 
+     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+         assert isinstance(dn, DN)
++        self.obj.handle_ipabaserid(entry_attrs, options)
+         self.obj.handle_iparangetype(entry_attrs, options)
+         return dn
+ 
+@@ -699,11 +719,23 @@ class idrange_mod(LDAPUpdate):
+                 raise errors.ValidationError(name='ID Range setup',
+                     error=_('Options dom-sid and secondary-rid-base cannot '
+                             'be used together'))
+-
+-            if not in_updated_attrs('ipabaserid'):
+-                raise errors.ValidationError(name='ID Range setup',
+-                    error=_('Options dom-sid and rid-base must '
+-                            'be used together'))
++            range_type = old_attrs['iparangetype'][0]
++            if range_type == u'ipa-ad-trust':
++                if not in_updated_attrs('ipabaserid'):
++                    raise errors.ValidationError(
++                        name='ID Range setup',
++                        error=_('Options dom-sid and rid-base must '
++                                'be used together'))
++            elif (range_type == u'ipa-ad-trust-posix' and
++                  'ipabaserid' in entry_attrs):
++                if entry_attrs['ipabaserid'] is None:
++                    entry_attrs['ipabaserid'] = 0
++                elif entry_attrs['ipabaserid'] != 0:
++                    raise errors.ValidationError(
++                        name='ID Range setup',
++                        error=_('Option rid-base must not be used when IPA '
++                                'range type is ipa-ad-trust-posix')
++                    )
+ 
+             if is_set('ipanttrusteddomainsid'):
+                 # Validate SID as the one of trusted domains
+@@ -766,6 +798,7 @@ class idrange_mod(LDAPUpdate):
+ 
+     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+         assert isinstance(dn, DN)
++        self.obj.handle_ipabaserid(entry_attrs, options)
+         self.obj.handle_iparangetype(entry_attrs, options)
+         return dn
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0019-Change-the-way-we-determine-if-the-host-has-a-passwo.patch b/SOURCES/0019-Change-the-way-we-determine-if-the-host-has-a-passwo.patch
deleted file mode 100644
index 118ee8a..0000000
--- a/SOURCES/0019-Change-the-way-we-determine-if-the-host-has-a-passwo.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From b574423a54dbff7dbca89c6cee49f0304f2393e1 Mon Sep 17 00:00:00 2001
-From: Rob Crittenden <rcritten@redhat.com>
-Date: Tue, 14 Jan 2014 14:23:47 -0500
-Subject: [PATCH 19/25] Change the way we determine if the host has a password
- set.
-
-When creating a host with a password we don't set a Kerberos
-principal or add the Kerberos objectclasses. Those get added when the
-host is enrolled. If one passed in --password= (so no password) then
-we incorrectly thought the user was in fact setting a password, so the
-principal and objectclasses weren't updated.
-
-https://fedorahosted.org/freeipa/ticket/4102
----
- ipalib/plugins/host.py                   |  2 +-
- ipatests/test_xmlrpc/test_host_plugin.py | 27 +++++++++++++++++++++++++++
- 2 files changed, 28 insertions(+), 1 deletion(-)
-
-diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
-index 7aa94aa95ba9be17c308546d5d2fe247f27a07b3..9d45e270ff8221e4b9380684cb56112db4af4f52 100644
---- a/ipalib/plugins/host.py
-+++ b/ipalib/plugins/host.py
-@@ -425,7 +425,7 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
-             entry_attrs['l'] = entry_attrs['locality']
-         entry_attrs['cn'] = keys[-1]
-         entry_attrs['serverhostname'] = keys[-1].split('.', 1)[0]
--        if 'userpassword' not in entry_attrs and not options.get('random', False):
-+        if not entry_attrs.get('userpassword', False) and not options.get('random', False):
-             entry_attrs['krbprincipalname'] = 'host/%s@%s' % (
-                 keys[-1], self.api.env.realm
-             )
-diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
-index a23a34112f5c041a8325d5090580b535d93c7a72..7b64398fadd236b9b06723ef561cb19d61bca6d5 100644
---- a/ipatests/test_xmlrpc/test_host_plugin.py
-+++ b/ipatests/test_xmlrpc/test_host_plugin.py
-@@ -863,6 +863,33 @@ class test_host(Declarative):
-             ),
-         ),
- 
-+
-+        dict(
-+            desc='Create a host with a NULL password',
-+            command=('host_add', [fqdn3],
-+                dict(
-+                    description=u'Test host 3',
-+                    force=True,
-+                    userpassword=None,
-+                ),
-+            ),
-+            expected=dict(
-+                value=fqdn3,
-+                summary=u'Added host "%s"' % fqdn3,
-+                result=dict(
-+                    dn=dn3,
-+                    fqdn=[fqdn3],
-+                    description=[u'Test host 3'],
-+                    krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
-+                    objectclass=objectclasses.host,
-+                    ipauniqueid=[fuzzy_uuid],
-+                    managedby_host=[u'%s' % fqdn3],
-+                    has_keytab=False,
-+                    has_password=False,
-+                ),
-+            ),
-+        ),
-+
-     ]
- 
- class test_host_false_pwd_change(XMLRPC_test):
--- 
-1.8.4.2
-
diff --git a/SOURCES/0019-ldapupdater-set-baserid-to-0-for-ipa-ad-trust-posix-.patch b/SOURCES/0019-ldapupdater-set-baserid-to-0-for-ipa-ad-trust-posix-.patch
new file mode 100644
index 0000000..47342c5
--- /dev/null
+++ b/SOURCES/0019-ldapupdater-set-baserid-to-0-for-ipa-ad-trust-posix-.patch
@@ -0,0 +1,102 @@
+From aa5a5fa8349444c2817feb21dd8c6f8ba6b38fd0 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 13 Oct 2014 14:59:24 +0200
+Subject: [PATCH] ldapupdater: set baserid to 0 for ipa-ad-trust-posix ranges
+
+New updater plugin which sets baserid to 0 for ranges with type ipa-ad-trust-posix
+
+https://fedorahosted.org/freeipa/ticket/4221
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ ipaserver/install/plugins/update_idranges.py | 69 +++++++++++++++++++++++++++-
+ 1 file changed, 68 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/plugins/update_idranges.py b/ipaserver/install/plugins/update_idranges.py
+index 9e97c9f74570484a8bae82e99a7561350163a1b1..1aa5fa7631fd35a7aaf4a23a5eee44e4e0a2e904 100644
+--- a/ipaserver/install/plugins/update_idranges.py
++++ b/ipaserver/install/plugins/update_idranges.py
+@@ -17,7 +17,7 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-from ipaserver.install.plugins import MIDDLE
++from ipaserver.install.plugins import MIDDLE, LAST
+ from ipaserver.install.plugins.baseupdate import PostUpdate
+ from ipalib import api, errors
+ from ipapython.dn import DN
+@@ -111,4 +111,71 @@ class update_idrange_type(PostUpdate):
+ 
+         return (False, False, [])
+ 
++
++class update_idrange_baserid(PostUpdate):
++    """
++    Update ipa-ad-trust-posix ranges' base RID to 0. This applies to AD trust
++    posix ranges prior to IPA 4.1.
++    """
++
++    order = LAST
++
++    def execute(self, **options):
++        ldap = self.obj.backend
++
++        base_dn = DN(api.env.container_ranges, api.env.basedn)
++        search_filter = ("(&(objectClass=ipaTrustedADDomainRange)"
++                         "(ipaRangeType=ipa-ad-trust-posix)"
++                         "(!(ipaBaseRID=0)))")
++        root_logger.debug(
++            "update_idrange_baserid: search for ipa-ad-trust-posix ID ranges "
++            "with ipaBaseRID != 0"
++        )
++
++        try:
++            (entries, truncated) = ldap.find_entries(
++                search_filter, ['ipabaserid'], base_dn,
++                paged_search=True, time_limit=0, size_limit=0)
++
++        except errors.NotFound:
++            root_logger.debug("update_idrange_baserid: no AD domain "
++                              "range with posix attributes found")
++            return (False, False, [])
++
++        except errors.ExecutionError, e:
++            root_logger.error("update_idrange_baserid: cannot retrieve "
++                              "list of affected ranges: %s", e)
++            return (False, False, [])
++
++        root_logger.debug("update_idrange_baserid: found %d "
++                          "idranges possible to update",
++                          len(entries))
++
++        error = False
++
++        # Set the range type
++        for entry in entries:
++            entry['ipabaserid'] = 0
++            try:
++                root_logger.info("Updating existing idrange: %s" % (entry.dn))
++                ldap.update_entry(entry)
++                root_logger.info("Done")
++            except (errors.EmptyModlist, errors.NotFound):
++                pass
++            except errors.ExecutionError, e:
++                root_logger.debug("update_idrange_type: cannot "
++                                  "update idrange: %s", e)
++                error = True
++
++        if error:
++            root_logger.error("update_idrange_baserid: error(s) "
++                              "detected during idrange baserid update")
++        else:
++            # All affected entries updated, exit the loop
++            root_logger.debug("update_idrange_baserid: all affected "
++                              "idranges updated")
++
++        return (False, False, [])
++
+ api.register(update_idrange_type)
++api.register(update_idrange_baserid)
+-- 
+2.1.0
+
diff --git a/SOURCES/0020-idrange-include-raw-range-type-in-output.patch b/SOURCES/0020-idrange-include-raw-range-type-in-output.patch
new file mode 100644
index 0000000..03e655f
--- /dev/null
+++ b/SOURCES/0020-idrange-include-raw-range-type-in-output.patch
@@ -0,0 +1,29 @@
+From 83e12a6e7266ab1324f259eaed809f8db1118d7a Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Wed, 15 Oct 2014 13:42:30 +0200
+Subject: [PATCH] idrange: include raw range type in output
+
+iparangetype output is a localized human-readable value which is not suitable for machine-based API consumers
+
+Solved by new iparangetyperaw output attribute which contains iparangetype's raw value
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ ipalib/plugins/idrange.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
+index 6c3be6e69595127e346969e41703dc98e783282e..fb198d79d4c14ffd5f7dc633c9f01a1465ff01d7 100644
+--- a/ipalib/plugins/idrange.py
++++ b/ipalib/plugins/idrange.py
+@@ -241,6 +241,7 @@ class idrange(LDAPObject):
+         if not any((options.get('pkey_only', False),
+                     options.get('raw', False))):
+             range_type = entry_attrs['iparangetype'][0]
++            entry_attrs['iparangetyperaw'] = [range_type]
+             entry_attrs['iparangetype'] = [self.range_types.get(range_type, None)]
+ 
+         # Remove the objectclass
+-- 
+2.1.0
+
diff --git a/SOURCES/0020-sudoOrder-missing-in-sudoers.patch b/SOURCES/0020-sudoOrder-missing-in-sudoers.patch
deleted file mode 100644
index 6f81e52..0000000
--- a/SOURCES/0020-sudoOrder-missing-in-sudoers.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 4e5f306c4a544d449a763b46baea0ebfdb0d5785 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Wed, 15 Jan 2014 08:58:16 +0100
-Subject: [PATCH 20/25] sudoOrder missing in sudoers
-
-sudoers compat plugin configuration missed the sudoOrder attribute
-and it thus did not show up in ou=sudoers. Add the definion to update
-file.
-
-https://fedorahosted.org/freeipa/ticket/4107
----
- install/updates/10-schema_compat.update | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/install/updates/10-schema_compat.update b/install/updates/10-schema_compat.update
-index e65e67afc40f10eee342afc12e2132d36e9c2a1a..1199ef3861fb60e204cd0cd6272a829b495cdde7 100644
---- a/install/updates/10-schema_compat.update
-+++ b/install/updates/10-schema_compat.update
-@@ -21,3 +21,5 @@ dn: cn=computers, cn=Schema Compatibility, cn=plugins,
- default:schema-compat-entry-attribute: cn=%{fqdn}
- default:schema-compat-entry-attribute: macAddress=%{macAddress}
- 
-+dn: cn=sudoers,cn=Schema Compatibility,cn=plugins,cn=config
-+add:schema-compat-entry-attribute: sudoOrder=%{sudoOrder}
--- 
-1.8.4.2
-
diff --git a/SOURCES/0021-Add-missing-example-to-sudorule.patch b/SOURCES/0021-Add-missing-example-to-sudorule.patch
deleted file mode 100644
index 5bae186..0000000
--- a/SOURCES/0021-Add-missing-example-to-sudorule.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From f85b3ba942c0347c197cd738fab444fe9a697a62 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Wed, 15 Jan 2014 09:31:37 +0100
-Subject: [PATCH 21/25] Add missing example to sudorule
-
-https://fedorahosted.org/freeipa/ticket/4090
----
- ipalib/plugins/sudorule.py | 21 ++++++++++++++++++++-
- 1 file changed, 20 insertions(+), 1 deletion(-)
-
-diff --git a/ipalib/plugins/sudorule.py b/ipalib/plugins/sudorule.py
-index a89941cb6ab9b258de26bb7cf3632dc0acc7e20e..9644aafa263b4790c8123d177f0ccd10b572f0f0 100644
---- a/ipalib/plugins/sudorule.py
-+++ b/ipalib/plugins/sudorule.py
-@@ -52,7 +52,26 @@
- -h ipa.example.com -ZZ -D "cn=Directory Manager" \
- uid=sudo,cn=sysaccounts,cn=etc,dc=example,dc=com
- 
--For more information, see the FreeIPA Documentation to Sudo.
-+EXAMPLES:
-+
-+ Create a new rule:
-+   ipa sudorule-add readfiles
-+
-+ Add sudo command object and add it as allowed command in the rule:
-+   ipa sudocmd-add /usr/bin/less
-+   ipa sudorule-add-allow-command readfiles --sudocmds /usr/bin/less
-+
-+ Add a host to the rule:
-+   ipa sudorule-add-host readfiles --hosts server.example.com
-+
-+ Add a user to the rule:
-+   ipa sudorule-add-user readfiles --users jsmith
-+
-+ Add a special Sudo rule for default Sudo server configuration:
-+   ipa sudorule-add defaults
-+
-+ Set a default Sudo option:
-+   ipa sudorule-add-option defaults --sudooption '!authenticate'
- """)
- 
- topic = ('sudo', _('Commands for controlling sudo configuration'))
--- 
-1.8.4.2
-
diff --git a/SOURCES/0021-webui-prohibit-setting-rid-base-with-ipa-trust-ad-po.patch b/SOURCES/0021-webui-prohibit-setting-rid-base-with-ipa-trust-ad-po.patch
new file mode 100644
index 0000000..ebcb9ab
--- /dev/null
+++ b/SOURCES/0021-webui-prohibit-setting-rid-base-with-ipa-trust-ad-po.patch
@@ -0,0 +1,153 @@
+From da57475f30f086b2420652b1aeab9e2902fb8664 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Wed, 3 Sep 2014 17:23:33 +0200
+Subject: [PATCH] webui: prohibit setting rid base with ipa-trust-ad-posix type
+
+Base RID is no longer editable for ipa-trust-ad-posix range type
+
+Adder dialog:
+- Range type selector was moved up because it affects a field above it
+
+Details page:
+- Only fields relevant to range's type are visible
+
+https://fedorahosted.org/freeipa/ticket/4221
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/ui/src/freeipa/idrange.js | 77 ++++++++++++++++++++++++++++++---------
+ 1 file changed, 60 insertions(+), 17 deletions(-)
+
+diff --git a/install/ui/src/freeipa/idrange.js b/install/ui/src/freeipa/idrange.js
+index 12c0b288b766c059db6b844f445fb88b5821a1db..4e5dbfa00dcf80495d8a96f7fc961b9c6676691f 100644
+--- a/install/ui/src/freeipa/idrange.js
++++ b/install/ui/src/freeipa/idrange.js
+@@ -54,6 +54,11 @@ return {
+                         'cn',
+                         'iparangetype',
+                         {
++                            name: 'iparangetyperaw',
++                            read_only: true,
++                            visible: false
++                        },
++                        {
+                             name: 'ipabaseid',
+                             label: '@i18n:objects.idrange.ipabaseid',
+                             title: '@mo-param:idrange:ipabaseid:label'
+@@ -80,6 +85,9 @@ return {
+                         }
+                     ]
+                 }
++            ],
++            policies: [
++                exp.idrange_policy
+             ]
+         }
+     ],
+@@ -89,21 +97,6 @@ return {
+                 name: 'cn'
+             },
+             {
+-                name: 'ipabaseid',
+-                label: '@i18n:objects.idrange.ipabaseid',
+-                title: '@mo-param:idrange:ipabaseid:label'
+-            },
+-            {
+-                name: 'ipaidrangesize',
+-                label: '@i18n:objects.idrange.ipaidrangesize',
+-                title: '@mo-param:idrange:ipaidrangesize:label'
+-            },
+-            {
+-                name: 'ipabaserid',
+-                label: '@i18n:objects.idrange.ipabaserid',
+-                title: '@mo-param:idrange:ipabaserid:label'
+-            },
+-            {
+                 name: 'iparangetype',
+                 $type: 'radio',
+                 label: '@i18n:objects.idrange.type',
+@@ -125,6 +118,21 @@ return {
+                 ]
+             },
+             {
++                name: 'ipabaseid',
++                label: '@i18n:objects.idrange.ipabaseid',
++                title: '@mo-param:idrange:ipabaseid:label'
++            },
++            {
++                name: 'ipaidrangesize',
++                label: '@i18n:objects.idrange.ipaidrangesize',
++                title: '@mo-param:idrange:ipaidrangesize:label'
++            },
++            {
++                name: 'ipabaserid',
++                label: '@i18n:objects.idrange.ipabaserid',
++                title: '@mo-param:idrange:ipabaserid:label'
++            },
++            {
+                 name: 'ipasecondarybaserid',
+                 label: '@i18n:objects.idrange.ipasecondarybaserid',
+                 title: '@mo-param:idrange:ipasecondarybaserid:label'
+@@ -147,7 +155,9 @@ IPA.idrange_adder_policy = function(spec) {
+     The logic for enabling/requiring ipabaserid, ipasecondarybaserid and
+     ipanttrusteddomainsid is as follows:
+         1) for AD ranges (range type is ipa-ad-trust or ipa-ad-trust-posix):
+-           * ipabaserid and ipanttrusteddomainsid are requred
++           * ipanttrusteddomainsid is required
++           * ipabaserid is required for ipa-ad-trust but disabled for
++             ipa-ad-trust-posix
+            * ipasecondarybaserid is disabled
+         2) for local ranges
+            *  ipanttrusteddomainsid is disabled
+@@ -206,7 +216,11 @@ IPA.idrange_adder_policy = function(spec) {
+         var is_ad_range = (type_v === 'ipa-ad-trust' || type_v === 'ipa-ad-trust-posix');
+ 
+         if (is_ad_range) {
+-            require(baserid_f);
++            if (type_v === 'ipa-ad-trust') {
++                require(baserid_f);
++            } else {
++                disable(baserid_f);
++            }
+             require(trusteddomainsid_f);
+             disable(secondarybaserid_f);
+         } else {
+@@ -230,6 +244,35 @@ IPA.idrange_adder_policy = function(spec) {
+     return that;
+ };
+ 
++exp.idrange_policy = function(spec) {
++
++    spec = spec || {};
++    var that = IPA.facet_policy(spec);
++
++    that.post_load = function() {
++        var type_f = that.container.fields.get_field('iparangetyperaw');
++        var widgets = that.container.widgets;
++        var type_v = type_f.get_value()[0];
++
++        var baserid = true;
++        var secrid = true;
++        var sid = true;
++
++        if (type_v === 'ipa-local') {
++            sid = false;
++        } else if (type_v === 'ipa-ad-trust-posix') {
++            baserid = secrid = false;
++        } else if (type_v === 'ipa-ad-trust') {
++            secrid = false;
++        }
++
++        widgets.get_widget('details.ipabaserid').set_visible(baserid);
++        widgets.get_widget('details.ipasecondarybaserid').set_visible(secrid);
++        widgets.get_widget('details.ipanttrusteddomainsid').set_visible(sid);
++    };
++    return that;
++};
++
+ exp.entity_spec = make_spec();
+ exp.register = function() {
+     var e = reg.entity;
+-- 
+2.1.0
+
diff --git a/SOURCES/0022-Fix-CA-certificate-backup-and-restore.patch b/SOURCES/0022-Fix-CA-certificate-backup-and-restore.patch
new file mode 100644
index 0000000..c41a1f3
--- /dev/null
+++ b/SOURCES/0022-Fix-CA-certificate-backup-and-restore.patch
@@ -0,0 +1,208 @@
+From 9037c4d84bcf9cde48beb83d69f05c3733106c2d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 16:24:22 +0000
+Subject: [PATCH] Fix CA certificate backup and restore
+
+Backup and restore /etc/pki/ca-trust/source/ipa.p11-kit.
+
+Create /etc/ipa/nssdb after restore if necessary.
+
+https://fedorahosted.org/freeipa/ticket/4711
+
+Reviewed-By: Petr Viktorin <pviktori@redhat.com>
+---
+ ipaplatform/base/paths.py        |  2 +-
+ ipaplatform/base/tasks.py        |  9 +++++++++
+ ipaplatform/redhat/tasks.py      | 43 ++++++++++++++++++++--------------------
+ ipaserver/install/ipa_backup.py  |  2 ++
+ ipaserver/install/ipa_restore.py | 35 +++++++++++++++++++++++++++++++-
+ 5 files changed, 67 insertions(+), 24 deletions(-)
+
+diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
+index af502628e493ad7b4d8d30ed1acb98bba8cb39e4..e28147ab4aa1faa3859c38665a83f57fb67e96b2 100644
+--- a/ipaplatform/base/paths.py
++++ b/ipaplatform/base/paths.py
+@@ -92,7 +92,7 @@ class BasePathNamespace(object):
+     PAM_LDAP_CONF = "/etc/pam_ldap.conf"
+     PASSWD = "/etc/passwd"
+     ETC_PKI_CA_DIR = "/etc/pki-ca"
+-    SYSTEMWIDE_CA_STORE = "/etc/pki/ca-trust/source/anchors/"
++    SYSTEMWIDE_IPA_CA_CRT = "/etc/pki/ca-trust/source/anchors/ipa-ca.crt"
+     IPA_P11_KIT = "/etc/pki/ca-trust/source/ipa.p11-kit"
+     NSS_DB_DIR = "/etc/pki/nssdb"
+     PKI_TOMCAT = "/etc/pki/pki-tomcat"
+diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
+index 408447e43cd36d0cdf11a1877b3bc9880c4785de..a6684d7653d6de8202a489edb1f7a38f4b344bbc 100644
+--- a/ipaplatform/base/tasks.py
++++ b/ipaplatform/base/tasks.py
+@@ -49,6 +49,15 @@ class BaseTaskNamespace(object):
+ 
+         return
+ 
++    def reload_systemwide_ca_store(self):
++        """
++        Reloads the systemwide CA store.
++
++        Returns True if the operation succeeded, False otherwise.
++        """
++
++        return True
++
+     def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
+         """
+         Adds CA certificates from 'ca_certs' to the systemwide CA store
+diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
+index 555516d90a6d1a7d3d9aced5de82a5c1efe6b8c2..4977e1c7c496e36d56110bcdf040ab5c932d31a2 100644
+--- a/ipaplatform/redhat/tasks.py
++++ b/ipaplatform/redhat/tasks.py
+@@ -158,8 +158,19 @@ class RedHatTaskNamespace(BaseTaskNamespace):
+         auth_config.add_option("nostart")
+         auth_config.execute()
+ 
++    def reload_systemwide_ca_store(self):
++        try:
++            ipautil.run([paths.UPDATE_CA_TRUST])
++        except CalledProcessError, e:
++            root_logger.error(
++                "Could not update systemwide CA trust database: %s", e)
++            return False
++        else:
++            root_logger.info("Systemwide CA database updated.")
++            return True
++
+     def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
+-        new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE, 'ipa-ca.crt')
++        new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT
+ 
+         if os.path.exists(new_cacert_path):
+             try:
+@@ -248,24 +259,18 @@ class RedHatTaskNamespace(BaseTaskNamespace):
+         f.close()
+ 
+         # Add the CA to the systemwide CA trust database
+-        try:
+-            ipautil.run([paths.UPDATE_CA_TRUST])
+-        except CalledProcessError, e:
+-            root_logger.info("Failed to add CA to the systemwide "
+-                             "CA trust database: %s" % str(e))
+-        else:
+-            root_logger.info('Added the CA to the systemwide CA trust '
+-                             'database.')
+-            return True
++        if not self.reload_systemwide_ca_store():
++            return False
+ 
+-        return False
++        return True
+ 
+     def remove_ca_certs_from_systemwide_ca_store(self):
+-        ipa_ca_crt = os.path.join(paths.SYSTEMWIDE_CA_STORE, 'ipa-ca.crt')
++        result = True
+         update = False
+ 
+         # Remove CA cert from systemwide store
+-        for new_cacert_path in (paths.IPA_P11_KIT, ipa_ca_crt):
++        for new_cacert_path in (paths.IPA_P11_KIT,
++                                paths.SYSTEMWIDE_IPA_CA_CRT):
+             if not os.path.exists(new_cacert_path):
+                 continue
+             try:
+@@ -273,21 +278,15 @@ class RedHatTaskNamespace(BaseTaskNamespace):
+             except OSError, e:
+                 root_logger.error(
+                     "Could not remove %s: %s", new_cacert_path, e)
++                result = False
+             else:
+                 update = True
+ 
+         if update:
+-            try:
+-                ipautil.run([paths.UPDATE_CA_TRUST])
+-            except CalledProcessError, e:
+-                root_logger.error(
+-                    "Could not update systemwide CA trust database: %s", e)
++            if not self.reload_systemwide_ca_store():
+                 return False
+-            else:
+-                root_logger.info("Systemwide CA database updated.")
+-                return True
+ 
+-        return False
++        return result
+ 
+     def backup_and_replace_hostname(self, fstore, statestore, hostname):
+         old_hostname = socket.gethostname()
+diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
+index 75ee243d1c8deb6f8452744df4c040fd0794250c..5d583f7e9186f20ebe8187ba70db28de0c255ae7 100644
+--- a/ipaserver/install/ipa_backup.py
++++ b/ipaserver/install/ipa_backup.py
+@@ -138,6 +138,8 @@ class Backup(admintool.AdminTool):
+         paths.SYSCONFIG_ODS,
+         paths.ETC_SYSCONFIG_AUTHCONFIG,
+         paths.IPA_NSSDB_PWDFILE_TXT,
++        paths.IPA_P11_KIT,
++        paths.SYSTEMWIDE_IPA_CA_CRT,
+         paths.NSSWITCH_CONF,
+         paths.KRB5_KEYTAB,
+         paths.SSSD_CONF,
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 352a1ca2bf283c0beb8c95925c6eb9c9984b3338..8b1e80f5ed5e140ccb17ea0b63d92b6049507b74 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -26,7 +26,7 @@ import pwd
+ from ConfigParser import SafeConfigParser
+ 
+ from ipalib import api, errors
+-from ipapython import version
++from ipapython import version, ipautil, certdb
+ from ipapython.ipautil import run, user_input
+ from ipapython import admintool
+ from ipapython.dn import DN
+@@ -278,7 +278,9 @@ class Restore(admintool.AdminTool):
+                     create_ca_user()
+                 if options.online:
+                     raise admintool.ScriptError('File restoration cannot be done online.')
++                self.cert_restore_prepare()
+                 self.file_restore(options.no_logs)
++                self.cert_restore()
+                 if 'CA' in self.backup_services:
+                     self.__create_dogtag_log_dirs()
+ 
+@@ -660,3 +662,34 @@ class Restore(admintool.AdminTool):
+             tasks.set_selinux_booleans(bools)
+         except ipapython.errors.SetseboolError as e:
+             self.log.error('%s', e)
++
++    def cert_restore_prepare(self):
++        for basename in ('cert8.db', 'key3.db', 'secmod.db', 'pwdfile.txt'):
++            filename = os.path.join(paths.IPA_NSSDB_DIR, basename)
++            try:
++                ipautil.backup_file(filename)
++            except OSError as e:
++                self.log.error("Failed to backup %s: %s" % (filename, e))
++
++        tasks.remove_ca_certs_from_systemwide_ca_store()
++
++    def cert_restore(self):
++        if not os.path.exists(os.path.join(paths.IPA_NSSDB_DIR, 'cert8.db')):
++            certdb.create_ipa_nssdb()
++            ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
++            sys_db = certdb.NSSDatabase(paths.NSS_DB_DIR)
++            for nickname, trust_flags in (('IPA CA', 'CT,C,C'),
++                                          ('External CA cert', 'C,,')):
++                try:
++                    cert = sys_db.get_cert(nickname)
++                except RuntimeError:
++                    pass
++                else:
++                    try:
++                        ipa_db.add_cert(cert, nickname, trust_flags)
++                    except ipautil.CalledProcessError as e:
++                        self.log.error(
++                            "Failed to add %s to %s: %s" %
++                            (nickname, paths.IPA_NSSDB_DIR, e))
++
++        tasks.reload_systemwide_ca_store()
+-- 
+2.1.0
+
diff --git a/SOURCES/0022-Fix-ipa-client-automount-uninstall-when-fstore-is-em.patch b/SOURCES/0022-Fix-ipa-client-automount-uninstall-when-fstore-is-em.patch
deleted file mode 100644
index e478189..0000000
--- a/SOURCES/0022-Fix-ipa-client-automount-uninstall-when-fstore-is-em.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 8782235cff60229051c82880131fb11c82659a0b Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Wed, 15 Jan 2014 10:48:10 +0100
-Subject: [PATCH 22/25] Fix ipa-client-automount uninstall when fstore is
- empty.
-
-https://fedorahosted.org/freeipa/ticket/4091
----
- ipa-client/ipa-install/ipa-client-automount | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipa-client/ipa-install/ipa-client-automount b/ipa-client/ipa-install/ipa-client-automount
-index 2ce31dcb9605941fa8734caad7ed5ba9b5ce1e01..62531bfe1d923b1705aed1187da6766b54c90a0c 100755
---- a/ipa-client/ipa-install/ipa-client-automount
-+++ b/ipa-client/ipa-install/ipa-client-automount
-@@ -360,7 +360,7 @@ def main():
- 
-     fstore = sysrestore.FileStore('/var/lib/ipa-client/sysrestore')
-     statestore = sysrestore.StateFile('/var/lib/ipa-client/sysrestore')
--    if not fstore.has_files():
-+    if not fstore.has_files() and not os.path.exists('/etc/ipa/default.conf'):
-         sys.exit('IPA client is not configured on this system.\n')
- 
-     options, args = parse_options()
--- 
-1.8.4.2
-
diff --git a/SOURCES/0023-Fix-DNS-installer-adds-invalid-zonemgr-email.patch b/SOURCES/0023-Fix-DNS-installer-adds-invalid-zonemgr-email.patch
new file mode 100644
index 0000000..0de6d63
--- /dev/null
+++ b/SOURCES/0023-Fix-DNS-installer-adds-invalid-zonemgr-email.patch
@@ -0,0 +1,43 @@
+From cb9593d1571ed8704ebe33084463b2462a30cab9 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Fri, 7 Nov 2014 12:45:43 +0100
+Subject: [PATCH] Fix: DNS installer adds invalid zonemgr email
+
+Installer adds zonemgr as relative (and invalid) address.
+This fix force installer to use absolute email.
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4707
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/share/bind.zone.db.template | 2 +-
+ ipaserver/install/bindinstance.py   | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/install/share/bind.zone.db.template b/install/share/bind.zone.db.template
+index 6795bb01a7d8003a26dcc8a1cbc337550b3c296c..ec175c60825869ea9b86f7d1351a96189028b5d4 100644
+--- a/install/share/bind.zone.db.template
++++ b/install/share/bind.zone.db.template
+@@ -1,6 +1,6 @@
+ $$ORIGIN $DOMAIN.
+ $$TTL	86400
+-@			IN SOA	$DOMAIN. $ZONEMGR. (
++@			IN SOA	$DOMAIN. $ZONEMGR (
+ 				01		; serial 
+ 				3H		; refresh
+ 				15M		; retry
+diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
+index 6cf018e9cda3734a99a8ac5ac1df134e9e4c2293..16894de0a009aacb123cf76072f2556aebc5722f 100644
+--- a/ipaserver/install/bindinstance.py
++++ b/ipaserver/install/bindinstance.py
+@@ -563,7 +563,7 @@ class BindInstance(service.Service):
+         self.no_dnssec_validation=no_dnssec_validation
+ 
+         if not zonemgr:
+-            self.zonemgr = 'hostmaster.%s' % self.domain
++            self.zonemgr = 'hostmaster.%s' % normalize_zone(self.domain)
+         else:
+             self.zonemgr = normalize_zonemgr(zonemgr)
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0023-trust-fetch-domains-create-ranges-for-new-child-doma.patch b/SOURCES/0023-trust-fetch-domains-create-ranges-for-new-child-doma.patch
deleted file mode 100644
index fca1bd3..0000000
--- a/SOURCES/0023-trust-fetch-domains-create-ranges-for-new-child-doma.patch
+++ /dev/null
@@ -1,346 +0,0 @@
-From f446cde6f626f5a4b086a542121486bde42d0dc7 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 14 Jan 2014 13:55:56 +0200
-Subject: [PATCH 23/25] trust-fetch-domains: create ranges for new child
- domains
-
-When trust is added, we do create ranges for discovered child domains.
-However, this functionality was not available through
-'trust-fetch-domains' command.
-
-Additionally, make sure non-existing trust will report proper error in
-trust-fetch-domains.
-
-https://fedorahosted.org/freeipa/ticket/4111
-https://fedorahosted.org/freeipa/ticket/4104
----
- ipalib/plugins/trust.py | 256 +++++++++++++++++++++++++-----------------------
- 1 file changed, 135 insertions(+), 121 deletions(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 76d609fd4de33edd96715deaaf7842c1de3ddaf4..a16c23083662fd674c45ba54b9dfb9f4837160df 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -188,6 +188,114 @@ def make_trust_dn(env, trust_type, dn):
-         return DN(dn, container_dn)
-     return dn
- 
-+def add_range(self, range_name, dom_sid, *keys, **options):
-+    """
-+    First, we try to derive the parameters of the ID range based on the
-+    information contained in the Active Directory.
-+
-+    If that was not successful, we go for our usual defaults (random base,
-+    range size 200 000, ipa-ad-trust range type).
-+
-+    Any of these can be overriden by passing appropriate CLI options
-+    to the trust-add command.
-+    """
-+
-+    range_size = None
-+    range_type = None
-+    base_id = None
-+
-+    # First, get information about ID space from AD
-+    # However, we skip this step if other than ipa-ad-trust-posix
-+    # range type is enforced
-+
-+    if options.get('range_type', None) in (None, u'ipa-ad-trust-posix'):
-+
-+        # Get the base dn
-+        domain = keys[-1]
-+        basedn = realm_to_suffix(domain)
-+
-+        # Search for information contained in
-+        # CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System
-+        info_filter = '(objectClass=msSFU30DomainInfo)'
-+        info_dn = DN('CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System')\
-+                  + basedn
-+
-+        # Get the domain validator
-+        domain_validator = ipaserver.dcerpc.DomainValidator(self.api)
-+        if not domain_validator.is_configured():
-+            raise errors.NotFound(
-+                reason=_('Cannot search in trusted domains without own '
-+                         'domain configured. Make sure you have run '
-+                         'ipa-adtrust-install on the IPA server first'))
-+
-+        # KDC might not get refreshed data at the first time,
-+        # retry several times
-+        for retry in range(10):
-+            info_list = domain_validator.search_in_dc(domain,
-+                                                      info_filter,
-+                                                      None,
-+                                                      SCOPE_SUBTREE,
-+                                                      basedn=info_dn,
-+                                                      quiet=True)
-+
-+            if info_list:
-+                info = info_list[0]
-+                break
-+            else:
-+                sleep(2)
-+
-+        required_msSFU_attrs = ['msSFU30MaxUidNumber', 'msSFU30OrderNumber']
-+
-+        if not info_list:
-+            # We were unable to gain UNIX specific info from the AD
-+            self.log.debug("Unable to gain POSIX info from the AD")
-+        else:
-+            if all(attr in info for attr in required_msSFU_attrs):
-+                self.log.debug("Able to gain POSIX info from the AD")
-+                range_type = u'ipa-ad-trust-posix'
-+
-+                max_uid = info.get('msSFU30MaxUidNumber')
-+                max_gid = info.get('msSFU30MaxGidNumber', None)
-+                max_id = int(max(max_uid, max_gid)[0])
-+
-+                base_id = int(info.get('msSFU30OrderNumber')[0])
-+                range_size = (1 + (max_id - base_id) / DEFAULT_RANGE_SIZE)\
-+                             * DEFAULT_RANGE_SIZE
-+
-+    # Second, options given via the CLI options take precedence to discovery
-+    if options.get('range_type', None):
-+        range_type = options.get('range_type', None)
-+    elif not range_type:
-+        range_type = u'ipa-ad-trust'
-+
-+    if options.get('range_size', None):
-+        range_size = options.get('range_size', None)
-+    elif not range_size:
-+        range_size = DEFAULT_RANGE_SIZE
-+
-+    if options.get('base_id', None):
-+        base_id = options.get('base_id', None)
-+    elif not base_id:
-+        # Generate random base_id if not discovered nor given via CLI
-+        base_id = DEFAULT_RANGE_SIZE + (
-+            pysss_murmur.murmurhash3(
-+                dom_sid,
-+                len(dom_sid), 0xdeadbeefL
-+            ) % 10000
-+        ) * DEFAULT_RANGE_SIZE
-+
-+    # Finally, add new ID range
-+    self.api.Command['idrange_add'](range_name,
-+                                    ipabaseid=base_id,
-+                                    ipaidrangesize=range_size,
-+                                    ipabaserid=0,
-+                                    iparangetype=range_type,
-+                                    ipanttrusteddomainsid=dom_sid)
-+
-+    # Return the values that were generated inside this function
-+    return range_type, range_size, base_id
-+
-+
- class trust(LDAPObject):
-     """
-     Trust object.
-@@ -258,15 +366,11 @@ def get_dn(self, *keys, **kwargs):
-             filter = ldap.make_filter({'objectclass': ['ipaNTTrustedDomain'], 'cn': [keys[-1]] },
-                                       rules=ldap.MATCH_ALL)
-             filter = ldap.combine_filters((filter, "ipaNTSIDBlacklistIncoming=*"), rules=ldap.MATCH_ALL)
--            try:
--                result = ldap.get_entries(DN(self.container_dn, self.env.basedn),
--                                          ldap.SCOPE_SUBTREE, filter, [''])
--            except errors.NotFound:
--                return None
--            else:
--                if len(result) > 1:
--                    raise errors.OnlyOneValueAllowed(attr='trust domain')
--                return result[0].dn
-+            result = ldap.get_entries(DN(self.container_dn, self.env.basedn),
-+                                      ldap.SCOPE_SUBTREE, filter, [''])
-+            if len(result) > 1:
-+                raise errors.OnlyOneValueAllowed(attr='trust domain')
-+            return result[0].dn
- 
-         dn=make_trust_dn(self.env, trust_type, DN(*sdn))
-         return dn
-@@ -341,8 +445,8 @@ def execute(self, *keys, **options):
-             # Store the created range type, since for POSIX trusts no
-             # ranges for the subdomains should be added, POSIX attributes
-             # provide a global mapping across all subdomains
--            (created_range_type, _, _) = self.add_range(range_name, dom_sid,
--                                                        *keys, **options)
-+            (created_range_type, _, _) = add_range(self, range_name, dom_sid,
-+                                                   *keys, **options)
-         else:
-             created_range_type = old_range['result']['iparangetype'][0]
- 
-@@ -382,8 +486,8 @@ def execute(self, *keys, **options):
- 
-                     # Try to add the range for each subdomain
-                     try:
--                        self.add_range(range_name, dom_sid, *keys,
--                                       **passed_options)
-+                        add_range(self, range_name, dom_sid, *keys,
-+                                  **passed_options)
-                     except errors.DuplicateEntry:
-                         pass
- 
-@@ -549,120 +653,17 @@ def validate_range(self, *keys, **options):
- 
-         return old_range, range_name, dom_sid
- 
--    def add_range(self, range_name, dom_sid, *keys, **options):
--        """
--        First, we try to derive the parameters of the ID range based on the
--        information contained in the Active Directory.
--
--        If that was not successful, we go for our usual defaults (random base,
--        range size 200 000, ipa-ad-trust range type).
--
--        Any of these can be overriden by passing appropriate CLI options
--        to the trust-add command.
--        """
--
--        range_size = None
--        range_type = None
--        base_id = None
--
--        # First, get information about ID space from AD
--        # However, we skip this step if other than ipa-ad-trust-posix
--        # range type is enforced
--
--        if options.get('range_type', None) in (None, u'ipa-ad-trust-posix'):
--
--            # Get the base dn
--            domain = keys[-1]
--            basedn = realm_to_suffix(domain)
--
--            # Search for information contained in
--            # CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System
--            info_filter = '(objectClass=msSFU30DomainInfo)'
--            info_dn = DN('CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System')\
--                      + basedn
--
--            # Get the domain validator
--            domain_validator = ipaserver.dcerpc.DomainValidator(self.api)
--            if not domain_validator.is_configured():
--                raise errors.NotFound(
--                    reason=_('Cannot search in trusted domains without own '
--                             'domain configured. Make sure you have run '
--                             'ipa-adtrust-install on the IPA server first'))
--
--            # KDC might not get refreshed data at the first time,
--            # retry several times
--            for retry in range(10):
--                info_list = domain_validator.search_in_dc(domain,
--                                                          info_filter,
--                                                          None,
--                                                          SCOPE_SUBTREE,
--                                                          basedn=info_dn,
--                                                          quiet=True)
--
--                if info_list:
--                    info = info_list[0]
--                    break
--                else:
--                    sleep(2)
--
--            required_msSFU_attrs = ['msSFU30MaxUidNumber', 'msSFU30OrderNumber']
--
--            if not info_list:
--                # We were unable to gain UNIX specific info from the AD
--                self.log.debug("Unable to gain POSIX info from the AD")
--            else:
--                if all(attr in info for attr in required_msSFU_attrs):
--                    self.log.debug("Able to gain POSIX info from the AD")
--                    range_type = u'ipa-ad-trust-posix'
--
--                    max_uid = info.get('msSFU30MaxUidNumber')
--                    max_gid = info.get('msSFU30MaxGidNumber', None)
--                    max_id = int(max(max_uid, max_gid)[0])
--
--                    base_id = int(info.get('msSFU30OrderNumber')[0])
--                    range_size = (1 + (max_id - base_id) / DEFAULT_RANGE_SIZE)\
--                                 * DEFAULT_RANGE_SIZE
--
--        # Second, options given via the CLI options take precedence to discovery
--        if options.get('range_type', None):
--            range_type = options.get('range_type', None)
--        elif not range_type:
--            range_type = u'ipa-ad-trust'
--
--        if options.get('range_size', None):
--            range_size = options.get('range_size', None)
--        elif not range_size:
--            range_size = DEFAULT_RANGE_SIZE
--
--        if options.get('base_id', None):
--            base_id = options.get('base_id', None)
--        elif not base_id:
--            # Generate random base_id if not discovered nor given via CLI
--            base_id = DEFAULT_RANGE_SIZE + (
--                pysss_murmur.murmurhash3(
--                    dom_sid,
--                    len(dom_sid), 0xdeadbeefL
--                ) % 10000
--            ) * DEFAULT_RANGE_SIZE
--
--        # Finally, add new ID range
--        api.Command['idrange_add'](range_name,
--                                   ipabaseid=base_id,
--                                   ipaidrangesize=range_size,
--                                   ipabaserid=0,
--                                   iparangetype=range_type,
--                                   ipanttrusteddomainsid=dom_sid)
--
--        # Return the values that were generated inside this function
--        return range_type, range_size, base_id
--
-     def execute_ad(self, full_join, *keys, **options):
-         # Join domain using full credentials and with random trustdom
-         # secret (will be generated by the join method)
- 
-         # First see if the trust is already in place
-         # Force retrieval of the trust object by not passing trust_type
--        dn = self.obj.get_dn(keys[-1])
-+        try:
-+            dn = self.obj.get_dn(keys[-1])
-+        except errors.NotFound:
-+            dn = None
-+
-         if dn:
-             summary = _('Re-established trust to domain "%(value)s"')
-         else:
-@@ -794,6 +795,7 @@ class trust_show(LDAPRetrieve):
- 
-     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
- 
-+        assert isinstance(dn, DN)
-         # Translate ipanttrusttype to trusttype
-         # and ipanttrustdirection to trustdirection
-         # if --raw not used
-@@ -1246,6 +1248,11 @@ def fetch_domains_from_trust(self, trustinstance, trust_entry, **options):
-     if not domains:
-         return result
- 
-+    # trust range must exist by the time fetch_domains_from_trust is called
-+    range_name = trust_name.upper() + '_id_range'
-+    old_range = api.Command.idrange_show(range_name, raw=True)['result']
-+    idrange_type = old_range['iparangetype']
-+
-     for dom in domains:
-         dom['trust_type'] = u'ad'
-         try:
-@@ -1255,8 +1262,15 @@ def fetch_domains_from_trust(self, trustinstance, trust_entry, **options):
-                 dom['all'] = options['all']
-             if 'raw' in options:
-                 dom['raw'] = options['raw']
-+
-             res = self.api.Command.trustdomain_add(trust_name, name, **dom)
-             result.append(res['result'])
-+
-+            if idrange_type != u'ipa-ad-trust-posix':
-+                range_name = name.upper() + '_id_range'
-+                dom['range_type'] = u'ipa-ad-trust'
-+                add_range(self, range_name, dom['ipanttrusteddomainsid'],
-+                          trust_name, name, **dom)
-         except errors.DuplicateEntry:
-             # Ignore updating duplicate entries
-             pass
--- 
-1.8.4.2
-
diff --git a/SOURCES/0024-ipaplatform-Use-the-dirsrv-service-not-target.patch b/SOURCES/0024-ipaplatform-Use-the-dirsrv-service-not-target.patch
new file mode 100644
index 0000000..fc46b34
--- /dev/null
+++ b/SOURCES/0024-ipaplatform-Use-the-dirsrv-service-not-target.patch
@@ -0,0 +1,37 @@
+From f16e7b3a95d48afc0e798055e8ff4ac9efd9ce28 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <pviktori@redhat.com>
+Date: Tue, 11 Nov 2014 16:07:37 +0100
+Subject: [PATCH] ipaplatform: Use the dirsrv service, not target
+
+IPA only uses one instance of the directory server. When an instance
+is not specified to a call to service.start/stop/restart/...,
+use IPA's instance.
+
+Stopping a systemd service is synchronous (bby default), but stopping
+a target is not. This will change ensures that the directory server
+is actually down when stop() finishes.
+
+https://fedorahosted.org/freeipa/ticket/4709
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaplatform/base/services.py | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py
+index 961c368e6b4d81d337cf0a8601075f052352ecbf..370b628c78a65591dec09db25f9f7545f920d795 100644
+--- a/ipaplatform/base/services.py
++++ b/ipaplatform/base/services.py
+@@ -187,8 +187,7 @@ class SystemdService(PlatformService):
+         elements = self.systemd_name.split("@")
+ 
+         # Make sure the correct DS instance is returned
+-        if (elements[0] == 'dirsrv' and not instance_name and
+-            operation == 'is-active'):
++        if elements[0] == 'dirsrv' and not instance_name:
+ 
+             return ('dirsrv@%s.service'
+                     % str(self.api.env.realm.replace('.', '-')))
+-- 
+2.1.0
+
diff --git a/SOURCES/0024-trustdomain-find-report-status-of-the-sub-domain.patch b/SOURCES/0024-trustdomain-find-report-status-of-the-sub-domain.patch
deleted file mode 100644
index 7c94776..0000000
--- a/SOURCES/0024-trustdomain-find-report-status-of-the-sub-domain.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From c805cd76acc8fbc9c2cb689deaf6e5eae78700c5 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 15 Jan 2014 15:42:10 +0200
-Subject: [PATCH 24/25] trustdomain-find: report status of the (sub)domain
-
-Show status of each enumerated domain
-
-trustdomain-find shows list of domains associated with the trust.
-Each domain except the trust forest root can be enabled or disabled
-with the help of trustdomain-enable and trustdomain-disable commands.
-
-https://fedorahosted.org/freeipa/ticket/4096
----
- ipalib/plugins/trust.py | 18 +++++++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index a16c23083662fd674c45ba54b9dfb9f4837160df..3d412c9c9f518347769e88ddc9089d6d92ccc4be 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -21,7 +21,7 @@
- from ipalib.plugins.baseldap import *
- from ipalib.plugins.dns import dns_container_exists
- from ipapython.ipautil import realm_to_suffix
--from ipalib import api, Str, StrEnum, Password, _, ngettext
-+from ipalib import api, Str, StrEnum, Password, Bool, _, ngettext
- from ipalib import Command
- from ipalib import errors
- from ldap import SCOPE_SUBTREE
-@@ -1183,8 +1183,24 @@ def get_dn(self, *keys, **kwargs):
- class trustdomain_find(LDAPSearch):
-     __doc__ = _('Search domains of the trust')
- 
-+    has_output_params = LDAPSearch.has_output_params + (
-+        Flag('domain_enabled', label= _('Domain enabled')),
-+    )
-     def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
-         return (filters, base_dn, ldap.SCOPE_SUBTREE)
-+
-+    def post_callback(self, ldap, entries, truncated, *args, **options):
-+        trust_dn = self.obj.get_dn(args[0], trust_type=u'ad')
-+        trust_entry = ldap.get_entry(trust_dn)
-+        for entry in entries:
-+            sid = entry['ipanttrusteddomainsid'][0]
-+            if sid in trust_entry['ipantsidblacklistincoming']:
-+                entry['domain_enabled'] = [False]
-+            else:
-+                entry['domain_enabled'] = [True]
-+        return truncated
-+
-+
- api.register(trustdomain_find)
- 
- class trustdomain_mod(LDAPUpdate):
--- 
-1.8.4.2
-
diff --git a/SOURCES/0025-CLDAP-do-not-prepend.patch b/SOURCES/0025-CLDAP-do-not-prepend.patch
deleted file mode 100644
index fc97f15..0000000
--- a/SOURCES/0025-CLDAP-do-not-prepend.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 198f16c26e36bd8b4b7d55a74bb679a6daa85084 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 13 Jan 2014 10:43:33 +0100
-Subject: [PATCH 25/25] CLDAP: do not prepend \\
-
-For NETLOGON_NT_VERSION_5EX requests the prepended \\ is not expected in
-the PDC NetBIOS name. In general AD seems to be smart enough to handle
-the two \ signs. But if the NetBIOS name reaches the maximum of 15
-character AD does not accept the responses anymore.
-
-Fixes https://fedorahosted.org/freeipa/ticket/4028
----
- daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-index 9ba05829418a0d1de46f2c7776cc15c54a9eab1c..c03172d474589ddee84f1cfa5395c23fdba83bcb 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-@@ -163,7 +163,7 @@ static int ipa_cldap_encode_netlogon(char *fq_hostname, char *domain,
-     nlr->domain_name = name;
- 
-     /* copy the first 15 characters of the fully qualified hostname*/
--    pdc_name = talloc_asprintf(nlr, "\\\\%.*s", NETBIOS_NAME_MAX, fq_hostname);
-+    pdc_name = talloc_asprintf(nlr, "%.*s", NETBIOS_NAME_MAX, fq_hostname);
- 
-     for (p = pdc_name; *p; p++) {
-         /* Create the NetBIOS name from the first segment of the hostname */
--- 
-1.8.4.2
-
diff --git a/SOURCES/0025-Fix-DNS-policy-upgrade-raises-asertion-error.patch b/SOURCES/0025-Fix-DNS-policy-upgrade-raises-asertion-error.patch
new file mode 100644
index 0000000..a56a044
--- /dev/null
+++ b/SOURCES/0025-Fix-DNS-policy-upgrade-raises-asertion-error.patch
@@ -0,0 +1,29 @@
+From a7fdb85235909e8498f0b8b257bbab5825c3c338 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Fri, 7 Nov 2014 15:09:29 +0100
+Subject: [PATCH] Fix: DNS policy upgrade raises asertion error
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4708
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/plugins/dns.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py
+index 1aef837f63176cd307868c726460485fd4a004ed..62cf588d27155acb03026f69ea09ff15582d26dc 100644
+--- a/ipaserver/install/plugins/dns.py
++++ b/ipaserver/install/plugins/dns.py
+@@ -86,7 +86,9 @@ class update_dnszones(PostUpdate):
+                         api.env.realm)
+ 
+             if update:
+-                api.Command.dnszone_mod(zone[u'idnsname'][0], **update)
++                # FIXME: https://fedorahosted.org/freeipa/ticket/4722
++                api.Command.dnszone_mod(zone[u'idnsname'][0].make_absolute(),
++                                        **update)
+ 
+         return (False, False, [])
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0026-Fix-upgrade-referint-plugin.patch b/SOURCES/0026-Fix-upgrade-referint-plugin.patch
new file mode 100644
index 0000000..d72fba0
--- /dev/null
+++ b/SOURCES/0026-Fix-upgrade-referint-plugin.patch
@@ -0,0 +1,153 @@
+From 822910bb85c4dedff39faff142e645c5f2922984 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Fri, 7 Nov 2014 13:28:01 +0100
+Subject: [PATCH] Fix upgrade referint plugin
+
+Mixing 'Old' and 'New' attr style for referential integrity plugin causes errors.
+Now old setting are migrated to new style setting before upgrade
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4622
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/updates/25-referint.update           | 13 +---
+ ipaserver/install/plugins/Makefile.am        |  1 +
+ ipaserver/install/plugins/update_referint.py | 90 ++++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+), 12 deletions(-)
+ create mode 100644 ipaserver/install/plugins/update_referint.py
+
+diff --git a/install/updates/25-referint.update b/install/updates/25-referint.update
+index a43d21ad5152358cb939c3545f0eef9d251e7fe0..609eaba74f0fcde6ce875093587315681fbd4584 100644
+--- a/install/updates/25-referint.update
++++ b/install/updates/25-referint.update
+@@ -1,19 +1,8 @@
+ # Expand attributes checked by Referential Integrity plugin
+ # pres and eq indexes defined in 20-indices.update must be set for all these
+ # attributes
++# NOTE: migration to new style is done in update_referint.py
+ dn: cn=referential integrity postoperation,cn=plugins,cn=config
+-remove: nsslapd-pluginArg7: manager
+-remove: nsslapd-pluginArg8: secretary
+-remove: nsslapd-pluginArg9: memberuser
+-remove: nsslapd-pluginArg10: memberhost
+-remove: nsslapd-pluginArg11: sourcehost
+-remove: nsslapd-pluginArg12: memberservice
+-remove: nsslapd-pluginArg13: managedby
+-remove: nsslapd-pluginArg14: memberallowcmd
+-remove: nsslapd-pluginArg15: memberdenycmd
+-remove: nsslapd-pluginArg16: ipasudorunas
+-remove: nsslapd-pluginArg17: ipasudorunasgroup
+-remove: nsslapd-pluginArg18: ipatokenradiusconfiglink
+ add: referint-membership-attr: manager
+ add: referint-membership-attr: secretary
+ add: referint-membership-attr: memberuser
+diff --git a/ipaserver/install/plugins/Makefile.am b/ipaserver/install/plugins/Makefile.am
+index 635877d8c2160a91208276498cdb4cd9bc82d56b..d651297ac141b0f05831e7fabbb9b561cdd239c7 100644
+--- a/ipaserver/install/plugins/Makefile.am
++++ b/ipaserver/install/plugins/Makefile.am
+@@ -11,6 +11,7 @@ app_PYTHON = 			\
+ 	update_services.py	\
+ 	update_anonymous_aci.py	\
+ 	update_pacs.py		\
++	update_referint.py	\
+ 	ca_renewal_master.py	\
+ 	update_uniqueness.py	\
+ 	$(NULL)
+diff --git a/ipaserver/install/plugins/update_referint.py b/ipaserver/install/plugins/update_referint.py
+new file mode 100644
+index 0000000000000000000000000000000000000000..1b7411035b27ebba04246a7ee6f220d470b46688
+--- /dev/null
++++ b/ipaserver/install/plugins/update_referint.py
+@@ -0,0 +1,90 @@
++#
++# Copyright (C) 2014  FreeIPA Contributors see COPYING for license
++#
++
++from ipaserver.install.plugins import MIDDLE
++from ipaserver.install.plugins.baseupdate import PreUpdate
++from ipalib import api, errors
++from ipapython.dn import DN
++from ipapython.ipa_log_manager import root_logger
++
++class update_referint(PreUpdate):
++    """
++    Update referential integrity configuration to new style
++    http://directory.fedoraproject.org/docs/389ds/design/ri-plugin-configuration.html
++
++    old attr              -> new attr
++    nsslapd-pluginArg0    -> referint-update-delay
++    nsslapd-pluginArg1    -> referint-logfile
++    nsslapd-pluginArg2    -> referint-logchanges
++    nsslapd-pluginArg3..N -> referint-membership-attr [3..N]
++
++    Old and new style cannot be mixed, all nslapd-pluginArg* attrs have to be removed
++    """
++
++    order = MIDDLE
++
++    referint_dn = DN(('cn', 'referential integrity postoperation'),
++                           ('cn', 'plugins'), ('cn', 'config'))
++
++    def execute(self, **options):
++
++        root_logger.debug("Upgrading referential integrity plugin configuration")
++        ldap = self.obj.backend
++        try:
++            entry = ldap.get_entry(self.referint_dn)
++        except errors.NotFound:
++            root_logger.error("Referential integrity configuration not found")
++            return False, False, []
++
++        referint_membership_attrs = []
++
++        root_logger.debug("Initial value: %s", repr(entry))
++
++        # nsslapd-pluginArg0    -> referint-update-delay
++        update_delay = entry.get('nsslapd-pluginArg0')
++        if update_delay:
++            root_logger.debug("add: referint-update-delay: %s", update_delay)
++            entry['referint-update-delay'] = update_delay
++            entry['nsslapd-pluginArg0'] = None
++        else:
++            root_logger.info("Plugin already uses new style, skipping")
++            return False, False, []
++
++        # nsslapd-pluginArg1    -> referint-logfile
++        logfile = entry.get('nsslapd-pluginArg1')
++        if logfile:
++            root_logger.debug("add: referint-logfile: %s", logfile)
++            entry['referint-logfile'] = logfile
++            entry['nsslapd-pluginArg1'] = None
++
++        # nsslapd-pluginArg2    -> referint-logchanges
++        logchanges = entry.get('nsslapd-pluginArg2')
++        if logchanges:
++            root_logger.debug("add: referint-logchanges: %s", logchanges)
++            entry['referint-logchanges'] = logchanges
++            entry['nsslapd-pluginArg2'] = None
++
++        # nsslapd-pluginArg3..N -> referint-membership-attr [3..N]
++        for key in entry.keys():
++            if key.lower().startswith('nsslapd-pluginarg'):
++                arg_val = entry.single_value[key]
++                if arg_val:
++                    referint_membership_attrs.append(arg_val)
++                entry[key] = None
++
++        if referint_membership_attrs:
++            # entry['referint-membership-attr'] is None, plugin doesn't allow
++            # mixing old and new style
++            entry['referint-membership-attr'] = referint_membership_attrs
++
++        root_logger.debug("Final value: %s", repr(entry))
++        try:
++            ldap.update_entry(entry)
++        except errors.EmptyModlist:
++            root_logger.debug("No modifications required")
++            return False, False, []
++
++        return False, True, []
++
++api.register(update_referint)
+-- 
+2.1.0
+
diff --git a/SOURCES/0026-ipaserver-install-installutils-clean-up-properly-aft.patch b/SOURCES/0026-ipaserver-install-installutils-clean-up-properly-aft.patch
deleted file mode 100644
index d80e27b..0000000
--- a/SOURCES/0026-ipaserver-install-installutils-clean-up-properly-aft.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From fcd4ec48c2515aff7c10f10653628631d832146b Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 15 Jan 2014 17:26:10 +0100
-Subject: [PATCH 26/27] ipaserver/install/installutils: clean up properly after
- yield
-
-When a context to which we yield generates exception, the code in
-private_ccache() and stopped_service() didn't get called for cleanup.
----
- ipaserver/install/installutils.py | 25 ++++++++++++++-----------
- 1 file changed, 14 insertions(+), 11 deletions(-)
-
-diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
-index c26f072f2f44149746d55b1160d09ebce8394fd5..3770432cae79f653fd57f726de43787dec8dd7d1 100644
---- a/ipaserver/install/installutils.py
-+++ b/ipaserver/install/installutils.py
-@@ -784,15 +784,16 @@ def private_ccache(path=None):
- 
-     os.environ['KRB5CCNAME'] = path
- 
--    yield
-+    try:
-+        yield
-+    finally:
-+        if original_value is not None:
-+            os.environ['KRB5CCNAME'] = original_value
-+        else:
-+            os.environ.pop('KRB5CCNAME')
- 
--    if original_value is not None:
--        os.environ['KRB5CCNAME'] = original_value
--    else:
--        os.environ.pop('KRB5CCNAME')
--
--    if os.path.exists(path):
--        os.remove(path)
-+        if os.path.exists(path):
-+            os.remove(path)
- 
- 
- @contextmanager
-@@ -825,6 +826,8 @@ def stopped_service(service, instance_name=""):
-         # Stop the service, do the required stuff and start it again
-         root_logger.debug('Stopping %s%s.', service, log_instance_name)
-         ipaservices.knownservices[service].stop(instance_name)
--        yield
--        root_logger.debug('Starting %s%s.', service, log_instance_name)
--        ipaservices.knownservices[service].start(instance_name)
-+        try:
-+            yield
-+        finally:
-+            root_logger.debug('Starting %s%s.', service, log_instance_name)
-+            ipaservices.knownservices[service].start(instance_name)
--- 
-1.8.4.2
-
diff --git a/SOURCES/0027-Do-not-start-the-service-in-stopped_service-if-it-wa.patch b/SOURCES/0027-Do-not-start-the-service-in-stopped_service-if-it-wa.patch
deleted file mode 100644
index 28749e4..0000000
--- a/SOURCES/0027-Do-not-start-the-service-in-stopped_service-if-it-wa.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From a923cedc1aedafe7f58d480a633257bd19809d72 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Tue, 15 Oct 2013 17:49:07 +0000
-Subject: [PATCH 27/27] Do not start the service in stopped_service if it was
- not running before.
-
-This fixes a possible NSS database corruption in renew_ca_cert.
----
- ipaserver/install/installutils.py | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
-index 3770432cae79f653fd57f726de43787dec8dd7d1..32671adc895b0cb2632729e8bdb44b5df02c1314 100644
---- a/ipaserver/install/installutils.py
-+++ b/ipaserver/install/installutils.py
-@@ -819,9 +819,6 @@ def stopped_service(service, instance_name=""):
-         root_logger.debug('Service %s%s is not running, continue.', service,
-                           log_instance_name)
-         yield
--        root_logger.debug('Starting %s%s.', service, log_instance_name)
--        ipaservices.knownservices[service].start(instance_name)
--        return
-     else:
-         # Stop the service, do the required stuff and start it again
-         root_logger.debug('Stopping %s%s.', service, log_instance_name)
--- 
-1.8.4.2
-
diff --git a/SOURCES/0027-Upgrade-fix-trusts-objectclass-violationi.patch b/SOURCES/0027-Upgrade-fix-trusts-objectclass-violationi.patch
new file mode 100644
index 0000000..e107203
--- /dev/null
+++ b/SOURCES/0027-Upgrade-fix-trusts-objectclass-violationi.patch
@@ -0,0 +1,63 @@
+From faa47e835213aaeff8ad4fa73b2bc20735615b37 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Mon, 10 Nov 2014 14:13:07 +0100
+Subject: [PATCH] Upgrade: fix trusts objectclass violationi
+
+Execute updates in proper ordering.
+Curently ldap-updater implementation doesnt allow better fix.
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4680
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/updates/59-trusts-sysacount.update | 8 ++++++++
+ install/updates/60-trusts.update           | 6 ------
+ install/updates/Makefile.am                | 1 +
+ 3 files changed, 9 insertions(+), 6 deletions(-)
+ create mode 100644 install/updates/59-trusts-sysacount.update
+
+diff --git a/install/updates/59-trusts-sysacount.update b/install/updates/59-trusts-sysacount.update
+new file mode 100644
+index 0000000000000000000000000000000000000000..b90de80d27b36c9a7bfd3b358338a0a79d969813
+--- /dev/null
++++ b/install/updates/59-trusts-sysacount.update
+@@ -0,0 +1,8 @@
++# this update must be applied before 60-trusts.update, because current
++# implementation of ipa-ldap-updater doesn't keep the order of updates in
++# filesets
++dn: cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX
++add: objectClass: nestedgroup
++default: objectClass: GroupOfNames
++default: objectClass: top
++default: cn: adtrust agents
+diff --git a/install/updates/60-trusts.update b/install/updates/60-trusts.update
+index 9dabc806e2f747c47ab809cd2ed2150b2a13c2a6..79caa837a55eae0e05e1a94f3eabdda7b2b9cc38 100644
+--- a/install/updates/60-trusts.update
++++ b/install/updates/60-trusts.update
+@@ -10,12 +10,6 @@ default: member: uid=admin,cn=users,cn=accounts,$SUFFIX
+ default: nsAccountLock: FALSE
+ default: ipaUniqueID: autogenerate
+ 
+-dn: cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX
+-add: objectClass: nestedgroup
+-default: objectClass: GroupOfNames
+-default: objectClass: top
+-default: cn: adtrust agents
+-
+ dn: cn=ADTrust Agents,cn=privileges,cn=pbac,$SUFFIX
+ default: objectClass: top
+ default: objectClass: groupofnames
+diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
+index e62a64cea925aaeae9d013ab01a89371c727a6fd..255586c6de1cab52a526c1ca82b4720adf998eee 100644
+--- a/install/updates/Makefile.am
++++ b/install/updates/Makefile.am
+@@ -41,6 +41,7 @@ app_DATA =				\
+ 	50-nis.update			\
+ 	50-ipaconfig.update		\
+ 	55-pbacmemberof.update		\
++	59-trusts-sysacount.update	\
+ 	60-trusts.update		\
+ 	61-trusts-s4u2proxy.update	\
+ 	62-ranges.update		\
+-- 
+2.1.0
+
diff --git a/SOURCES/0028-Harmonize-policy-discovery-to-kdb-driver.patch b/SOURCES/0028-Harmonize-policy-discovery-to-kdb-driver.patch
deleted file mode 100644
index 6e2a1f2..0000000
--- a/SOURCES/0028-Harmonize-policy-discovery-to-kdb-driver.patch
+++ /dev/null
@@ -1,180 +0,0 @@
-From 8ee0ea62d669f59246c8727d89a860bb6d6082f8 Mon Sep 17 00:00:00 2001
-From: Simo Sorce <simo@redhat.com>
-Date: Tue, 14 Jan 2014 10:09:37 -0500
-Subject: [PATCH 28/34] Harmonize policy discovery to kdb driver
-
-The KDB driver does not walk the tree back like the original password plugin.
-Also we do not store the default policy in the base DN as we used to do in the
-past anymore.
-So doing a full subtree search and walking back the tree is just a waste of
-time.
-Instead hardcode the default policy like we do in the kdb driver.
-
-Fixes: https://fedorahosted.org/freeipa/ticket/4085
----
- daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c | 106 ++++-------------------
- 1 file changed, 17 insertions(+), 89 deletions(-)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
-index 2538a4094bd9a166e61b0911e5ea93426092d88a..ef20c4c61bd764bffc426208ff8b99f5d0b782ec 100644
---- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
-+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
-@@ -436,75 +436,44 @@ static void pwd_values_free(Slapi_ValueSet** results,
-     slapi_vattr_values_free(results, actual_type_name, buffer_flags);
- }
- 
--static int ipapwd_rdn_count(const char *dn)
--{
--    int rdnc = 0;
--    LDAPDN ldn;
--    int ret;
--
--    ret = ldap_str2dn(dn, &ldn, LDAP_DN_FORMAT_LDAPV3);
--    if (ret != LDAP_SUCCESS) {
--        LOG_TRACE("ldap_str2dn(dn) failed ?!");
--        return -1;
--    }
--
--    for (rdnc = 0; ldn != NULL && ldn[rdnc]; rdnc++) /* count */ ;
--    ldap_dnfree(ldn);
--
--    return rdnc;
--}
--
- int ipapwd_getPolicy(const char *dn,
-                      Slapi_Entry *target,
-                      struct ipapwd_policy *policy)
- {
-     const char *krbPwdPolicyReference;
--    const char *pdn;
--    const Slapi_DN *psdn;
--    Slapi_Backend *be;
-+    char *pdn = NULL;
-     Slapi_PBlock *pb = NULL;
-     char *attrs[] = { "krbMaxPwdLife", "krbMinPwdLife",
-                       "krbPwdMinDiffChars", "krbPwdMinLength",
-                       "krbPwdHistoryLength", NULL};
-     Slapi_Entry **es = NULL;
-     Slapi_Entry *pe = NULL;
--    int ret, res, dist, rdnc, scope, i;
--    Slapi_DN *sdn = NULL;
-+    int ret, res, scope, i;
-     int buffer_flags=0;
-     Slapi_ValueSet* results = NULL;
--    char* actual_type_name = NULL;
-+    char *actual_type_name = NULL;
-     int tmpint;
- 
-     LOG_TRACE("Searching policy for [%s]\n", dn);
- 
--    sdn = slapi_sdn_new_dn_byref(dn);
--    if (sdn == NULL) {
--        LOG_OOM();
--        ret = -1;
--        goto done;
--    }
--
-     pwd_get_values(target, "krbPwdPolicyReference",
-                    &results, &actual_type_name, &buffer_flags);
-     if (results) {
-         Slapi_Value *sv;
-         slapi_valueset_first_value(results, &sv);
-         krbPwdPolicyReference = slapi_value_get_string(sv);
--        pdn = krbPwdPolicyReference;
--        scope = LDAP_SCOPE_BASE;
--        LOG_TRACE("using policy reference: %s\n", pdn);
-+        pdn = slapi_ch_strdup(krbPwdPolicyReference);
-     } else {
--        /* Find ancestor base DN */
--        be = slapi_be_select(sdn);
--        psdn = slapi_be_getsuffix(be, 0);
--        if (psdn == NULL) {
--            LOG_FATAL("Invalid DN [%s]\n", dn);
--            ret = -1;
--            goto done;
--        }
--        pdn = slapi_sdn_get_dn(psdn);
--        scope = LDAP_SCOPE_SUBTREE;
-+        /* Fallback to hardcoded value */
-+        pdn = slapi_ch_smprintf("cn=global_policy,%s", ipa_realm_dn);
-     }
-+    if (pdn == NULL) {
-+        LOG_OOM();
-+        ret = -1;
-+        goto done;
-+    }
-+    LOG_TRACE("Using policy at [%s]\n", pdn);
-+    scope = LDAP_SCOPE_BASE;
- 
-     pb = slapi_pblock_new();
-     slapi_search_internal_set_pb(pb,
-@@ -539,54 +508,13 @@ int ipapwd_getPolicy(const char *dn,
-     /* if there is only one, return that */
-     if (i == 1) {
-         pe = es[0];
--        goto fill;
--    }
--
--    /* count number of RDNs in DN */
--    rdnc = ipapwd_rdn_count(dn);
--    if (rdnc == -1) {
--        LOG_TRACE("ipapwd_rdn_count(dn) failed");
--        ret = -1;
--        goto done;
--    }
--
--    pe = NULL;
--    dist = -1;
--
--    /* find closest entry */
--    for (i = 0; es[i]; i++) {
--        const Slapi_DN *esdn;
--
--        esdn = slapi_entry_get_sdn_const(es[i]);
--        if (esdn == NULL) continue;
--        if (0 == slapi_sdn_compare(esdn, sdn)) {
--            pe = es[i];
--            dist = 0;
--            break;
--        }
--        if (slapi_sdn_issuffix(sdn, esdn)) {
--            const char *dn1;
--            int c1;
--
--            dn1 = slapi_sdn_get_dn(esdn);
--            if (!dn1) continue;
--            c1 = ipapwd_rdn_count(dn1);
--            if (c1 == -1) continue;
--            if ((dist == -1) ||
--                ((rdnc - c1) < dist)) {
--                dist = rdnc - c1;
--                pe = es[i];
--            }
--        }
--        if (dist == 0) break; /* found closest */
--    }
--
--    if (pe == NULL) {
-+    } else {
-+        LOG_TRACE("Multiple entries from a base search ?!");
-         ret = -1;
-         goto done;
-     }
- 
--fill:
-+    /* read data out of policy object */
-     policy->min_pwd_life = slapi_entry_attr_get_int(pe, "krbMinPwdLife");
- 
-     tmpint = slapi_entry_attr_get_int(pe, "krbMaxPwdLife");
-@@ -615,7 +543,7 @@ done:
-         slapi_free_search_results_internal(pb);
-         slapi_pblock_destroy(pb);
-     }
--    if (sdn) slapi_sdn_free(&sdn);
-+    slapi_ch_free_string(&pdn);
-     return ret;
- }
- 
--- 
-1.8.4.2
-
diff --git a/SOURCES/0028-Produce-better-error-in-group-add-command.patch b/SOURCES/0028-Produce-better-error-in-group-add-command.patch
new file mode 100644
index 0000000..9cbe930
--- /dev/null
+++ b/SOURCES/0028-Produce-better-error-in-group-add-command.patch
@@ -0,0 +1,28 @@
+From 2ed0fd652cce1cef6035856ff16bf090c844646e Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Wed, 5 Nov 2014 02:40:10 -0500
+Subject: [PATCH] Produce better error in group-add command.
+
+https://fedorahosted.org/freeipa/ticket/4611
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/plugins/group.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
+index 03e6893e3c7604268b503b28ea39ed3f610aec47..d25ed9a1958119a5872db85e958323fdb8205366 100644
+--- a/ipalib/plugins/group.py
++++ b/ipalib/plugins/group.py
+@@ -287,7 +287,7 @@ class group_add(LDAPCreate):
+         if options['external']:
+             entry_attrs['objectclass'].append('ipaexternalgroup')
+             if 'gidnumber' in options:
+-                raise errors.RequirementError(name='gid')
++                raise errors.MutuallyExclusiveError(reason=_('gid cannot be set for external group'))
+         elif not options['nonposix']:
+             entry_attrs['objectclass'].append('posixgroup')
+             if not 'gidnumber' in options:
+-- 
+2.1.0
+
diff --git a/SOURCES/0029-Search-using-proper-scope-when-connecting-CA-instanc.patch b/SOURCES/0029-Search-using-proper-scope-when-connecting-CA-instanc.patch
new file mode 100644
index 0000000..0a02cd2
--- /dev/null
+++ b/SOURCES/0029-Search-using-proper-scope-when-connecting-CA-instanc.patch
@@ -0,0 +1,32 @@
+From 6aa3004870321dc5f34b2a6a9e6d6cdf2459d7ee Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Thu, 6 Nov 2014 16:10:01 -0500
+Subject: [PATCH] Search using proper scope when connecting CA instances
+
+The wrong search scope was being used when trying to determine if
+a given master had a CA installed when trying to create a new
+connection.
+
+https://fedorahosted.org/freeipa/ticket/4704
+
+Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com>
+---
+ install/tools/ipa-csreplica-manage | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/tools/ipa-csreplica-manage b/install/tools/ipa-csreplica-manage
+index c534446d7b0daf0ce0709edf952a8795ba85e937..6f6c6c75a122274eeb221f6e0eb15959dec56786 100755
+--- a/install/tools/ipa-csreplica-manage
++++ b/install/tools/ipa-csreplica-manage
+@@ -303,7 +303,7 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
+ 
+         dn = DN(('cn', 'CA'), ('cn', replica2), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
+                 ipautil.realm_to_suffix(realm))
+-        conn.get_entries(dn, conn.SCOPE_ONELEVEL)
++        conn.get_entries(dn, conn.SCOPE_BASE)
+         conn.unbind()
+     except errors.NotFound:
+         sys.exit('%s does not have a CA configured.' % replica2)
+-- 
+2.1.0
+
diff --git a/SOURCES/0029-Stop-adding-a-default-password-policy-reference.patch b/SOURCES/0029-Stop-adding-a-default-password-policy-reference.patch
deleted file mode 100644
index 4e325d2..0000000
--- a/SOURCES/0029-Stop-adding-a-default-password-policy-reference.patch
+++ /dev/null
@@ -1,409 +0,0 @@
-From 46ad7d5e76929d5744355374c1e56c5004bf5281 Mon Sep 17 00:00:00 2001
-From: Simo Sorce <simo@redhat.com>
-Date: Thu, 16 Jan 2014 09:06:18 +0100
-Subject: [PATCH 29/34] Stop adding a default password policy reference
-
-Both the password plugin and the kdb driver code automatically fall
-back to the default password policy.
-so stop adding an explicit reference to user objects and instead rely on the
-fallback.
-This way users created via the framework and users created via winsync plugin
-behave the same way wrt password policies and no surprises will happen.
-
-Also in case we need to change the default password policy DN this will allow
-just code changes instead of having to change each user entry created, and
-distinguish between the default policy and explicit admin changes.
-
-Related: https://fedorahosted.org/freeipa/ticket/4085
-
-Patch backported/updated by Martin Kosek to accomodate different ipatests
-structure in ipa-3-3 branch.
----
- ipalib/plugins/user.py                             |  3 --
- ipatests/test_xmlrpc/test_attr.py                  |  2 --
- ipatests/test_xmlrpc/test_automember_plugin.py     |  4 ---
- ipatests/test_xmlrpc/test_group_plugin.py          |  4 ---
- ipatests/test_xmlrpc/test_krbtpolicy.py            |  2 --
- ipatests/test_xmlrpc/test_nesting.py               |  8 -----
- ipatests/test_xmlrpc/test_netgroup_plugin.py       |  4 ---
- ipatests/test_xmlrpc/test_range_plugin.py          |  2 --
- ipatests/test_xmlrpc/test_replace.py               |  2 --
- ipatests/test_xmlrpc/test_selinuxusermap_plugin.py |  5 ---
- ipatests/test_xmlrpc/test_user_plugin.py           | 40 ----------------------
- 11 files changed, 76 deletions(-)
-
-diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
-index 471981f48204209753eda2fb994d4c653dca0fa2..9b212005ef522920a86deacc8f9b3e658a088ec1 100644
---- a/ipalib/plugins/user.py
-+++ b/ipalib/plugins/user.py
-@@ -498,9 +498,6 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
-             homes_root = config.get('ipahomesrootdir', ['/home'])[0]
-             # build user's home directory based on his uid
-             entry_attrs['homedirectory'] = posixpath.join(homes_root, keys[-1])
--        entry_attrs.setdefault('krbpwdpolicyreference',
--                               DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
--                                  api.env.basedn))
-         entry_attrs.setdefault('krbprincipalname', '%s@%s' % (entry_attrs['uid'], api.env.realm))
- 
-         if entry_attrs.get('gidnumber') is None:
-diff --git a/ipatests/test_xmlrpc/test_attr.py b/ipatests/test_xmlrpc/test_attr.py
-index 118eabdeb5c8f6e86c0a9fc7dcdf9fc73a0a9ad2..a9e2956947109efcdcd132dff3807b7400d95a09 100644
---- a/ipatests/test_xmlrpc/test_attr.py
-+++ b/ipatests/test_xmlrpc/test_attr.py
-@@ -71,8 +71,6 @@ class test_attr(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_automember_plugin.py b/ipatests/test_xmlrpc/test_automember_plugin.py
-index 2c38b6463bfc684dbe23904f54b7107bb4ce3ff2..32fc59bac70d0f2e16d5d988835772f894bd78a9 100644
---- a/ipatests/test_xmlrpc/test_automember_plugin.py
-+++ b/ipatests/test_xmlrpc/test_automember_plugin.py
-@@ -812,8 +812,6 @@ class test_automember(Declarative):
-                     cn=[u'Michael Scott'],
-                     initials=[u'MS'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
--                                              api.env.basedn)],
-                     mepmanagedentry=[DN(('cn', manager1), ('cn', 'groups'), ('cn', 'accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'defaultgroup1', u'ipausers'],
-@@ -851,8 +849,6 @@ class test_automember(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
--                                              api.env.basedn)],
-                     mepmanagedentry=[DN(('cn', user1), ('cn', 'groups'), ('cn', 'accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'group1', u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py
-index be31af453bbd28d420c5e9f301bef6eb56388f61..9cc337db2a5f80abc960f5bc8a226372bf16b980 100644
---- a/ipatests/test_xmlrpc/test_group_plugin.py
-+++ b/ipatests/test_xmlrpc/test_group_plugin.py
-@@ -812,8 +812,6 @@ class test_group(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     dn=DN(('uid',user1),('cn','users'),('cn','accounts'),
-@@ -932,8 +930,6 @@ class test_group(Declarative):
-                     ipauniqueid=[fuzzy_uuid],
-                     dn=DN(('uid','tuser1'),('cn','users'),('cn','accounts'),
-                           api.env.basedn),
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-                     has_password=False,
-diff --git a/ipatests/test_xmlrpc/test_krbtpolicy.py b/ipatests/test_xmlrpc/test_krbtpolicy.py
-index 2fac11f1854037aa197f2df42c72a9d7ae947ccd..fb66e8a6ca72bee7dcfc595f3b89badc2608ca09 100644
---- a/ipatests/test_xmlrpc/test_krbtpolicy.py
-+++ b/ipatests/test_xmlrpc/test_krbtpolicy.py
-@@ -110,8 +110,6 @@ class test_krbtpolicy(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_nesting.py b/ipatests/test_xmlrpc/test_nesting.py
-index 850010b8797734406aa81a911a64bb1d051b7196..5be05688973f9ee39425f1bfc9cdedaa1a193c25 100644
---- a/ipatests/test_xmlrpc/test_nesting.py
-+++ b/ipatests/test_xmlrpc/test_nesting.py
-@@ -176,8 +176,6 @@ class test_nesting(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-@@ -214,8 +212,6 @@ class test_nesting(Declarative):
-                     cn=[u'Test User2'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user2),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-@@ -252,8 +248,6 @@ class test_nesting(Declarative):
-                     cn=[u'Test User3'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user3),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-@@ -290,8 +284,6 @@ class test_nesting(Declarative):
-                     cn=[u'Test User4'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user4),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_netgroup_plugin.py b/ipatests/test_xmlrpc/test_netgroup_plugin.py
-index 09241a7d691aeb7d967e549d14ff5d87a80b6a9b..15453bd3cfd45dce9be43cc5003b67a87a7915ac 100644
---- a/ipatests/test_xmlrpc/test_netgroup_plugin.py
-+++ b/ipatests/test_xmlrpc/test_netgroup_plugin.py
-@@ -288,8 +288,6 @@ class test_netgroup(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-@@ -325,8 +323,6 @@ class test_netgroup(Declarative):
-                     cn=[u'Test User2'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user2),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
-index df80e2fb72725c52d13be7a661364cbeafa3f84f..8c7b5f26e70283db62f18b152378d1b7d31bcc96 100644
---- a/ipatests/test_xmlrpc/test_range_plugin.py
-+++ b/ipatests/test_xmlrpc/test_range_plugin.py
-@@ -248,8 +248,6 @@ def tearDownClass(cls):
-                     initials=[u'TU'],
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_replace.py b/ipatests/test_xmlrpc/test_replace.py
-index 1b946b76cb9ecccc3452b3714d1647b0a09ec831..691918f5857827365323ed1d20835a15dd899a4f 100644
---- a/ipatests/test_xmlrpc/test_replace.py
-+++ b/ipatests/test_xmlrpc/test_replace.py
-@@ -66,8 +66,6 @@ class test_replace(Declarative):
-                     initials=[u'TU'],
-                     mail=[u'test1@example.com', u'test2@example.com'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),('cn','kerberos'),
--                                              api.env.basedn)],
-                     mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py b/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py
-index d1fedf1f0ff603a702089651db7f226ea58a98cd..9438bd01227c3ed0317976a38de8f67ec4ae425f 100644
---- a/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py
-+++ b/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py
-@@ -216,11 +216,6 @@ class test_selinuxusermap(Declarative):
-                     cn=[u'Test User1'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn', 'global_policy'),
--                                              ('cn', api.env.realm),
--                                              ('cn', 'kerberos'),
--                                              api.env.basedn)
--                                        ],
-                     mepmanagedentry=[DN(('cn', user1), ('cn', 'groups'),
-                         ('cn', 'accounts'), api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
-index 98e1965a4fbd3c2e77363495d0391be580bd0805..6a5ba50034fd2c9b63db63eeaa0061657574342d 100644
---- a/ipatests/test_xmlrpc/test_user_plugin.py
-+++ b/ipatests/test_xmlrpc/test_user_plugin.py
-@@ -125,8 +125,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -199,8 +197,6 @@ class test_user(Declarative):
-                         'gidnumber': [fuzzy_digits],
-                         'ipauniqueid': [fuzzy_uuid],
-                         'mepmanagedentry': [get_group_dn(user1)],
--                        'krbpwdpolicyreference': [DN(('cn','global_policy'),('cn',api.env.realm),
--                                                     ('cn','kerberos'),api.env.basedn)],
-                         'nsaccountlock': False,
-                         'has_keytab': False,
-                         'has_password': False,
-@@ -594,8 +590,6 @@ class test_user(Declarative):
-                     ipasshpubkey=[sshpubkey],
-                     sshpubkeyfp=[sshpubkeyfp],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -650,8 +644,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -687,8 +679,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user2)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -908,8 +898,6 @@ class test_user(Declarative):
-                     postalcode=[u'01234-5678'],
-                     telephonenumber=[u'410-555-1212'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -954,8 +942,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=True,
-@@ -1003,8 +989,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user2)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1075,8 +1059,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1148,8 +1130,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1210,8 +1190,6 @@ class test_user(Declarative):
-                     initials=[u'TU'],
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1273,8 +1251,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-                     has_password=False,
-@@ -1327,8 +1303,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[group1],
-                     has_keytab=False,
-                     has_password=False,
-@@ -1364,8 +1338,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[group1],
-                     has_keytab=False,
-                     has_password=False,
-@@ -1446,8 +1418,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[group1],
-                     nsaccountlock=False,
-                     has_keytab=False,
-@@ -1493,8 +1463,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user2, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     memberof_group=[group1],
-                     nsaccountlock=False,
-                     has_keytab=False,
-@@ -1553,8 +1521,6 @@ class test_user(Declarative):
-                     initials=[u'SA'],
-                     mail=[u'%s@%s' % (admin2, api.env.domain)],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(admin2)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1744,8 +1710,6 @@ class test_user(Declarative):
-                     cn=[u'Test User2'],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
--                                        api.env.basedn)],
-                     mepmanagedentry=[DN(('cn', user2), ('cn', 'groups'), ('cn', 'accounts'),
-                                         api.env.basedn)],
-                     memberof_group=[u'ipausers'],
-@@ -1780,8 +1744,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
-@@ -1828,8 +1790,6 @@ class test_user(Declarative):
-                     mail=[u'%s@%s' % (user1, api.env.domain)],
-                     initials=[u'TU'],
-                     ipauniqueid=[fuzzy_uuid],
--                    krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
--                                              ('cn','kerberos'),api.env.basedn)],
-                     mepmanagedentry=[get_group_dn(user1)],
-                     memberof_group=[u'ipausers'],
-                     has_keytab=False,
--- 
-1.8.4.2
-
diff --git a/SOURCES/0030-Fix-zonemgr-must-be-unicode-value.patch b/SOURCES/0030-Fix-zonemgr-must-be-unicode-value.patch
new file mode 100644
index 0000000..adbf8bb
--- /dev/null
+++ b/SOURCES/0030-Fix-zonemgr-must-be-unicode-value.patch
@@ -0,0 +1,30 @@
+From 969021984125c94b1058bf94681f295071849a22 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Thu, 13 Nov 2014 18:22:22 +0100
+Subject: [PATCH] Fix: zonemgr must be unicode value
+
+To support IDNA --zonemgr option must be unicode not ascii
+
+https://fedorahosted.org/freeipa/ticket/4724
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipaserver/install/bindinstance.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
+index 16894de0a009aacb123cf76072f2556aebc5722f..5bf784e62aec7c323a84fc5130e53c3deb86e6fd 100644
+--- a/ipaserver/install/bindinstance.py
++++ b/ipaserver/install/bindinstance.py
+@@ -403,6 +403,8 @@ def zonemgr_callback(option, opt_str, value, parser):
+     """
+     # validate the value first
+     try:
++        # IDNA support requires unicode
++        value = value.decode(sys.stdin.encoding)
+         validate_zonemgr_str(value)
+     except ValueError, e:
+         parser.error("invalid zonemgr: " + unicode(e))
+-- 
+2.1.0
+
diff --git a/SOURCES/0030-Increase-service-startup-timeout-default.patch b/SOURCES/0030-Increase-service-startup-timeout-default.patch
deleted file mode 100644
index e4790a7..0000000
--- a/SOURCES/0030-Increase-service-startup-timeout-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From b3d3abfa3adcfc8b1f5ea09e52a0bd8a519571e6 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Wed, 15 Jan 2014 09:41:15 +0100
-Subject: [PATCH 30/34] Increase service startup timeout default.
-
-https://fedorahosted.org/freeipa/ticket/4078
----
- ipalib/constants.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipalib/constants.py b/ipalib/constants.py
-index 79885a33a3008bd83908fc34a7340e78ab25e31f..6d4088be9a958eb5cb3b2725f8696fb4a7926e57 100644
---- a/ipalib/constants.py
-+++ b/ipalib/constants.py
-@@ -116,7 +116,7 @@
-     ('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),
-+    ('startup_timeout', 300),
- 
-     # Web Application mount points
-     ('mount_ipa', '/ipa/'),
--- 
-1.8.4.2
-
diff --git a/SOURCES/0031-Fix-warning-message-should-not-contain-CLI-commands.patch b/SOURCES/0031-Fix-warning-message-should-not-contain-CLI-commands.patch
new file mode 100644
index 0000000..38f504e
--- /dev/null
+++ b/SOURCES/0031-Fix-warning-message-should-not-contain-CLI-commands.patch
@@ -0,0 +1,73 @@
+From 22f830576d7d9f6585842818ea33379fd1674091 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Thu, 13 Nov 2014 14:02:02 +0100
+Subject: [PATCH] Fix warning message should not contain CLI commands
+
+Message is now universal for both CLI and WebUI
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4647
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipalib/messages.py                      | 4 ++--
+ ipalib/plugins/dns.py                   | 9 ++++-----
+ ipatests/test_xmlrpc/test_dns_plugin.py | 9 ++++++---
+ 3 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/ipalib/messages.py b/ipalib/messages.py
+index 5eeab3c54caf3a7318d89a4aeaee1357fceb787f..102e35275dbe37328c84ecb3cd5b2a8d8578056f 100644
+--- a/ipalib/messages.py
++++ b/ipalib/messages.py
+@@ -175,8 +175,8 @@ class OptionSemanticChangedWarning(PublicMessage):
+ 
+     errno = 13005
+     type = "warning"
+-    format = _(u"semantic of '%(option)s' option was changed: "
+-               u"%(current_behavior)s.\n%(hint)s")
++    format = _(u"Semantic of %(label)s was changed. %(current_behavior)s\n"
++               u"%(hint)s")
+ 
+ 
+ class DNSServerNotRespondingWarning(PublicMessage):
+diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
+index dd1e640f4062a32921bf1edf316e122b81a6d485..c5d96a8c4fcdf101254ecefb60cb83d63bee6310 100644
+--- a/ipalib/plugins/dns.py
++++ b/ipalib/plugins/dns.py
+@@ -2369,11 +2369,10 @@ class dnszone(DNSZoneBase):
+             messages.add_message(
+                 options['version'],
+                 result, messages.OptionSemanticChangedWarning(
+-                    option=u"--name-server",
+-                    current_behavior=_(u"the option is used only for "
+-                                       u"setting up the SOA MNAME attribute"),
+-                    hint=_(u"To edit NS record(s) in zone apex, use command "
+-                           u"'dnsrecord-mod [zone] @ --ns-rec=nameserver'.")
++                    label=_(u"setting Authoritative nameserver"),
++                    current_behavior=_(u"It is used only for setting the "
++                                       u"SOA MNAME attribute."),
++                    hint=_(u"NS record(s) can be edited in zone apex - '@'. ")
+                 )
+             )
+ 
+diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
+index a34d11a3278c67a3d00ca8f59bb8d8d19cf8a46e..fb53853147ecf663cf7015867131445f32364cfb 100644
+--- a/ipatests/test_xmlrpc/test_dns_plugin.py
++++ b/ipatests/test_xmlrpc/test_dns_plugin.py
+@@ -497,9 +497,12 @@ class test_dns(Declarative):
+                     'objectclass': objectclasses.dnszone,
+                 },
+                 'messages': (
+-                    {'message': u"semantic of '--name-server' option was changed: the option is used only for setting up"
+-                                u" the SOA MNAME attribute.\nTo edit NS record(s) in zone apex, use command "
+-                                u"'dnsrecord-mod [zone] @ --ns-rec=nameserver'.",
++                    {'message': u"Semantic of setting Authoritative nameserver "
++                                u"was changed. "
++                                u"It is used only for setting the SOA MNAME "
++                                u"attribute.\n"
++                                u"NS record(s) can be edited in zone "
++                                u"apex - '@'. ",
+                      'code': 13005,
+                      'type': u'warning',
+                      'name': u'OptionSemanticChangedWarning'},
+-- 
+2.1.0
+
diff --git a/SOURCES/0031-cli.print_attribute-Convert-values-to-strings.patch b/SOURCES/0031-cli.print_attribute-Convert-values-to-strings.patch
deleted file mode 100644
index 343a418..0000000
--- a/SOURCES/0031-cli.print_attribute-Convert-values-to-strings.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 32d3d38edfd47f3cc5425d3c2e7d42a38ea4a95b Mon Sep 17 00:00:00 2001
-From: Petr Viktorin <pviktori@redhat.com>
-Date: Tue, 26 Nov 2013 23:31:05 +0100
-Subject: [PATCH 31/34] cli.print_attribute: Convert values to strings
-
-When output_for_cli was called directly, rather than for values
-received through XML or JSON API, joining multiple values failed
-on non-strings such as DN objects.
-
-Convert output to strings before printing it out.
----
- ipalib/cli.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipalib/cli.py b/ipalib/cli.py
-index 5f02e929fe0df7051f4bb925a960678d780d4883..41e1b4752a2a549ea687632e60eb8003d0cad95f 100644
---- a/ipalib/cli.py
-+++ b/ipalib/cli.py
-@@ -293,7 +293,7 @@ def print_attribute(self, attr, value, format='%s: %s', indent=1, one_value_per_
-                     return
-                 else:
-                     if len(value) > 0:
--                        text = ', '.join(value)
-+                        text = ', '.join(str(v) for v in value)
-                     else:
-                         return
-                 line_len = self.get_tty_width()
--- 
-1.8.4.2
-
diff --git a/SOURCES/0032-Fix-wrong-expiration-date-on-renewed-IPA-CA-certific.patch b/SOURCES/0032-Fix-wrong-expiration-date-on-renewed-IPA-CA-certific.patch
new file mode 100644
index 0000000..c7805e0
--- /dev/null
+++ b/SOURCES/0032-Fix-wrong-expiration-date-on-renewed-IPA-CA-certific.patch
@@ -0,0 +1,54 @@
+From 6c7f71caf333363f8b4c18b3229de1533c1ad6fc Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 18 Nov 2014 14:01:59 +0000
+Subject: [PATCH] Fix wrong expiration date on renewed IPA CA certificates
+
+The expiration date was always set to the expiration date of the original
+certificate.
+
+https://fedorahosted.org/freeipa/ticket/4717
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ freeipa.spec.in                                     | 4 ++--
+ install/certmonger/dogtag-ipa-ca-renew-agent-submit | 2 ++
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/freeipa.spec.in b/freeipa.spec.in
+index be13e69255e7612f84aeca22105645b544cc50b5..e29f77de0db89035d15008c6be2da0ae7e96158a 100644
+--- a/freeipa.spec.in
++++ b/freeipa.spec.in
+@@ -140,7 +140,7 @@ Requires: python-dns >= 1.11.1
+ Requires: zip
+ Requires: policycoreutils >= 2.1.12-5
+ Requires: tar
+-Requires(pre): certmonger >= 0.75.13
++Requires(pre): certmonger >= 0.76.8
+ Requires(pre): 389-ds-base >= 1.3.3.5
+ Requires: fontawesome-fonts
+ Requires: open-sans-fonts
+@@ -221,7 +221,7 @@ Requires: wget
+ Requires: libcurl >= 7.21.7-2
+ Requires: xmlrpc-c >= 1.27.4
+ Requires: sssd >= 1.12.2
+-Requires: certmonger >= 0.75.6
++Requires: certmonger >= 0.76.8
+ Requires: nss-tools
+ Requires: bind-utils
+ Requires: oddjob-mkhomedir
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index e5ad9639b03b95e6e265214067a985f6c3ca0b2a..0a2cff148810e4800c02121afc68911c221d34d7 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -146,6 +146,8 @@ def request_cert():
+ 
+     path = paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT
+     args = [path] + sys.argv[1:]
++    if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert':
++        args += ['-O', 'bypassCAnotafter=true']
+     stdout, stderr, rc = ipautil.run(args, raiseonerr=False, env=os.environ)
+     sys.stderr.write(stderr)
+     sys.stderr.flush()
+-- 
+2.1.0
+
diff --git a/SOURCES/0032-group-show-resolve-external-members-of-the-groups.patch b/SOURCES/0032-group-show-resolve-external-members-of-the-groups.patch
deleted file mode 100644
index 609d8ba..0000000
--- a/SOURCES/0032-group-show-resolve-external-members-of-the-groups.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 2d1a85606d61128611f49101854bb8efe4abd638 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Thu, 16 Jan 2014 20:31:37 +0200
-Subject: [PATCH 32/34] group-show: resolve external members of the groups
-
-Perform SID to name conversion for existing external members of the
-groups if trust is configured.
-
-https://bugzilla.redhat.com/show_bug.cgi?id=1054391
-https://fedorahosted.org/freeipa/ticket/4123
----
- ipalib/plugins/group.py | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
-index 02eeb10ca2ca2a5710e88d6e3c11f1d1cdaa4a7b..dac55003e5a4291e8a3b7db58ae9b3c9c76e271e 100644
---- a/ipalib/plugins/group.py
-+++ b/ipalib/plugins/group.py
-@@ -387,6 +387,21 @@ def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **option
- class group_show(LDAPRetrieve):
-     __doc__ = _('Display information about a named group.')
-     has_output_params = LDAPRetrieve.has_output_params + (ipaexternalmember_param,)
-+    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
-+        assert isinstance(dn, DN)
-+        if ('ipaexternalmember' in entry_attrs and
-+            len(entry_attrs['ipaexternalmember']) > 0 and
-+            'trust_resolve' in self.Command and
-+            not options.get('raw', False)):
-+            sids = entry_attrs['ipaexternalmember']
-+            result = self.Command.trust_resolve(sids=sids)
-+            for entry in result['result']:
-+                try:
-+                    idx = sids.index(entry['sid'][0])
-+                    sids[idx] = entry['name'][0]
-+                except ValueError:
-+                    pass
-+        return dn
- api.register(group_show)
- 
- 
--- 
-1.8.4.2
-
diff --git a/SOURCES/0033-Do-not-restore-SELinux-settings-that-were-not-backed.patch b/SOURCES/0033-Do-not-restore-SELinux-settings-that-were-not-backed.patch
new file mode 100644
index 0000000..108f221
--- /dev/null
+++ b/SOURCES/0033-Do-not-restore-SELinux-settings-that-were-not-backed.patch
@@ -0,0 +1,43 @@
+From 449e333dbf4c803bb179e7d27f08666fd6e333af Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <pviktori@redhat.com>
+Date: Tue, 18 Nov 2014 10:40:31 +0100
+Subject: [PATCH] Do not restore SELinux settings that were not backed up
+
+https://fedorahosted.org/freeipa/ticket/4678
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipaplatform/base/tasks.py   | 3 ++-
+ ipaplatform/redhat/tasks.py | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
+index a6684d7653d6de8202a489edb1f7a38f4b344bbc..ab2c50332bce9f6eb95e2cb76aa6f7904b542765 100644
+--- a/ipaplatform/base/tasks.py
++++ b/ipaplatform/base/tasks.py
+@@ -146,7 +146,8 @@ class BaseTaskNamespace(object):
+ 
+         :param required_settings: A dictionary mapping the boolean names
+                                   to desired_values.
+-                                  The desired value can be 'on' or 'off'.
++                                  The desired value can be 'on' or 'off',
++                                  or None to leave the setting unchanged.
+ 
+         :param backup_func: A function called for each boolean with two
+                             arguments: the name and the previous value
+diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
+index 4977e1c7c496e36d56110bcdf040ab5c932d31a2..c01d8cf8b65b3d93ba204b3453f5c65d556723cf 100644
+--- a/ipaplatform/redhat/tasks.py
++++ b/ipaplatform/redhat/tasks.py
+@@ -366,6 +366,8 @@ class RedHatTaskNamespace(BaseTaskNamespace):
+         updated_vars = {}
+         failed_vars = {}
+         for setting, state in required_settings.iteritems():
++            if state is None:
++                continue
+             try:
+                 (stdout, stderr, rc) = ipautil.run([paths.GETSEBOOL, setting])
+                 original_state = stdout.split()[2]
+-- 
+2.1.0
+
diff --git a/SOURCES/0033-Remove-SID-resolve-call-from-Web-UI.patch b/SOURCES/0033-Remove-SID-resolve-call-from-Web-UI.patch
deleted file mode 100644
index 35fee47..0000000
--- a/SOURCES/0033-Remove-SID-resolve-call-from-Web-UI.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From ff15df8bd58bddd4c53644867f8ee340febdc198 Mon Sep 17 00:00:00 2001
-From: Petr Vobornik <pvoborni@redhat.com>
-Date: Mon, 20 Jan 2014 09:50:56 +0100
-Subject: [PATCH 33/34] Remove SID resolve call from Web UI
-
-- it's called in group-show
-
-https://bugzilla.redhat.com/show_bug.cgi?id=1054391
-https://fedorahosted.org/freeipa/ticket/4123
----
- install/ui/src/freeipa/association.js | 47 -----------------------------------
- install/ui/src/freeipa/group.js       |  1 -
- 2 files changed, 48 deletions(-)
-
-diff --git a/install/ui/src/freeipa/association.js b/install/ui/src/freeipa/association.js
-index ad427d66b6b98119b2eb577ae98e4b7c2f1a6932..8d81e495a153c06cdbcfa9917bdf04d70916f997 100644
---- a/install/ui/src/freeipa/association.js
-+++ b/install/ui/src/freeipa/association.js
-@@ -1455,53 +1455,6 @@ exp.attribute_facet = IPA.attribute_facet = function(spec, no_init) {
-     return that;
- };
- 
--IPA.sid_facet = function(spec, no_init) {
--
--    spec.name = spec.name || 'sid_facet';
--
--    var that = IPA.attribute_facet(spec, no_init);
--
--    that.load_records = function(value) {
--        var xlate = {};
--        var sidxlate_command = IPA.command({
--            entity: 'trust',
--            method: 'resolve',
--            options: {
--                sids: ''
--            }
--        });
--        sidxlate_command.on_success = function(data, text_status, xhr) {
--            for (var i=0; i< data.result.result.length; i++) {
--                var entry = data.result.result[i];
--                if (entry.sid[0] in xlate) {
--                    xlate[entry.sid[0]].resolve(entry.name[0]);
--                }
--            }
--        };
--        that.table.empty();
--
--        if (value.length === 0) return;
--
--        var sids = [];
--        for (var i=0; i< value.length; i++) {
--            var sid = value[i][that.attribute];
--            var deferred = new Deferred();
--            value[i][that.attribute] = {
--                promise: deferred.promise,
--                temp: sid
--            };
--            xlate[sid] = deferred;
--            sids.push(sid);
--            that.add_record(value[i]);
--        }
--        sidxlate_command.options.sids = sids;
--        sidxlate_command.execute();
--    };
--
--    return that;
--};
--
--
- IPA.attr_read_only_evaluator = function(spec) {
- 
-     spec.name = spec.name || 'attr_read_only_evaluator';
-diff --git a/install/ui/src/freeipa/group.js b/install/ui/src/freeipa/group.js
-index 5e8cdf991cdaf4f52e3f49dca431e999a72f2089..bb12d902fcba8228098b667aa6fbd3fa7daee34d 100644
---- a/install/ui/src/freeipa/group.js
-+++ b/install/ui/src/freeipa/group.js
-@@ -112,7 +112,6 @@ return {
-         },
-         {
-             $type: 'attribute',
--            $factory: IPA.sid_facet,
-             name: 'member_external',
-             attribute: 'ipaexternalmember',
-             tab_label: 'External',
--- 
-1.8.4.2
-
diff --git a/SOURCES/0034-Improve-otptoken-help-messages.patch b/SOURCES/0034-Improve-otptoken-help-messages.patch
new file mode 100644
index 0000000..3a6ca29
--- /dev/null
+++ b/SOURCES/0034-Improve-otptoken-help-messages.patch
@@ -0,0 +1,121 @@
+From 0d1c2e1039758c1c11fb60299f571013f3572842 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Thu, 6 Nov 2014 15:19:01 -0500
+Subject: [PATCH] Improve otptoken help messages
+
+https://fedorahosted.org/freeipa/ticket/4689
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipalib/plugins/otptoken.py | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
+index 2b5f1c5fb83341d392e165a3507f5076820f1d3a..77366bafe7a102f5d2c048ac3d5f7d9948ed7fe4 100644
+--- a/ipalib/plugins/otptoken.py
++++ b/ipalib/plugins/otptoken.py
+@@ -153,6 +153,7 @@ class otptoken(LDAPObject):
+         ),
+         StrEnum('type?',
+             label=_('Type'),
++            doc=_('Type of the token'),
+             default=u'totp',
+             autofill=True,
+             values=tuple(TOKEN_TYPES.keys() + [x.upper() for x in TOKEN_TYPES]),
+@@ -161,42 +162,52 @@ class otptoken(LDAPObject):
+         Str('description?',
+             cli_name='desc',
+             label=_('Description'),
++            doc=_('Token description (informational only)'),
+         ),
+         Str('ipatokenowner?',
+             cli_name='owner',
+             label=_('Owner'),
++            doc=_('Assigned user of the token (default: self)'),
+         ),
+         Str('managedby_user?',
+             label=_('Manager'),
++            doc=_('Assigned manager of the token (default: self)'),
+             flags=['no_create', 'no_update', 'no_search'],
+         ),
+         Bool('ipatokendisabled?',
+             cli_name='disabled',
+-            label=_('Disabled state')
++            label=_('Disabled'),
++            doc=_('Mark the token as disabled (default: false)')
+         ),
+         DateTime('ipatokennotbefore?',
+             cli_name='not_before',
+             label=_('Validity start'),
++            doc=_('First date/time the token can be used'),
+         ),
+         DateTime('ipatokennotafter?',
+             cli_name='not_after',
+             label=_('Validity end'),
++            doc=_('Last date/time the token can be used'),
+         ),
+         Str('ipatokenvendor?',
+             cli_name='vendor',
+             label=_('Vendor'),
++            doc=_('Token vendor name (informational only)'),
+         ),
+         Str('ipatokenmodel?',
+             cli_name='model',
+             label=_('Model'),
++            doc=_('Token model (informational only)'),
+         ),
+         Str('ipatokenserial?',
+             cli_name='serial',
+             label=_('Serial'),
++            doc=_('Token serial (informational only)'),
+         ),
+         OTPTokenKey('ipatokenotpkey?',
+             cli_name='key',
+             label=_('Key'),
++            doc=_('Token secret (Base32; default: random)'),
+             default_from=lambda: os.urandom(KEY_LENGTH),
+             autofill=True,
+             flags=('no_display', 'no_update', 'no_search'),
+@@ -204,6 +215,7 @@ class otptoken(LDAPObject):
+         StrEnum('ipatokenotpalgorithm?',
+             cli_name='algo',
+             label=_('Algorithm'),
++            doc=_('Token hash algorithm'),
+             default=u'sha1',
+             autofill=True,
+             flags=('no_update'),
+@@ -212,6 +224,7 @@ class otptoken(LDAPObject):
+         IntEnum('ipatokenotpdigits?',
+             cli_name='digits',
+             label=_('Digits'),
++            doc=_('Number of digits each token code will have'),
+             values=(6, 8),
+             default=6,
+             autofill=True,
+@@ -220,6 +233,7 @@ class otptoken(LDAPObject):
+         Int('ipatokentotpclockoffset?',
+             cli_name='offset',
+             label=_('Clock offset'),
++            doc=_('TOTP token / FreeIPA server time difference'),
+             default=0,
+             autofill=True,
+             flags=('no_update'),
+@@ -227,6 +241,7 @@ class otptoken(LDAPObject):
+         Int('ipatokentotptimestep?',
+             cli_name='interval',
+             label=_('Clock interval'),
++            doc=_('Length of TOTP token code validity'),
+             default=30,
+             autofill=True,
+             minvalue=5,
+@@ -235,6 +250,7 @@ class otptoken(LDAPObject):
+         Int('ipatokenhotpcounter?',
+             cli_name='counter',
+             label=_('Counter'),
++            doc=_('Initial counter for the HOTP token'),
+             default=0,
+             autofill=True,
+             minvalue=0,
+-- 
+2.1.0
+
diff --git a/SOURCES/0034-ipa-adtrust-install-configure-host-netbios-name-by-d.patch b/SOURCES/0034-ipa-adtrust-install-configure-host-netbios-name-by-d.patch
deleted file mode 100644
index f0ccd4a..0000000
--- a/SOURCES/0034-ipa-adtrust-install-configure-host-netbios-name-by-d.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From 7358fdd85215b9ee9becb2e352480abd2789691f Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Fri, 17 Jan 2014 14:09:34 +0200
-Subject: [PATCH 34/34] ipa-adtrust-install: configure host netbios name by
- default
-
-Ensure we set host netbios name by default in smb.conf
-
-https://fedorahosted.org/freeipa/ticket/4116
----
- install/share/smb.conf.template      | 1 +
- ipaserver/install/adtrustinstance.py | 3 +++
- 2 files changed, 4 insertions(+)
-
-diff --git a/install/share/smb.conf.template b/install/share/smb.conf.template
-index 086b0fcfe5cff2bc3582f2a89962a99c9095b4bb..2908b998cc85fcb84f60847135aaa4b008e121f8 100644
---- a/install/share/smb.conf.template
-+++ b/install/share/smb.conf.template
-@@ -1,5 +1,6 @@
- [global]
- workgroup = $NETBIOS_NAME
-+netbios name = $HOST_NETBIOS_NAME
- realm = $REALM
- kerberos method = dedicated keytab
- dedicated keytab file = FILE:/etc/samba/samba.keytab
-diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
-index 4aa8322e3e2cfb6fbc07696097c3e6e21fc7f665..621e3fd46780beb15f3d642cb9e3eb1c5fa721ad 100644
---- a/ipaserver/install/adtrustinstance.py
-+++ b/ipaserver/install/adtrustinstance.py
-@@ -124,6 +124,7 @@ def __init__(self, fstore=None):
-         self.secondary_rid_base = None
- 
-         self.fqdn = None
-+        self.host_netbios_name = None
-         self.realm = None
-         self.domain_name = None
- 
-@@ -151,6 +152,7 @@ def __setup_default_attributes(self):
- 
-         # Values obtained from API.env
-         self.fqdn = self.fqdn or api.env.host
-+        self.host_netbios_name = make_netbios_name(self.fqdn)
-         self.realm = self.realm or api.env.realm
-         self.domain_name = self.domain_name or api.env.domain
- 
-@@ -769,6 +771,7 @@ def __setup_sub_dict(self):
-         self.sub_dict = dict(REALM = self.realm,
-                              SUFFIX = self.suffix,
-                              NETBIOS_NAME = self.netbios_name,
-+                             HOST_NETBIOS_NAME = self.host_netbios_name,
-                              SMB_DN = self.smb_dn,
-                              LDAPI_SOCKET = self.ldapi_socket,
-                              FQDN = self.fqdn)
--- 
-1.8.4.2
-
diff --git a/SOURCES/0035-Ensure-users-exist-when-assigning-tokens-to-them.patch b/SOURCES/0035-Ensure-users-exist-when-assigning-tokens-to-them.patch
new file mode 100644
index 0000000..a19c17a
--- /dev/null
+++ b/SOURCES/0035-Ensure-users-exist-when-assigning-tokens-to-them.patch
@@ -0,0 +1,34 @@
+From 6e7474a1db6d49a4b07cd01663ec7f55df5225c4 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Fri, 24 Oct 2014 16:16:50 -0400
+Subject: [PATCH] Ensure users exist when assigning tokens to them
+
+https://fedorahosted.org/freeipa/ticket/4642
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/plugins/otptoken.py | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
+index 77366bafe7a102f5d2c048ac3d5f7d9948ed7fe4..f48feeee0502992f1b5fed4f342cace1c404624b 100644
+--- a/ipalib/plugins/otptoken.py
++++ b/ipalib/plugins/otptoken.py
+@@ -100,8 +100,11 @@ def _convert_owner(userobj, entry_attrs, options):
+ 
+ def _normalize_owner(userobj, entry_attrs):
+     owner = entry_attrs.get('ipatokenowner', None)
+-    if owner is not None:
+-        entry_attrs['ipatokenowner'] = userobj.get_dn(owner)
++    if owner:
++        try:
++            entry_attrs['ipatokenowner'] = userobj._normalize_manager(owner)[0]
++        except NotFound:
++            userobj.handle_not_found(owner)
+ 
+ def _check_interval(not_before, not_after):
+     if not_before and not_after:
+-- 
+2.1.0
+
diff --git a/SOURCES/0035-Remove-missing-VERSION-warning-in-dnsrecord-mod.patch b/SOURCES/0035-Remove-missing-VERSION-warning-in-dnsrecord-mod.patch
deleted file mode 100644
index 876fa45..0000000
--- a/SOURCES/0035-Remove-missing-VERSION-warning-in-dnsrecord-mod.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From a8cc1ff0dbf3de89b78c8d382779433658286750 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Fri, 17 Jan 2014 09:26:35 +0100
-Subject: [PATCH] Remove missing VERSION warning in dnsrecord-mod
-
-dnsrecord-mod may call dnsrecord-delentry command when all records
-are deleted. However, the version was not passwd to delentry and
-it resulted in a warning.
-
-https://fedorahosted.org/freeipa/ticket/4120
----
- ipalib/plugins/dns.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
-index 07523dc72466892f0e7d5fdd9261024d0e898548..94ae92ba5d1ae42e31ebb6100c743a2334f29e70 100644
---- a/ipalib/plugins/dns.py
-+++ b/ipalib/plugins/dns.py
-@@ -2636,7 +2636,7 @@ def execute(self, *keys, **options):
-                     break
- 
-             if del_all:
--                return self.obj.methods.delentry(*keys)
-+                return self.obj.methods.delentry(*keys, version=options['version'])
-         return result
- 
-     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
--- 
-1.8.4.2
-
diff --git a/SOURCES/0036-Enable-QR-code-display-by-default-in-otptoken-add.patch b/SOURCES/0036-Enable-QR-code-display-by-default-in-otptoken-add.patch
new file mode 100644
index 0000000..7a89d30
--- /dev/null
+++ b/SOURCES/0036-Enable-QR-code-display-by-default-in-otptoken-add.patch
@@ -0,0 +1,104 @@
+From 9adf96c47f37ee027cef03dc5bed49c2567ae75d Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Thu, 6 Nov 2014 15:30:13 -0500
+Subject: [PATCH] Enable QR code display by default in otptoken-add
+
+This is possible because python-qrcode's output now fits in a standard
+terminal. Also, update ipa-otp-import and otptoken-add-yubikey to
+disable QR code output as it doesn't make sense in these contexts.
+
+https://fedorahosted.org/freeipa/ticket/4703
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ API.txt                                  | 3 ++-
+ VERSION                                  | 4 ++--
+ ipalib/plugins/otptoken.py               | 5 +++--
+ ipalib/plugins/otptoken_yubikey.py       | 1 +
+ ipaserver/install/ipa_otptoken_import.py | 2 +-
+ 5 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/API.txt b/API.txt
+index 0000491d7a76fd1d2d50208d314d1600839ce295..2a63f1e2349f0df69433fa7cb742e269cd42d79f 100644
+--- a/API.txt
++++ b/API.txt
+@@ -2592,7 +2592,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
+ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+ output: PrimaryKey('value', None, None)
+ command: otptoken_add
+-args: 1,22,3
++args: 1,23,3
+ arg: Str('ipatokenuniqueid', attribute=True, cli_name='id', multivalue=False, primary_key=True, required=False)
+ option: Str('addattr*', cli_name='addattr', exclude='webui')
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+@@ -2611,6 +2611,7 @@ option: Int('ipatokentotpclockoffset', attribute=True, autofill=True, cli_name='
+ option: Int('ipatokentotptimestep', attribute=True, autofill=True, cli_name='interval', default=30, minvalue=5, multivalue=False, required=False)
+ option: Str('ipatokenvendor', attribute=True, cli_name='vendor', multivalue=False, required=False)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
++option: Flag('no_qrcode', autofill=True, default=False)
+ option: Flag('qrcode?', autofill=True, default=False)
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('setattr*', cli_name='setattr', exclude='webui')
+diff --git a/VERSION b/VERSION
+index 138648545c3cbe395303fa3cfa9dc99623b7e6c2..750b5058867ca5f073a083009c4aadeeb0240c35 100644
+--- a/VERSION
++++ b/VERSION
+@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
+ #                                                      #
+ ########################################################
+ IPA_API_VERSION_MAJOR=2
+-IPA_API_VERSION_MINOR=108
+-# Last change: pvoborni - manage authorization of keytab operations
++IPA_API_VERSION_MINOR=109
++# Last change: npmccallum - display qrcode by default
+diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
+index f48feeee0502992f1b5fed4f342cace1c404624b..f0850854f98e84e44acdcef311225220ac0129a3 100644
+--- a/ipalib/plugins/otptoken.py
++++ b/ipalib/plugins/otptoken.py
+@@ -268,7 +268,8 @@ class otptoken_add(LDAPCreate):
+     msg_summary = _('Added OTP token "%(value)s"')
+ 
+     takes_options = LDAPCreate.takes_options + (
+-        Flag('qrcode?', label=_('Display QR code')),
++        Flag('qrcode?', label=_('(deprecated)'), flags=('no_option')),
++        Flag('no_qrcode', label=_('Do not display QR code'), default=False),
+     )
+ 
+     has_output_params = LDAPCreate.has_output_params + (
+@@ -348,7 +349,7 @@ class otptoken_add(LDAPCreate):
+         rv = super(otptoken_add, self).output_for_cli(textui, output, *args, **options)
+ 
+         # Print QR code to terminal if specified
+-        if uri and options.get('qrcode', False):
++        if uri and not options.get('no_qrcode', False):
+             print "\n"
+             qr = qrcode.QRCode()
+             qr.add_data(uri)
+diff --git a/ipalib/plugins/otptoken_yubikey.py b/ipalib/plugins/otptoken_yubikey.py
+index e70ddb6e42b5ea34d7ebecb252d6bbd73ac64d03..7095887ac7cdf5d4b7d0d30edc6cab0222246664 100644
+--- a/ipalib/plugins/otptoken_yubikey.py
++++ b/ipalib/plugins/otptoken_yubikey.py
+@@ -124,6 +124,7 @@ class otptoken_add_yubikey(Command):
+                                                 ipatokenotpalgorithm=u'sha1',
+                                                 ipatokenhotpcounter=0,
+                                                 ipatokenotpkey=key,
++                                                no_qrcode=True,
+                                                 **options)
+ 
+         # Suppress values we don't want to return.
+diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
+index 31a6902014b8e3b2aafb3ba98a4190dc2059a3e7..b78aba93a2edc987450d921c87ea4f61b014b419 100644
+--- a/ipaserver/install/ipa_otptoken_import.py
++++ b/ipaserver/install/ipa_otptoken_import.py
+@@ -517,7 +517,7 @@ class OTPTokenImport(admintool.AdminTool):
+             # Parse tokens
+             for keypkg in self.doc.getKeyPackages():
+                 try:
+-                    api.Command.otptoken_add(keypkg.id, **keypkg.options)
++                    api.Command.otptoken_add(keypkg.id, no_qrcode=True, **keypkg.options)
+                 except Exception as e:
+                     self.log.warn("Error adding token: %s", e)
+                 else:
+-- 
+2.1.0
+
diff --git a/SOURCES/0036-Hide-trust-resolve-command.patch b/SOURCES/0036-Hide-trust-resolve-command.patch
deleted file mode 100644
index 3e8c387..0000000
--- a/SOURCES/0036-Hide-trust-resolve-command.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 94888d83efbbd3b3ddf194e35d4d10f03bb47bb2 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Fri, 17 Jan 2014 16:13:17 +0100
-Subject: [PATCH] Hide trust-resolve command
-
-We do not need to expose a public FreeIPA specific interface to resolve
-SIDs to names. The interface is only used internally to resolve SIDs
-when external group members are listed. Additionally, the command interface
-is not prepared for regular user and can give rather confusing results.
-
-Hide it from CLI. The API itself is still accessible and compatible with
-older clients.
-
-https://fedorahosted.org/freeipa/ticket/4113
----
- ipalib/plugins/trust.py | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 3d412c9c9f518347769e88ddc9089d6d92ccc4be..0b6db27c696cd169c8f4b33128520961c20e3015 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -978,6 +978,7 @@ def idmap_type_string(level):
-         return unicode(string)
- 
- class trust_resolve(Command):
-+    NO_CLI = True
-     __doc__ = _('Resolve security identifiers of users and groups in trusted domains')
- 
-     takes_options = (
--- 
-1.8.4.2
-
diff --git a/SOURCES/0037-Show-warning-instead-of-error-if-CA-did-not-start.patch b/SOURCES/0037-Show-warning-instead-of-error-if-CA-did-not-start.patch
new file mode 100644
index 0000000..d70a544
--- /dev/null
+++ b/SOURCES/0037-Show-warning-instead-of-error-if-CA-did-not-start.patch
@@ -0,0 +1,32 @@
+From 2e974ebf99737504f01feb2cbb85d3acbc2a15d6 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Tue, 18 Nov 2014 18:30:59 +0100
+Subject: [PATCH] Show warning instead of error if CA did not start
+
+This is just workaround, checking if CA is working raises false positive
+exception during upgrade
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4676
+Reviewed-By: Simo Sorce <ssorce@redhat.com>
+---
+ install/tools/ipa-upgradeconfig | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index 6556d8f313d3a9efeb32d4cba97cb82796459652..3484f8e8768fe05dddb08e9a40e58d8ad9c2e1e7 100644
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -1457,6 +1457,10 @@ def main():
+             ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME)
+         except ipautil.CalledProcessError, e:
+             root_logger.error("Failed to restart %s: %s", ca.service_name, e)
++        # FIXME https://fedorahosted.org/freeipa/ticket/4676
++        # workaround
++        except RuntimeError as e:
++            root_logger.warning(str(e))
+ 
+     set_sssd_domain_option('ipa_server_mode', 'True')
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0037-Trust-domains-Web-UI.patch b/SOURCES/0037-Trust-domains-Web-UI.patch
deleted file mode 100644
index a7b76fb..0000000
--- a/SOURCES/0037-Trust-domains-Web-UI.patch
+++ /dev/null
@@ -1,188 +0,0 @@
-From 8dcaa8f17b94fd7056340622e49d8ab505694603 Mon Sep 17 00:00:00 2001
-From: Petr Vobornik <pvoborni@redhat.com>
-Date: Wed, 15 Jan 2014 18:01:02 +0100
-Subject: [PATCH] Trust domains Web UI
-
-Add Web UI counterpart of following CLI commands:
-
-* trust-fetch-domains Refresh list of the domains associated with the trust
-* trustdomain-del Remove infromation about the domain associated with the trust.
-* trustdomain-disable Disable use of IPA resources by the domain of the trust
-* trustdomain-enable Allow use of IPA resources by the domain of the trust
-* trustdomain-find Search domains of the trust
-
-https://fedorahosted.org/freeipa/ticket/4119
----
- install/ui/src/freeipa/search.js   | 11 +++---
- install/ui/src/freeipa/trust.js    | 68 ++++++++++++++++++++++++++++++++++++++
- install/ui/test/data/ipa_init.json |  1 +
- ipalib/plugins/internal.py         |  1 +
- 4 files changed, 77 insertions(+), 4 deletions(-)
-
-diff --git a/install/ui/src/freeipa/search.js b/install/ui/src/freeipa/search.js
-index c2e678a35e7d7d5179c1b766eea88599710593c3..3f7fdf9b1e6716c73e0657dc678abe332f6fc8c0 100644
---- a/install/ui/src/freeipa/search.js
-+++ b/install/ui/src/freeipa/search.js
-@@ -470,20 +470,23 @@ IPA.batch_items_action = function(spec) {
-     that.execute_action = function(facet, on_success, on_error) {
- 
-         var entity = facet.managed_entity;
--        var pkeys = facet.get_selected_values();
-+        var selected_keys = facet.get_selected_values();
-+        var pkeys = facet.get_pkeys();
-+        if (!pkeys[0]) pkeys = []; // correction for search facet
- 
-         that.batch = IPA.batch_command({
-             name: entity.name + '_batch_'+ that.method,
-             on_success: that.get_on_success(facet, on_success)
-         });
- 
--        for (var i=0; i<pkeys.length; i++) {
--            var pkey = pkeys[i];
-+        for (var i=0; i<selected_keys.length; i++) {
-+            var item_keys = pkeys.splice(0);
-+            item_keys.push(selected_keys[i]);
- 
-             var command = IPA.command({
-                 entity: entity.name,
-                 method: that.method,
--                args: [pkey]
-+                args: item_keys
-             });
- 
-             that.batch.add_command(command);
-diff --git a/install/ui/src/freeipa/trust.js b/install/ui/src/freeipa/trust.js
-index 2653d3e67c2c5591f000e32c43a3a5878eef28fd..51f2000b47fd7943cb9a200c9bec7ebd3459178a 100644
---- a/install/ui/src/freeipa/trust.js
-+++ b/install/ui/src/freeipa/trust.js
-@@ -48,6 +48,7 @@ return {
-             dest_facet: 'search'
-         }
-     ],
-+    facet_groups: [ 'settings', 'trustdomain' ],
-     facets: [
-         {
-             $type: 'search',
-@@ -56,6 +57,63 @@ return {
-             ]
-         },
-         {
-+            $type: 'nested_search',
-+            $pre_ops: [
-+                // trustdomain-add is hidden, remove add button
-+                { $del: [[ 'control_buttons', [{ name: 'add'}] ]] }
-+            ],
-+            nested_entity: 'trustdomain',
-+            facet_group: 'trustdomain',
-+            name: 'domains',
-+            label: '@mo:trustdomain.label',
-+            tab_label: '@mo:trustdomain.label',
-+            search_all_entries: true,
-+            actions: [
-+                {
-+                    $type: 'batch_disable'
-+                },
-+                {
-+                    $type: 'batch_enable'
-+                },
-+                {
-+                    $type: 'object',
-+                    name: 'fetch',
-+                    label: '@i18n:objects.trust.fetch_domains',
-+                    method: 'fetch_domains'
-+                }
-+            ],
-+            control_buttons: [
-+                {
-+                    name: 'disable',
-+                    label: '@i18n:buttons.disable',
-+                    icon: 'fa-minus'
-+                },
-+                {
-+                    name: 'enable',
-+                    label: '@i18n:buttons.enable',
-+                    icon: 'fa-check'
-+                },
-+                {
-+                    name: 'fetch',
-+                    label: '@i18n:objects.trust.fetch_domains',
-+                    icon: 'fa-download'
-+                }
-+            ],
-+            columns: [
-+                {
-+                    name: 'cn',
-+                    link: false
-+                },
-+                {
-+                    name: 'domain_enabled',
-+                    label: '@i18n:status.label',
-+                    formatter: 'boolean_status'
-+                },
-+                'ipantflatname',
-+                'ipanttrusteddomainsid'
-+            ]
-+        },
-+        {
-             $type: 'details',
-             sections: [
-                 {
-@@ -261,6 +319,13 @@ IPA.trust.adder_dialog = function(spec) {
-     return that;
- };
- 
-+
-+var make_trustdomain_spec = function() {
-+return {
-+    name: 'trustdomain',
-+    containing_entity: 'trust'
-+};};
-+
- var make_trustconfig_spec = function() {
- return {
-     name: 'trustconfig',
-@@ -349,14 +414,17 @@ exp.remove_menu_item = function() {
- };
- 
- exp.trust_spec = make_trust_spec();
-+exp.trustdomain_spec = make_trustdomain_spec();
- exp.trustconfig_spec = make_trustconfig_spec();
- 
-+
- IPA.trust.register = function() {
-     var e = reg.entity;
-     var w = reg.widget;
-     var f = reg.field;
- 
-     e.register({type: 'trust', spec: exp.trust_spec});
-+    e.register({type: 'trustdomain', spec: exp.trustdomain_spec});
-     e.register({type: 'trustconfig', spec: exp.trustconfig_spec});
- 
-     w.register('trust_fallbackgroup_select', IPA.trust.fallbackgroup_select_widget);
-diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
-index 8e0b2a33cc45d2a68878b7f3ab49b1491ae7c3f5..80a1c08ed3745bdce44676c6f2716e207f653e8d 100644
---- a/install/ui/test/data/ipa_init.json
-+++ b/install/ui/test/data/ipa_init.json
-@@ -464,6 +464,7 @@
-                             "details": "Trust Settings",
-                             "domain": "Domain",
-                             "establish_using": "Establish using",
-+                            "fetch_domains": "Fetch domains",
-                             "ipantflatname": "Domain NetBIOS name",
-                             "ipanttrusteddomainsid": "Domain Security Identifier",
-                             "preshared_password": "Pre-shared password",
-diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
-index 83b505dae1c6349097f7ad5ed20ab25b5a262aa8..dbd40f91ef2b84beb1bb521dcbcdb059cd3b3c7e 100644
---- a/ipalib/plugins/internal.py
-+++ b/ipalib/plugins/internal.py
-@@ -600,6 +600,7 @@ class i18n_messages(Command):
-                 "details": _("Trust Settings"),
-                 "domain": _("Domain"),
-                 "establish_using": _("Establish using"),
-+                "fetch_domains": _("Fetch domains"),
-                 "ipantflatname": _("Domain NetBIOS name"),
-                 "ipanttrusteddomainsid": _("Domain Security Identifier"),
-                 "preshared_password": _("Pre-shared password"),
--- 
-1.8.4.2
-
diff --git a/SOURCES/0038-ipasam-delete-trusted-child-domains-before-removing-.patch b/SOURCES/0038-ipasam-delete-trusted-child-domains-before-removing-.patch
deleted file mode 100644
index eb13168..0000000
--- a/SOURCES/0038-ipasam-delete-trusted-child-domains-before-removing-.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From 706617eee0f735d2a49fd41f5c86e8b22bbf5434 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Mon, 20 Jan 2014 16:42:48 +0200
-Subject: [PATCH] ipasam: delete trusted child domains before removing the
- trust
-
-LDAP protocol doesn't allow deleting non-leaf entries. One needs to
-remove all leaves first before removing the tree node.
-
-https://fedorahosted.org/freeipa/ticket/4126
----
- daemons/ipa-sam/ipa_sam.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 44 insertions(+), 1 deletion(-)
-
-diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
-index 674085d2a14c67359df16458dbbb098414a24d8b..1ca504db4e442c834ebe44d7e3503abafd6f9602 100644
---- a/daemons/ipa-sam/ipa_sam.c
-+++ b/daemons/ipa-sam/ipa_sam.c
-@@ -2437,6 +2437,44 @@ done:
- 	return status;
- }
- 
-+static int delete_subtree(struct ldapsam_privates *ldap_state, char* dn)
-+{
-+	LDAP *state = priv2ld(ldap_state);
-+	int rc;
-+	char *filter = NULL;
-+	int scope = LDAP_SCOPE_SUBTREE;
-+	LDAPMessage *result = NULL;
-+	LDAPMessage *entry = NULL;
-+	char *entry_dn = NULL;
-+
-+	/* use 'dn' for a temporary talloc context */
-+	filter = talloc_asprintf(dn, "(objectClass=*)");
-+	if (filter == NULL) {
-+		return LDAP_NO_MEMORY;
-+	}
-+
-+	rc = smbldap_search(ldap_state->smbldap_state, dn, scope, filter, NULL, 0, &result);
-+	TALLOC_FREE(filter);
-+
-+	if (result != NULL) {
-+		smbldap_talloc_autofree_ldapmsg(dn, result);
-+	}
-+
-+	for (entry = ldap_first_entry(state, result);
-+	     entry != NULL;
-+	     entry = ldap_next_entry(state, entry)) {
-+		entry_dn = get_dn(dn, state, entry);
-+		/* remove child entries */
-+		if ((entry_dn != NULL) && (strcmp(entry_dn, dn) != 0)) {
-+			rc = smbldap_delete(ldap_state->smbldap_state, entry_dn);
-+		}
-+	}
-+	rc = smbldap_delete(ldap_state->smbldap_state, dn);
-+
-+	/* caller will destroy dn */
-+	return rc;
-+}
-+
- static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
- 					   const char *domain)
- {
-@@ -2444,7 +2482,7 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
- 	struct ldapsam_privates *ldap_state =
- 		(struct ldapsam_privates *)methods->private_data;
- 	LDAPMessage *entry = NULL;
--	const char *dn;
-+	char *dn;
- 	const char *domain_name;
- 	TALLOC_CTX *tmp_ctx;
- 	NTSTATUS status;
-@@ -2490,6 +2528,11 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
- 	}
- 
- 	ret = smbldap_delete(ldap_state->smbldap_state, dn);
-+	if (ret == LDAP_NOT_ALLOWED_ON_NONLEAF) {
-+		/* delete_subtree will use 'dn' as temporary context too */
-+		ret = delete_subtree(ldap_state, dn);
-+	}
-+
- 	if (ret != LDAP_SUCCESS) {
- 		status = NT_STATUS_UNSUCCESSFUL;
- 		goto done;
--- 
-1.8.4.2
-
diff --git a/SOURCES/0038-webui-fix-potential-XSS-vulnerabilities.patch b/SOURCES/0038-webui-fix-potential-XSS-vulnerabilities.patch
new file mode 100644
index 0000000..f6c78d2
--- /dev/null
+++ b/SOURCES/0038-webui-fix-potential-XSS-vulnerabilities.patch
@@ -0,0 +1,131 @@
+From a1d4f412181423cb3883650e033b9fb5b415bd83 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 10 Nov 2014 16:24:15 +0100
+Subject: [PATCH] webui: fix potential XSS vulnerabilities
+
+Escape user defined text to prevent XSS attacks. Extra precaution was taken
+to escape also parts which are unlikely to contain user-defined text.
+
+fixes CVE-2014-7850
+
+https://fedorahosted.org/freeipa/ticket/4742
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/ui/src/freeipa/Application_controller.js |  4 ++--
+ install/ui/src/freeipa/facet.js                  | 12 +++++++-----
+ install/ui/src/freeipa/ipa.js                    |  1 +
+ install/ui/src/freeipa/rule.js                   |  2 +-
+ install/ui/src/freeipa/widget.js                 |  4 ++--
+ 5 files changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/install/ui/src/freeipa/Application_controller.js b/install/ui/src/freeipa/Application_controller.js
+index 094bd3da7c4806a316ebe2589b98a523410f4a5f..4bf76f8f56a8e34e330c35956b8922cc3c8f79e3 100644
+--- a/install/ui/src/freeipa/Application_controller.js
++++ b/install/ui/src/freeipa/Application_controller.js
+@@ -252,12 +252,12 @@ define([
+             var error_container = $('<div/>', {
+                 'class': 'container facet-content facet-error'
+             }).appendTo($('.app-container .content').empty());
+-            error_container.append('<h1>'+name+'</h1>');
++            error_container.append($('<h1/>', { text: name }));
+             var details = $('<div/>', {
+                 'class': 'error-details'
+             }).appendTo(error_container);
+ 
+-            details.append('<p> Web UI got in unrecoverable state during "'+error.phase+'" phase.</p>');
++            details.append($('<p/>', { text: 'Web UI got in unrecoverable state during "' + error.phase + '" phase' }));
+             if (error.name) window.console.error(error.name);
+             if (error.results) {
+                 var msg = error.results.message;
+diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js
+index 43627d9d531ed700ff780a0773451eaf17b1cbdd..b0121c75fd584988883a3b5f7d1665a985a321fd 100644
+--- a/install/ui/src/freeipa/facet.js
++++ b/install/ui/src/freeipa/facet.js
+@@ -895,12 +895,12 @@ exp.facet = IPA.facet = function(spec, no_init) {
+         title = title.replace('${error}', error_thrown.name);
+ 
+         that.error_container.empty();
+-        that.error_container.append('<h1>'+title+'</h1>');
++        that.error_container.append($('<h1/>', { text: title }));
+ 
+         var details = $('<div/>', {
+             'class': 'error-details'
+         }).appendTo(that.error_container);
+-        details.append('<p>'+error_thrown.message+'</p>');
++        details.append($('<p/>', { text: error_thrown.message }));
+ 
+         $('<div/>', {
+             text: text.get('@i18n:error_report.options')
+@@ -932,7 +932,9 @@ exp.facet = IPA.facet = function(spec, no_init) {
+             }
+         );
+ 
+-        that.error_container.append('<p>'+text.get('@i18n:error_report.problem_persists')+'</p>');
++        that.error_container.append($('<p/>', {
++            text: text.get('@i18n:error_report.problem_persists')
++        }));
+ 
+         that.show_error();
+     };
+@@ -1214,7 +1216,7 @@ exp.facet_header = IPA.facet_header = function(spec) {
+                 click: item.handler
+             }).appendTo(bc_item);
+         } else {
+-            bc_item.append(item.text);
++            bc_item.text(item.text);
+         }
+         return bc_item;
+     };
+@@ -1823,7 +1825,7 @@ exp.table_facet = IPA.table_facet = function(spec, no_init) {
+             function(xhr, text_status, error_thrown) {
+                 that.load_records([]);
+                 var summary = that.table.summary.empty();
+-                summary.append(error_thrown.name+': '+error_thrown.message);
++                summary.text(error_thrown.name+': '+error_thrown.message);
+             }
+         );
+     };
+diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js
+index 6d3aeaaaaca11dfdaf20935e5c9084c9ed106e6c..137f11e832ff8d0b6dd1b50060f8537c7b117616 100644
+--- a/install/ui/src/freeipa/ipa.js
++++ b/install/ui/src/freeipa/ipa.js
+@@ -1133,6 +1133,7 @@ IPA.notify = function(message, type, timeout) {
+ 
+     if (typeof message === 'string') {
+         message = text.get(message);
++        message = document.createTextNode(message);
+     }
+ 
+     var notification_area = $('#notification .notification-area');
+diff --git a/install/ui/src/freeipa/rule.js b/install/ui/src/freeipa/rule.js
+index 8a2b01963b74e1892ac15127ae0050b35fe6ac27..706827190261efda136f6d1489bdb13543c00f7a 100644
+--- a/install/ui/src/freeipa/rule.js
++++ b/install/ui/src/freeipa/rule.js
+@@ -91,7 +91,7 @@ IPA.rule_radio_widget = function(spec) {
+         var param_info = IPA.get_entity_param(that.entity.name, that.name);
+         var title = param_info ? param_info.doc : that.name;
+ 
+-        container.append(title + ': ');
++        container.append(document.createTextNode(title + ': '));
+         that.widget_create(container);
+         that.owb_create(container);
+         if (that.undo) {
+diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
+index 9240df8ef5402310ec9ceafd0b766def10c8cb48..1ef1a2bf22b735edcfcca44cfc1e69bc8d36a740 100644
+--- a/install/ui/src/freeipa/widget.js
++++ b/install/ui/src/freeipa/widget.js
+@@ -4166,8 +4166,8 @@ IPA.link_widget = function(spec) {
+ 
+         that.values = util.normalize_value(values);
+         that.value = that.values.slice(-1)[0] || '';
+-        that.link.html(that.value);
+-        that.nonlink.html(that.value);
++        that.link.text(that.value);
++        that.nonlink.text(that.value);
+         that.update_link();
+         that.check_entity_link();
+         that.on_value_changed(values);
+-- 
+2.1.0
+
diff --git a/SOURCES/0039-CLDAP-generate-NetBIOS-name-like-ipa-adtrust-install.patch b/SOURCES/0039-CLDAP-generate-NetBIOS-name-like-ipa-adtrust-install.patch
deleted file mode 100644
index 7bcceae..0000000
--- a/SOURCES/0039-CLDAP-generate-NetBIOS-name-like-ipa-adtrust-install.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-From c57ff0a9aae8e51de1de8671dc6c8d91a1f1af66 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 23 Jan 2014 14:39:24 +0100
-Subject: [PATCH] CLDAP: generate NetBIOS name like ipa-adtrust-install does
-
-Fixes  https://fedorahosted.org/freeipa/ticket/4116
----
- daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h    |  2 +
- .../ipa-cldap/ipa_cldap_netlogon.c                 | 47 +++++++++++++++-------
- 2 files changed, 35 insertions(+), 14 deletions(-)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-index 3f420ff2c5acc7bd75bff7f042f76b9c61144461..5e963e3f8557d468d646e6343366921d17242e2d 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap.h
-@@ -51,6 +51,7 @@
- #include <stdlib.h>
- #include <pthread.h>
- #include <dirsrv/slapi-plugin.h>
-+#include <talloc.h>
- #include "util.h"
- 
- #define IPA_CLDAP_PLUGIN_NAME "CLDAP Server"
-@@ -106,4 +107,5 @@ int ipa_cldap_netlogon(struct ipa_cldap_ctx *ctx,
-                        struct ipa_cldap_req *req,
-                        struct berval *reply);
- 
-+char *make_netbios_name(TALLOC_CTX *mem_ctx, const char *s);
- #endif /* _IPA_CLDAP_H_ */
-diff --git a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-index c03172d474589ddee84f1cfa5395c23fdba83bcb..1d16de7be09cf9675c2ee1a602ddfb800cd6e7af 100644
---- a/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-+++ b/daemons/ipa-slapi-plugins/ipa-cldap/ipa_cldap_netlogon.c
-@@ -121,6 +121,38 @@ done:
-     return ret;
- }
- 
-+char *make_netbios_name(TALLOC_CTX *mem_ctx, const char *s)
-+{
-+    char *nb_name;
-+    const char *p;
-+    size_t c = 0;
-+
-+    if (s == NULL) {
-+        return NULL;
-+    }
-+
-+    nb_name = talloc_zero_size(mem_ctx, NETBIOS_NAME_MAX + 1);
-+    if (nb_name == NULL) {
-+        return NULL;
-+    }
-+
-+    for (p = s; *p && c < NETBIOS_NAME_MAX; p++) {
-+        /* Create the NetBIOS name from the first segment of the hostname */
-+        if (*p == '.') {
-+            break;
-+        } else if (isalnum(*p)) {
-+            nb_name[c++] = toupper(*p);
-+        }
-+    }
-+
-+    if (*nb_name == '\0') {
-+        talloc_free(nb_name);
-+        return NULL;
-+    }
-+
-+    return nb_name;
-+}
-+
- #define NETLOGON_SAM_LOGON_RESPONSE_EX_pusher \
-             (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX
- 
-@@ -131,8 +163,6 @@ static int ipa_cldap_encode_netlogon(char *fq_hostname, char *domain,
-     struct NETLOGON_SAM_LOGON_RESPONSE_EX *nlr;
-     enum ndr_err_code ndr_err;
-     DATA_BLOB blob;
--    char *pdc_name;
--    char *p;
-     int ret;
- 
-     nlr = talloc_zero(NULL, struct NETLOGON_SAM_LOGON_RESPONSE_EX);
-@@ -162,18 +192,7 @@ static int ipa_cldap_encode_netlogon(char *fq_hostname, char *domain,
-     nlr->pdc_dns_name = fq_hostname;
-     nlr->domain_name = name;
- 
--    /* copy the first 15 characters of the fully qualified hostname*/
--    pdc_name = talloc_asprintf(nlr, "%.*s", NETBIOS_NAME_MAX, fq_hostname);
--
--    for (p = pdc_name; *p; p++) {
--        /* Create the NetBIOS name from the first segment of the hostname */
--        if (*p == '.') {
--            *p = '\0';
--            break;
--        }
--        *p = toupper(*p);
--    }
--    nlr->pdc_name = pdc_name;
-+    nlr->pdc_name = make_netbios_name(nlr, fq_hostname);
-     nlr->user_name = "";
-     nlr->server_site = "Default-First-Site-Name";
-     nlr->client_site = "Default-First-Site-Name";
--- 
-1.8.3.1
-
diff --git a/SOURCES/0039-Raise-right-exception-if-domain-name-is-not-valid.patch b/SOURCES/0039-Raise-right-exception-if-domain-name-is-not-valid.patch
new file mode 100644
index 0000000..2714868
--- /dev/null
+++ b/SOURCES/0039-Raise-right-exception-if-domain-name-is-not-valid.patch
@@ -0,0 +1,46 @@
+From e2f285e7c63a8ff9f2c049ee3a058b6e281352a8 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Wed, 19 Nov 2014 14:51:20 +0100
+Subject: [PATCH] Raise right exception if domain name is not valid
+
+Because of dnspython implementation, in some cases UnicodeError is
+raised instead of DNS SyntaxError
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4734
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipapython/dnsutil.py | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
+index d7841fe2548dd100d51e60ea11bc6e468f3475cf..f08cddad959658a11623a31cb591655f1a5fdabf 100644
+--- a/ipapython/dnsutil.py
++++ b/ipapython/dnsutil.py
+@@ -26,15 +26,16 @@ class DNSName(dns.name.Name):
+     labels = None  # make pylint happy
+ 
+     def __init__(self, labels, origin=None):
+-        if isinstance(labels, str):
+-            #pylint: disable=E1101
+-            labels = dns.name.from_text(labels, origin).labels
+-        elif isinstance(labels, unicode):
+-            #pylint: disable=E1101
+-            labels = dns.name.from_unicode(labels, origin).labels
+-        elif isinstance(labels, dns.name.Name):
+-            labels = labels.labels
+         try:
++            if isinstance(labels, str):
++                #pylint: disable=E1101
++                labels = dns.name.from_text(labels, origin).labels
++            elif isinstance(labels, unicode):
++                #pylint: disable=E1101
++                labels = dns.name.from_unicode(labels, origin).labels
++            elif isinstance(labels, dns.name.Name):
++                labels = labels.labels
++
+             super(DNSName, self).__init__(labels)
+         except UnicodeError, e:
+             # dnspython bug, an invalid domain name returns the UnicodeError
+-- 
+2.1.0
+
diff --git a/SOURCES/0040-Fallback-to-global-policy-in-ipa-lockout-plugin.patch b/SOURCES/0040-Fallback-to-global-policy-in-ipa-lockout-plugin.patch
deleted file mode 100644
index 5483f37..0000000
--- a/SOURCES/0040-Fallback-to-global-policy-in-ipa-lockout-plugin.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 2392ccb4ff9f0310512a6313240749900567d831 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Thu, 30 Jan 2014 16:58:25 +0100
-Subject: [PATCH] Fallback to global policy in ipa-lockout plugin
-
-krbPwdPolicyReference is no longer filled default users. Instead, plugins
-fallback to hardcoded global policy reference.
-
-Fix ipa-lockout plugin to fallback to it instead of failing to apply
-the policy.
-
-https://fedorahosted.org/freeipa/ticket/4085
----
- .../ipa-slapi-plugins/ipa-lockout/ipa_lockout.c    | 34 ++++++++++++++++++++++
- 1 file changed, 34 insertions(+)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-index fd6602fdee9b2fd95c154fd512fcba4f37e56bad..5a24359d319aaea28773daa01d268d2d46583270 100644
---- a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-+++ b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-@@ -49,6 +49,7 @@
- #include <time.h>
- #include "slapi-plugin.h"
- #include "nspr.h"
-+#include <krb5.h>
- 
- #include "util.h"
- 
-@@ -81,6 +82,8 @@ static int g_plugin_started = 0;
- 
- static struct ipa_context *global_ipactx = NULL;
- 
-+static char *ipa_global_policy = NULL;
-+
- #define GENERALIZED_TIME_LENGTH 15
- 
- /**
-@@ -142,8 +145,11 @@ ipalockout_get_global_config(struct ipa_context *ipactx)
-     Slapi_Attr *attr = NULL;
-     char *dn = NULL;
-     char *basedn = NULL;
-+    char *realm = NULL;
-     Slapi_DN *sdn;
-     Slapi_Entry *config_entry;
-+    krb5_context krbctx = NULL;
-+    krb5_error_code krberr;
-     int ret;
- 
-     /* Get cn=config so we can get the default naming context */
-@@ -167,6 +173,28 @@ ipalockout_get_global_config(struct ipa_context *ipactx)
-         goto done;
-     }
- 
-+    krberr = krb5_init_context(&krbctx);
-+    if (krberr) {
-+        LOG_FATAL("krb5_init_context failed (%d)\n", krberr);
-+        ret = LDAP_OPERATIONS_ERROR;
-+        goto done;
-+    }
-+
-+    krberr = krb5_get_default_realm(krbctx, &realm);
-+    if (krberr) {
-+        LOG_FATAL("Failed to get default realm (%d)\n", krberr);
-+        ret = LDAP_OPERATIONS_ERROR;
-+        goto done;
-+    }
-+
-+    ipa_global_policy = slapi_ch_smprintf("cn=global_policy,cn=%s,cn=kerberos,%s",
-+                                          realm, basedn);
-+    if (!ipa_global_policy) {
-+        LOG_OOM();
-+        ret = LDAP_OPERATIONS_ERROR;
-+        goto done;
-+    }
-+
-     ret = asprintf(&dn, "cn=ipaConfig,cn=etc,%s", basedn);
-     if (ret == -1) {
-         LOG_OOM();
-@@ -221,6 +249,8 @@ ipalockout_get_global_config(struct ipa_context *ipactx)
- done:
-     if (config_entry)
-         slapi_entry_free(config_entry);
-+    free(realm);
-+    krb5_free_context(krbctx);
-     free(dn);
-     free(basedn);
-     return ret;
-@@ -248,6 +278,8 @@ int ipalockout_getpolicy(Slapi_Entry *target_entry, Slapi_Entry **policy_entry,
-             slapi_valueset_first_value(*values, &sv);
-             *policy_dn = slapi_value_get_string(sv);
-         }
-+    } else {
-+        *policy_dn = ipa_global_policy;
-     }
- 
-     if (*policy_dn == NULL) {
-@@ -376,6 +408,8 @@ ipalockout_close(Slapi_PBlock * pb)
- {
-     LOG_TRACE( "--in-->\n");
- 
-+    slapi_ch_free_string(&ipa_global_policy);
-+
-     LOG_TRACE("<--out--\n");
- 
-     return EOK;
--- 
-1.8.5.3
-
diff --git a/SOURCES/0040-Restore-file-extended-attributes-and-SELinux-context.patch b/SOURCES/0040-Restore-file-extended-attributes-and-SELinux-context.patch
new file mode 100644
index 0000000..5d920ee
--- /dev/null
+++ b/SOURCES/0040-Restore-file-extended-attributes-and-SELinux-context.patch
@@ -0,0 +1,38 @@
+From 387a4fb2430639f3d87ee1d310997576ddfd9246 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 20 Nov 2014 12:45:40 +0000
+Subject: [PATCH] Restore file extended attributes and SELinux context in
+ ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4712
+
+Reviewed-By: Petr Viktorin <pviktori@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 8b1e80f5ed5e140ccb17ea0b63d92b6049507b74..7b92ab5d490a7a254b1ea307d5031da002b9f653 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -523,6 +523,8 @@ class Restore(admintool.AdminTool):
+         cwd = os.getcwd()
+         os.chdir('/')
+         args = ['tar',
++                '--xattrs',
++                '--selinux',
+                 '-xzf',
+                 os.path.join(self.dir, 'files.tar')
+                ]
+@@ -581,6 +583,8 @@ class Restore(admintool.AdminTool):
+         os.chdir(self.dir)
+ 
+         args = ['tar',
++                '--xattrs',
++                '--selinux',
+                 '-xzf',
+                 filename,
+                 '.'
+-- 
+2.1.0
+
diff --git a/SOURCES/0041-Migration-does-not-add-users-to-default-group.patch b/SOURCES/0041-Migration-does-not-add-users-to-default-group.patch
deleted file mode 100644
index 10c292c..0000000
--- a/SOURCES/0041-Migration-does-not-add-users-to-default-group.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 8b7a17d19428fa13dcd76893d758863adb9f515e Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Mon, 27 Jan 2014 12:28:12 +0100
-Subject: [PATCH] Migration does not add users to default group
-
-When users with missing default group were searched, IPA suffix was
-not passed so these users were searched in a wrong base DN. Thus,
-no user was detected and added to default group.
-
-https://fedorahosted.org/freeipa/ticket/4141
----
- ipalib/plugins/migration.py | 17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
-diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
-index 83bf40dbfa4cf2310b2501c28cf095299711331d..0ed65f7015f458aa1cf96efb0e36e28c5019cbd2 100644
---- a/ipalib/plugins/migration.py
-+++ b/ipalib/plugins/migration.py
-@@ -286,19 +286,21 @@ def _update_default_group(ldap, pkey, config, ctx, force):
-         searchfilter = "(&(objectclass=posixAccount)(!(memberof=%s)))" % group_dn
-         try:
-             (result, truncated) = ldap.find_entries(searchfilter,
--                [''], api.env.container_user, scope=ldap.SCOPE_SUBTREE,
--                time_limit = -1)
-+                [''], DN(api.env.container_user, api.env.basedn),
-+                scope=ldap.SCOPE_SUBTREE, time_limit = -1)
-         except errors.NotFound:
-+            api.log.debug('All users have default group set')
-             return
-         new_members = []
-         (group_dn, group_entry_attrs) = ldap.get_entry(group_dn, ['member'])
-+        existing_members = set(group_entry_attrs.get('member', []))
-         for m in result:
--            if m[0] not in group_entry_attrs.get('member', []):
-+            if m[0] not in existing_members:
-                 new_members.append(m[0])
--        if len(new_members) > 0:
--            members = group_entry_attrs.get('member', [])
-+
-+        if new_members:
-+            members = group_entry_attrs.setdefault('member', [])
-             members.extend(new_members)
--            group_entry_attrs['member'] = members
- 
-             try:
-                 ldap.update_entry(group_dn, group_entry_attrs)
-@@ -308,7 +310,8 @@ def _update_default_group(ldap, pkey, config, ctx, force):
-         e = datetime.datetime.now()
-         d = e - s
-         mode = " (forced)" if force else ""
--        api.log.debug('Adding %d users to group%s duration %s' % (len(new_members), mode, d))
-+        api.log.debug('Adding %d users to group%s duration %s',
-+                len(new_members), mode, d)
- 
- # GROUP MIGRATION CALLBACKS AND VARS
- 
--- 
-1.8.5.3
-
diff --git a/SOURCES/0041-restore-clear-httpd-ccache-after-restore.patch b/SOURCES/0041-restore-clear-httpd-ccache-after-restore.patch
new file mode 100644
index 0000000..ed2eb27
--- /dev/null
+++ b/SOURCES/0041-restore-clear-httpd-ccache-after-restore.patch
@@ -0,0 +1,32 @@
+From 8fb9a4a82c6ab1026e3d414d39b86d0467735a37 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 20 Nov 2014 15:11:02 +0100
+Subject: [PATCH] restore: clear httpd ccache after restore
+
+so that httpd ccache won't contain old credentials which would make ipa CLI fail with error:
+
+ Insufficient access: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure.  Minor code may provide more information (Decrypt integrity check failed)
+
+https://fedorahosted.org/freeipa/ticket/4726
+
+Reviewed-By: Petr Viktorin <pviktori@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 7b92ab5d490a7a254b1ea307d5031da002b9f653..93f176d302a49319940555a0be3037620143e1f3 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -315,6 +315,8 @@ class Restore(admintool.AdminTool):
+                 self.log.info('Restarting SSSD')
+                 sssd = services.service('sssd')
+                 sssd.restart()
++                http = httpinstance.HTTPInstance()
++                http.remove_httpd_ccache()
+         finally:
+             try:
+                 os.chdir(cwd)
+-- 
+2.1.0
+
diff --git a/SOURCES/0042-Fix-user-group-ignore-attribute-in-migration-plugin.patch b/SOURCES/0042-Fix-user-group-ignore-attribute-in-migration-plugin.patch
new file mode 100644
index 0000000..0b0939a
--- /dev/null
+++ b/SOURCES/0042-Fix-user-group-ignore-attribute-in-migration-plugin.patch
@@ -0,0 +1,45 @@
+From 7f2021b3fc501d3ee70976f4dba06629c71ae417 Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Wed, 19 Nov 2014 09:57:59 -0500
+Subject: [PATCH] Fix --{user,group}-ignore-attribute in migration plugin.
+
+Ignore case in attribute names.
+
+https://fedorahosted.org/freeipa/ticket/4620
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ ipalib/plugins/migration.py | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
+index 6b630a464f0be163e82de95afe3a74b22889574b..fa3d512bf1434c7d349713f78c292b481021303a 100644
+--- a/ipalib/plugins/migration.py
++++ b/ipalib/plugins/migration.py
+@@ -196,9 +196,8 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs
+         entry_attrs.setdefault('loginshell', default_shell)
+ 
+     # do not migrate all attributes
+-    for attr in entry_attrs.keys():
+-        if attr in attr_blacklist:
+-            del entry_attrs[attr]
++    for attr in attr_blacklist:
++        entry_attrs.pop(attr, None)
+ 
+     # do not migrate all object classes
+     if 'objectclass' in entry_attrs:
+@@ -393,9 +392,8 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
+         raise ValueError('Schema %s not supported' % schema)
+ 
+     # do not migrate all attributes
+-    for attr in entry_attrs.keys():
+-        if attr in attr_blacklist:
+-            del entry_attrs[attr]
++    for attr in attr_blacklist:
++        entry_attrs.pop(attr, None)
+ 
+     # do not migrate all object classes
+     if 'objectclass' in entry_attrs:
+-- 
+2.1.0
+
diff --git a/SOURCES/0042-ipa-lockout-do-not-fail-when-default-realm-cannot-be.patch b/SOURCES/0042-ipa-lockout-do-not-fail-when-default-realm-cannot-be.patch
deleted file mode 100644
index 3020bec..0000000
--- a/SOURCES/0042-ipa-lockout-do-not-fail-when-default-realm-cannot-be.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From c41034f5ab587023d9941409618bdf5dc9046fae Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Tue, 4 Feb 2014 11:02:34 +0100
-Subject: [PATCH] ipa-lockout: do not fail when default realm cannot be read
-
-When ipa-lockout plugin is started during FreeIPA server installation,
-the default realm may not be available and plugin should then not end
-with failure.
-
-Similarly to other plugins, start in degraded mode in this situation.
-Operation is fully restored during the final services restart.
-
-https://fedorahosted.org/freeipa/ticket/4085
----
- .../ipa-slapi-plugins/ipa-lockout/ipa_lockout.c    | 34 +++++++++++-----------
- 1 file changed, 17 insertions(+), 17 deletions(-)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-index 5a24359d319aaea28773daa01d268d2d46583270..265c2701c36fe78486a2bdd4a66366b0b05472a0 100644
---- a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-+++ b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
-@@ -176,23 +176,23 @@ ipalockout_get_global_config(struct ipa_context *ipactx)
-     krberr = krb5_init_context(&krbctx);
-     if (krberr) {
-         LOG_FATAL("krb5_init_context failed (%d)\n", krberr);
--        ret = LDAP_OPERATIONS_ERROR;
--        goto done;
--    }
--
--    krberr = krb5_get_default_realm(krbctx, &realm);
--    if (krberr) {
--        LOG_FATAL("Failed to get default realm (%d)\n", krberr);
--        ret = LDAP_OPERATIONS_ERROR;
--        goto done;
--    }
--
--    ipa_global_policy = slapi_ch_smprintf("cn=global_policy,cn=%s,cn=kerberos,%s",
--                                          realm, basedn);
--    if (!ipa_global_policy) {
--        LOG_OOM();
--        ret = LDAP_OPERATIONS_ERROR;
--        goto done;
-+        /* Yes, we failed, but it is because /etc/krb5.conf doesn't exist
-+         * or is misconfigured. Start up in a degraded mode.
-+         */
-+    } else {
-+        krberr = krb5_get_default_realm(krbctx, &realm);
-+        if (krberr) {
-+            LOG_FATAL("Failed to get default realm (%d)\n", krberr);
-+        } else {
-+            ipa_global_policy =
-+                slapi_ch_smprintf("cn=global_policy,cn=%s,cn=kerberos,%s",
-+                                  realm, basedn);
-+            if (!ipa_global_policy) {
-+                LOG_OOM();
-+                ret = LDAP_OPERATIONS_ERROR;
-+                goto done;
-+            }
-+        }
-     }
- 
-     ret = asprintf(&dn, "cn=ipaConfig,cn=etc,%s", basedn);
--- 
-1.8.5.3
-
diff --git a/SOURCES/0043-Fix-filtering-of-enctypes-in-server-code.patch b/SOURCES/0043-Fix-filtering-of-enctypes-in-server-code.patch
new file mode 100644
index 0000000..27024cf
--- /dev/null
+++ b/SOURCES/0043-Fix-filtering-of-enctypes-in-server-code.patch
@@ -0,0 +1,98 @@
+From 6a6389fefdc055b5a920e6e4412ff0b7e37ef33a Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Mon, 17 Nov 2014 21:05:56 -0500
+Subject: [PATCH] Fix filtering of enctypes in server code.
+
+The filtering was incorrect and would result in always discarding all values.
+Also make sure there are no duplicates in the list.
+
+Partial fix for:
+https://fedorahosted.org/freeipa/ticket/4718
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com>
+---
+ .../ipa-pwd-extop/ipa_pwd_extop.c                  | 60 ++++++++++++++++------
+ 1 file changed, 43 insertions(+), 17 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+index f0346a343188930dfc90e19d2e5d38cb30741b90..b87ae0dc7a180008228f31293b49212df80584e8 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+@@ -125,6 +125,48 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
+     }
+ }
+ 
++static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
++                            krb5_key_salt_tuple *kenctypes,
++                            int *num_kenctypes)
++{
++    /* first filter for duplicates */
++    for (int i = 0; i + 1 < *num_kenctypes; i++) {
++        for (int j = i + 1; j < *num_kenctypes; j++) {
++            if (kenctypes[i].ks_enctype == kenctypes[j].ks_enctype) {
++                /* duplicate, filter out */
++                for (int k = j; k + 1 < *num_kenctypes; k++) {
++                    kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
++                    kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
++                }
++                (*num_kenctypes)--;
++                j--;
++            }
++        }
++    }
++
++    /* then filter for supported */
++    for (int i = 0; i < *num_kenctypes; i++) {
++        int j;
++
++        /* Check if supported */
++        for (j = 0; j < krbcfg->num_supp_encsalts; j++) {
++            if (kenctypes[i].ks_enctype ==
++                                    krbcfg->supp_encsalts[j].ks_enctype) {
++                break;
++            }
++        }
++        if (j == krbcfg->num_supp_encsalts) {
++            /* Unsupported, filter out */
++            for (int k = i; k + 1 < *num_kenctypes; k++) {
++                kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
++                kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
++            }
++            (*num_kenctypes)--;
++            i--;
++        }
++    }
++}
++
+ static int ipapwd_to_ldap_pwpolicy_error(int ipapwderr)
+ {
+     switch (ipapwderr) {
+@@ -1740,23 +1782,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
+             goto free_and_return;
+         }
+ 
+-        for (int i = 0; i < num_kenctypes; i++) {
+-
+-            /* Check if supported */
+-            for (int j = 0; j < krbcfg->num_supp_encsalts; j++) {
+-                if (kenctypes[i].ks_enctype ==
+-                                        krbcfg->supp_encsalts[j].ks_enctype) {
+-                    continue;
+-                }
+-            }
+-            /* Unsupported, filter out */
+-            for (int j = i; j + 1 < num_kenctypes; j++) {
+-                kenctypes[j].ks_enctype = kenctypes[j + 1].ks_enctype;
+-                kenctypes[j].ks_salttype = kenctypes[j + 1].ks_salttype;
+-            }
+-            num_kenctypes--;
+-            i--;
+-        }
++        filter_enctypes(krbcfg, kenctypes, &num_kenctypes);
+ 
+         /* check if we have any left */
+         if (num_kenctypes == 0 && kenctypes != NULL) {
+-- 
+2.1.0
+
diff --git a/SOURCES/0043-ipa-tool-Print-the-name-of-the-server-we-are-connect.patch b/SOURCES/0043-ipa-tool-Print-the-name-of-the-server-we-are-connect.patch
deleted file mode 100644
index 9f66da8..0000000
--- a/SOURCES/0043-ipa-tool-Print-the-name-of-the-server-we-are-connect.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 09a2ae5368abce22e397fef29d3acf3c16b8b96c Mon Sep 17 00:00:00 2001
-From: Petr Viktorin <pviktori@redhat.com>
-Date: Wed, 5 Feb 2014 09:24:22 +0100
-Subject: [PATCH 43/46] ipa tool: Print the name of the server we are
- connecting to with -v
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The logging level for these messages was decreaed so that they
-do not show up in ipa-advise output.
-Reset the log level to INFO and configure ipa-advise to not display
-INFO messages from xmlclient by default.
-
-Partially reverts commit efe5a96725d3ddcd05b03a1ca9df5597eee693be
-
-https://fedorahosted.org/freeipa/ticket/4135
-
-Reviewed-By: Tomáš Babej <tbabej@redhat.com>
----
- ipalib/rpc.py            | 4 ++--
- ipaserver/advise/base.py | 5 +++++
- 2 files changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/ipalib/rpc.py b/ipalib/rpc.py
-index 81e7aa35fdf780b3dcd850cfcc3ba5285d71e461..1eec1134617dd49395c2b36f11f304c473067a5d 100644
---- a/ipalib/rpc.py
-+++ b/ipalib/rpc.py
-@@ -621,7 +621,7 @@ def create_connection(self, ccache=None, verbose=False, fallback=True,
-                     kw['transport'] = KerbTransport()
-             else:
-                 kw['transport'] = LanguageAwareTransport()
--            self.log.debug('trying %s' % url)
-+            self.log.info('trying %s' % url)
-             setattr(context, 'request_url', url)
-             serverproxy = ServerProxy(url, **kw)
-             if len(urls) == 1:
-@@ -697,7 +697,7 @@ def forward(self, name, *args, **kw):
-                 '%s.forward(): %r not in api.Command' % (self.name, name)
-             )
-         server = getattr(context, 'request_url', None)
--        self.debug("Forwarding '%s' to server '%s'", name, server)
-+        self.log.info("Forwarding '%s' to server '%s'", name, server)
-         command = getattr(self.conn, name)
-         params = [args, kw]
-         try:
-diff --git a/ipaserver/advise/base.py b/ipaserver/advise/base.py
-index 92dbb4e9e30c6d624eca95609568ae62bd9ea7fe..056cb808d24805202f16b4afd60356163ca9006a 100644
---- a/ipaserver/advise/base.py
-+++ b/ipaserver/advise/base.py
-@@ -22,6 +22,7 @@
- from ipalib.errors import ValidationError
- from ipapython import admintool
- from textwrap import wrap
-+from ipapython.ipa_log_manager import log_mgr
- 
- 
- """
-@@ -173,6 +174,10 @@ def run(self):
- 
-         api.bootstrap(in_server=False, context='advise')
-         api.finalize()
-+        if not self.options.verbose:
-+            # Do not print connection information by default
-+            logger_name = r'ipa\.ipalib\.rpc\.xmlclient'
-+            log_mgr.configure(dict(logger_regexps=[(logger_name, 'warning')]))
- 
-         # With no argument, print the list out and exit
-         if not self.args:
--- 
-1.8.5.3
-
diff --git a/SOURCES/0044-Add-asn1c-generated-code-for-keytab-controls.patch b/SOURCES/0044-Add-asn1c-generated-code-for-keytab-controls.patch
new file mode 100644
index 0000000..31aba71
--- /dev/null
+++ b/SOURCES/0044-Add-asn1c-generated-code-for-keytab-controls.patch
@@ -0,0 +1,13109 @@
+From eaad64ae7202fd46c85cc20fc9a09891efb3c937 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Thu, 13 Nov 2014 11:31:09 -0500
+Subject: [PATCH] Add asn1c generated code for keytab controls
+
+Instead of manually encoding controls, use an actual asn1 compiler.
+The file asn1/asn1c/ipa.asn1 will contain ipa modules. The generated code
+is committed to the tree and built into a static library that is linked
+to the code that uses it.
+
+The first module implements the GetKeytabControl control.
+
+Related:
+https://fedorahosted.org/freeipa/ticket/4718
+https://fedorahosted.org/freeipa/ticket/4728
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com>
+---
+ .gitignore                      |    1 +
+ Makefile                        |    5 +-
+ asn1/Makefile.am                |    8 +
+ asn1/README                     |   17 +
+ asn1/asn1c/BIT_STRING.c         |  188 +++++
+ asn1/asn1c/BIT_STRING.h         |   33 +
+ asn1/asn1c/GKCurrentKeys.c      |   61 ++
+ asn1/asn1c/GKCurrentKeys.h      |   37 +
+ asn1/asn1c/GKNewKeys.c          |  126 ++++
+ asn1/asn1c/GKNewKeys.h          |   47 ++
+ asn1/asn1c/GKReply.c            |  115 +++
+ asn1/asn1c/GKReply.h            |   51 ++
+ asn1/asn1c/GetKeytabControl.c   |   77 ++
+ asn1/asn1c/GetKeytabControl.h   |   52 ++
+ asn1/asn1c/INTEGER.c            |  835 +++++++++++++++++++++
+ asn1/asn1c/INTEGER.h            |   65 ++
+ asn1/asn1c/Int32.c              |  127 ++++
+ asn1/asn1c/Int32.h              |   38 +
+ asn1/asn1c/KrbKey.c             |   81 ++
+ asn1/asn1c/KrbKey.h             |   46 ++
+ asn1/asn1c/Makefile.am          |   93 +++
+ asn1/asn1c/NativeEnumerated.c   |  204 ++++++
+ asn1/asn1c/NativeEnumerated.h   |   32 +
+ asn1/asn1c/NativeInteger.c      |  314 ++++++++
+ asn1/asn1c/NativeInteger.h      |   37 +
+ asn1/asn1c/OCTET_STRING.c       | 1550 +++++++++++++++++++++++++++++++++++++++
+ asn1/asn1c/OCTET_STRING.h       |   80 ++
+ asn1/asn1c/TypeValuePair.c      |   71 ++
+ asn1/asn1c/TypeValuePair.h      |   39 +
+ asn1/asn1c/asn_SEQUENCE_OF.c    |   41 ++
+ asn1/asn1c/asn_SEQUENCE_OF.h    |   52 ++
+ asn1/asn1c/asn_SET_OF.c         |   88 +++
+ asn1/asn1c/asn_SET_OF.h         |   62 ++
+ asn1/asn1c/asn_application.h    |   47 ++
+ asn1/asn1c/asn_codecs.h         |  109 +++
+ asn1/asn1c/asn_codecs_prim.c    |  295 ++++++++
+ asn1/asn1c/asn_codecs_prim.h    |   53 ++
+ asn1/asn1c/asn_internal.h       |  111 +++
+ asn1/asn1c/asn_system.h         |  104 +++
+ asn1/asn1c/ber_decoder.c        |  283 +++++++
+ asn1/asn1c/ber_decoder.h        |   63 ++
+ asn1/asn1c/ber_tlv_length.c     |  178 +++++
+ asn1/asn1c/ber_tlv_length.h     |   50 ++
+ asn1/asn1c/ber_tlv_tag.c        |  144 ++++
+ asn1/asn1c/ber_tlv_tag.h        |   60 ++
+ asn1/asn1c/constr_CHOICE.c      | 1101 +++++++++++++++++++++++++++
+ asn1/asn1c/constr_CHOICE.h      |   57 ++
+ asn1/asn1c/constr_SEQUENCE.c    | 1251 +++++++++++++++++++++++++++++++
+ asn1/asn1c/constr_SEQUENCE.h    |   60 ++
+ asn1/asn1c/constr_SEQUENCE_OF.c |  208 ++++++
+ asn1/asn1c/constr_SEQUENCE_OF.h |   33 +
+ asn1/asn1c/constr_SET_OF.c      |  942 ++++++++++++++++++++++++
+ asn1/asn1c/constr_SET_OF.h      |   42 ++
+ asn1/asn1c/constr_TYPE.c        |   77 ++
+ asn1/asn1c/constr_TYPE.h        |  180 +++++
+ asn1/asn1c/constraints.c        |   93 +++
+ asn1/asn1c/constraints.h        |   63 ++
+ asn1/asn1c/der_encoder.c        |  199 +++++
+ asn1/asn1c/der_encoder.h        |   67 ++
+ asn1/asn1c/ipa.asn1             |   37 +
+ asn1/asn1c/per_decoder.c        |   55 ++
+ asn1/asn1c/per_decoder.h        |   44 ++
+ asn1/asn1c/per_encoder.c        |   95 +++
+ asn1/asn1c/per_encoder.h        |   49 ++
+ asn1/asn1c/per_support.c        |  318 ++++++++
+ asn1/asn1c/per_support.h        |  105 +++
+ asn1/asn1c/xer_decoder.c        |  363 +++++++++
+ asn1/asn1c/xer_decoder.h        |  106 +++
+ asn1/asn1c/xer_encoder.c        |   67 ++
+ asn1/asn1c/xer_encoder.h        |   59 ++
+ asn1/asn1c/xer_support.c        |  233 ++++++
+ asn1/asn1c/xer_support.h        |   55 ++
+ asn1/configure.ac               |   24 +
+ asn1/ipa_asn1.c                 |  229 ++++++
+ asn1/ipa_asn1.h                 |   76 ++
+ util/ipa_krb5.h                 |    1 +
+ 76 files changed, 12457 insertions(+), 2 deletions(-)
+ create mode 100644 asn1/Makefile.am
+ create mode 100644 asn1/README
+ create mode 100644 asn1/asn1c/BIT_STRING.c
+ create mode 100644 asn1/asn1c/BIT_STRING.h
+ create mode 100644 asn1/asn1c/GKCurrentKeys.c
+ create mode 100644 asn1/asn1c/GKCurrentKeys.h
+ create mode 100644 asn1/asn1c/GKNewKeys.c
+ create mode 100644 asn1/asn1c/GKNewKeys.h
+ create mode 100644 asn1/asn1c/GKReply.c
+ create mode 100644 asn1/asn1c/GKReply.h
+ create mode 100644 asn1/asn1c/GetKeytabControl.c
+ create mode 100644 asn1/asn1c/GetKeytabControl.h
+ create mode 100644 asn1/asn1c/INTEGER.c
+ create mode 100644 asn1/asn1c/INTEGER.h
+ create mode 100644 asn1/asn1c/Int32.c
+ create mode 100644 asn1/asn1c/Int32.h
+ create mode 100644 asn1/asn1c/KrbKey.c
+ create mode 100644 asn1/asn1c/KrbKey.h
+ create mode 100644 asn1/asn1c/Makefile.am
+ create mode 100644 asn1/asn1c/NativeEnumerated.c
+ create mode 100644 asn1/asn1c/NativeEnumerated.h
+ create mode 100644 asn1/asn1c/NativeInteger.c
+ create mode 100644 asn1/asn1c/NativeInteger.h
+ create mode 100644 asn1/asn1c/OCTET_STRING.c
+ create mode 100644 asn1/asn1c/OCTET_STRING.h
+ create mode 100644 asn1/asn1c/TypeValuePair.c
+ create mode 100644 asn1/asn1c/TypeValuePair.h
+ create mode 100644 asn1/asn1c/asn_SEQUENCE_OF.c
+ create mode 100644 asn1/asn1c/asn_SEQUENCE_OF.h
+ create mode 100644 asn1/asn1c/asn_SET_OF.c
+ create mode 100644 asn1/asn1c/asn_SET_OF.h
+ create mode 100644 asn1/asn1c/asn_application.h
+ create mode 100644 asn1/asn1c/asn_codecs.h
+ create mode 100644 asn1/asn1c/asn_codecs_prim.c
+ create mode 100644 asn1/asn1c/asn_codecs_prim.h
+ create mode 100644 asn1/asn1c/asn_internal.h
+ create mode 100644 asn1/asn1c/asn_system.h
+ create mode 100644 asn1/asn1c/ber_decoder.c
+ create mode 100644 asn1/asn1c/ber_decoder.h
+ create mode 100644 asn1/asn1c/ber_tlv_length.c
+ create mode 100644 asn1/asn1c/ber_tlv_length.h
+ create mode 100644 asn1/asn1c/ber_tlv_tag.c
+ create mode 100644 asn1/asn1c/ber_tlv_tag.h
+ create mode 100644 asn1/asn1c/constr_CHOICE.c
+ create mode 100644 asn1/asn1c/constr_CHOICE.h
+ create mode 100644 asn1/asn1c/constr_SEQUENCE.c
+ create mode 100644 asn1/asn1c/constr_SEQUENCE.h
+ create mode 100644 asn1/asn1c/constr_SEQUENCE_OF.c
+ create mode 100644 asn1/asn1c/constr_SEQUENCE_OF.h
+ create mode 100644 asn1/asn1c/constr_SET_OF.c
+ create mode 100644 asn1/asn1c/constr_SET_OF.h
+ create mode 100644 asn1/asn1c/constr_TYPE.c
+ create mode 100644 asn1/asn1c/constr_TYPE.h
+ create mode 100644 asn1/asn1c/constraints.c
+ create mode 100644 asn1/asn1c/constraints.h
+ create mode 100644 asn1/asn1c/der_encoder.c
+ create mode 100644 asn1/asn1c/der_encoder.h
+ create mode 100644 asn1/asn1c/ipa.asn1
+ create mode 100644 asn1/asn1c/per_decoder.c
+ create mode 100644 asn1/asn1c/per_decoder.h
+ create mode 100644 asn1/asn1c/per_encoder.c
+ create mode 100644 asn1/asn1c/per_encoder.h
+ create mode 100644 asn1/asn1c/per_support.c
+ create mode 100644 asn1/asn1c/per_support.h
+ create mode 100644 asn1/asn1c/xer_decoder.c
+ create mode 100644 asn1/asn1c/xer_decoder.h
+ create mode 100644 asn1/asn1c/xer_encoder.c
+ create mode 100644 asn1/asn1c/xer_encoder.h
+ create mode 100644 asn1/asn1c/xer_support.c
+ create mode 100644 asn1/asn1c/xer_support.h
+ create mode 100644 asn1/configure.ac
+ create mode 100644 asn1/ipa_asn1.c
+ create mode 100644 asn1/ipa_asn1.h
+
+diff --git a/.gitignore b/.gitignore
+index 5b3f401d26c172cf24a08014651e453439a5e9d1..c4c761903d29e1b9f62c7ece04dbaa187fb84de8 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -25,6 +25,7 @@ missing
+ stamp-h1
+ libtool
+ build/
++compile
+ 
+ # Python compilation
+ *.pyc
+diff --git a/Makefile b/Makefile
+index eca282a2390002dcefcc7b544b69a47b81418e0d..c1a298f91717246e8dab5e3f0de47d0ac9b2ae35 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ include VERSION
+ 
+-SUBDIRS=daemons install ipapython ipa-client
+-CLIENTDIRS=ipapython ipa-client
++SUBDIRS=asn1 daemons install ipapython ipa-client
++CLIENTDIRS=ipapython ipa-client asn1
+ 
+ PRJ_PREFIX=freeipa
+ 
+@@ -79,6 +79,7 @@ bootstrap-autogen: version-update client-autogen
+ 	cd install; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 
+ client-autogen: version-update
++	cd asn1; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 	cd ipa-client; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 	cd install; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 
+diff --git a/asn1/Makefile.am b/asn1/Makefile.am
+new file mode 100644
+index 0000000000000000000000000000000000000000..03e92b2d6d73f89625d5613f039361a6e02866b9
+--- /dev/null
++++ b/asn1/Makefile.am
+@@ -0,0 +1,8 @@
++SUBDIRS = asn1c
++
++AM_CPPFLAGS = -I../util -Iasn1c
++
++noinst_LTLIBRARIES=libipaasn1.la
++noinst_HEADERS=ipa_asn1.h
++libipaasn1_la_SOURCES=ipa_asn1.c
++libipaasn1_la_LIBADD=asn1c/libasn1c.la
+diff --git a/asn1/README b/asn1/README
+new file mode 100644
+index 0000000000000000000000000000000000000000..ec9752f566a8b57b45d433bb46316c9aba325fa7
+--- /dev/null
++++ b/asn1/README
+@@ -0,0 +1,17 @@
++libipaasn1.a is a small static convenience library used by other ipa
++binaries and modules. At the moment it is not meant to be a public shared
++library and stable interface, but may become one in future.
++
++The only files that should be manually modified are:
++* asn1c/ipa.asn1 - when new interfaces are added
++* ipa_asn1.[ch] - to add wrappers around interfaces
++
++ipa_asn1.[ch] are the public interface and they SHOULD NOT export generated
++structures so that the autogenerated code can change w/o impacting any other
++code except the internal library functions.
++
++To regenerate the automatically generated files run the following command:
++cd asn1c;
++make regenerate
++
++Remember to commit and add any new file to asn1c/Makefile.am
+diff --git a/asn1/asn1c/BIT_STRING.c b/asn1/asn1c/BIT_STRING.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..6469d4fd2c8782048e228c19e67950f3b2dc1305
+--- /dev/null
++++ b/asn1/asn1c/BIT_STRING.c
+@@ -0,0 +1,188 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <BIT_STRING.h>
++#include <asn_internal.h>
++
++/*
++ * BIT STRING basic type description.
++ */
++static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
++};
++static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
++	sizeof(BIT_STRING_t),
++	offsetof(BIT_STRING_t, _asn_ctx),
++	1,	/* Special indicator that this is a BIT STRING type */
++};
++asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
++	"BIT STRING",
++	"BIT_STRING",
++	OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */
++	BIT_STRING_print,
++	BIT_STRING_constraint,
++	OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
++	OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
++	OCTET_STRING_decode_xer_binary,
++	BIT_STRING_encode_xer,
++	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
++	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
++	0, /* Use generic outmost tag fetcher */
++	asn_DEF_BIT_STRING_tags,
++	sizeof(asn_DEF_BIT_STRING_tags)
++	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
++	asn_DEF_BIT_STRING_tags,	/* Same as above */
++	sizeof(asn_DEF_BIT_STRING_tags)
++	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	&asn_DEF_BIT_STRING_specs
++};
++
++/*
++ * BIT STRING generic constraint.
++ */
++int
++BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
++		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
++	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
++
++	if(st && st->buf) {
++		if(st->size == 1 && st->bits_unused) {
++			_ASN_CTFAIL(app_key, td,
++				"%s: invalid padding byte (%s:%d)",
++				td->name, __FILE__, __LINE__);
++			return -1;
++		}
++	} else {
++		_ASN_CTFAIL(app_key, td,
++			"%s: value not given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++
++	return 0;
++}
++
++static char *_bit_pattern[16] = {
++	"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
++	"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
++};
++
++asn_enc_rval_t
++BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er;
++	char scratch[128];
++	char *p = scratch;
++	char *scend = scratch + (sizeof(scratch) - 10);
++	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
++	int xcan = (flags & XER_F_CANONICAL);
++	uint8_t *buf;
++	uint8_t *end;
++
++	if(!st || !st->buf)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = 0;
++
++	buf = st->buf;
++	end = buf + st->size - 1;	/* Last byte is special */
++
++	/*
++	 * Binary dump
++	 */
++	for(; buf < end; buf++) {
++		int v = *buf;
++		int nline = xcan?0:(((buf - st->buf) % 8) == 0);
++		if(p >= scend || nline) {
++			er.encoded += p - scratch;
++			_ASN_CALLBACK(scratch, p - scratch);
++			p = scratch;
++			if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
++		}
++		memcpy(p + 0, _bit_pattern[v >> 4], 4);
++		memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
++		p += 8;
++	}
++
++	if(!xcan && ((buf - st->buf) % 8) == 0)
++		_i_ASN_TEXT_INDENT(1, ilevel);
++	er.encoded += p - scratch;
++	_ASN_CALLBACK(scratch, p - scratch);
++	p = scratch;
++
++	if(buf == end) {
++		int v = *buf;
++		int ubits = st->bits_unused;
++		int i;
++		for(i = 7; i >= ubits; i--)
++			*p++ = (v & (1 << i)) ? 0x31 : 0x30;
++		er.encoded += p - scratch;
++		_ASN_CALLBACK(scratch, p - scratch);
++	}
++
++	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++
++/*
++ * BIT STRING specific contents printer.
++ */
++int
++BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	static const char *h2c = "0123456789ABCDEF";
++	char scratch[64];
++	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
++	uint8_t *buf;
++	uint8_t *end;
++	char *p = scratch;
++
++	(void)td;	/* Unused argument */
++
++	if(!st || !st->buf)
++		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++
++	ilevel++;
++	buf = st->buf;
++	end = buf + st->size;
++
++	/*
++	 * Hexadecimal dump.
++	 */
++	for(; buf < end; buf++) {
++		if((buf - st->buf) % 16 == 0 && (st->size > 16)
++				&& buf != st->buf) {
++			_i_INDENT(1);
++			/* Dump the string */
++			if(cb(scratch, p - scratch, app_key) < 0) return -1;
++			p = scratch;
++		}
++		*p++ = h2c[*buf >> 4];
++		*p++ = h2c[*buf & 0x0F];
++		*p++ = 0x20;
++	}
++
++	if(p > scratch) {
++		p--;	/* Eat the tailing space */
++
++		if((st->size > 16)) {
++			_i_INDENT(1);
++		}
++
++		/* Dump the incomplete 16-bytes row */
++		if(cb(scratch, p - scratch, app_key) < 0)
++			return -1;
++	}
++
++	return 0;
++}
++
+diff --git a/asn1/asn1c/BIT_STRING.h b/asn1/asn1c/BIT_STRING.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..732e878bcad1694e685153934afd8ce91f869e83
+--- /dev/null
++++ b/asn1/asn1c/BIT_STRING.h
+@@ -0,0 +1,33 @@
++/*-
++ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_BIT_STRING_H_
++#define	_BIT_STRING_H_
++
++#include <OCTET_STRING.h>	/* Some help from OCTET STRING */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct BIT_STRING_s {
++	uint8_t *buf;	/* BIT STRING body */
++	int size;	/* Size of the above buffer */
++
++	int bits_unused;/* Unused trailing bits in the last octet (0..7) */
++
++	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
++} BIT_STRING_t;
++
++extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
++
++asn_struct_print_f BIT_STRING_print;	/* Human-readable output */
++asn_constr_check_f BIT_STRING_constraint;
++xer_type_encoder_f BIT_STRING_encode_xer;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _BIT_STRING_H_ */
+diff --git a/asn1/asn1c/GKCurrentKeys.c b/asn1/asn1c/GKCurrentKeys.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..abcc53130d64259d0f2947b04412b4b769bb4360
+--- /dev/null
++++ b/asn1/asn1c/GKCurrentKeys.c
+@@ -0,0 +1,61 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "GKCurrentKeys.h"
++
++static asn_TYPE_member_t asn_MBR_GKCurrentKeys_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct GKCurrentKeys, serviceIdentity),
++		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_OCTET_STRING,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"serviceIdentity"
++		},
++};
++static ber_tlv_tag_t asn_DEF_GKCurrentKeys_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_TYPE_tag2member_t asn_MAP_GKCurrentKeys_tag2el_1[] = {
++    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* serviceIdentity at 19 */
++};
++static asn_SEQUENCE_specifics_t asn_SPC_GKCurrentKeys_specs_1 = {
++	sizeof(struct GKCurrentKeys),
++	offsetof(struct GKCurrentKeys, _asn_ctx),
++	asn_MAP_GKCurrentKeys_tag2el_1,
++	1,	/* Count of tags in the map */
++	0, 0, 0,	/* Optional elements (not needed) */
++	-1,	/* Start extensions */
++	-1	/* Stop extensions */
++};
++asn_TYPE_descriptor_t asn_DEF_GKCurrentKeys = {
++	"GKCurrentKeys",
++	"GKCurrentKeys",
++	SEQUENCE_free,
++	SEQUENCE_print,
++	SEQUENCE_constraint,
++	SEQUENCE_decode_ber,
++	SEQUENCE_encode_der,
++	SEQUENCE_decode_xer,
++	SEQUENCE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_GKCurrentKeys_tags_1,
++	sizeof(asn_DEF_GKCurrentKeys_tags_1)
++		/sizeof(asn_DEF_GKCurrentKeys_tags_1[0]), /* 1 */
++	asn_DEF_GKCurrentKeys_tags_1,	/* Same as above */
++	sizeof(asn_DEF_GKCurrentKeys_tags_1)
++		/sizeof(asn_DEF_GKCurrentKeys_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_GKCurrentKeys_1,
++	1,	/* Elements count */
++	&asn_SPC_GKCurrentKeys_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/GKCurrentKeys.h b/asn1/asn1c/GKCurrentKeys.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..7ec4e4c60dd5c605bec311f713e33630dedaca58
+--- /dev/null
++++ b/asn1/asn1c/GKCurrentKeys.h
+@@ -0,0 +1,37 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_GKCurrentKeys_H_
++#define	_GKCurrentKeys_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include <OCTET_STRING.h>
++#include <constr_SEQUENCE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* GKCurrentKeys */
++typedef struct GKCurrentKeys {
++	OCTET_STRING_t	 serviceIdentity;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} GKCurrentKeys_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_GKCurrentKeys;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _GKCurrentKeys_H_ */
+diff --git a/asn1/asn1c/GKNewKeys.c b/asn1/asn1c/GKNewKeys.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..35ebcf245c25c02572377381ba3418f3f8488fd7
+--- /dev/null
++++ b/asn1/asn1c/GKNewKeys.c
+@@ -0,0 +1,126 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "GKNewKeys.h"
++
++static asn_TYPE_member_t asn_MBR_enctypes_3[] = {
++	{ ATF_POINTER, 0, 0,
++		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
++		0,
++		&asn_DEF_Int32,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		""
++		},
++};
++static ber_tlv_tag_t asn_DEF_enctypes_tags_3[] = {
++	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_SET_OF_specifics_t asn_SPC_enctypes_specs_3 = {
++	sizeof(struct enctypes),
++	offsetof(struct enctypes, _asn_ctx),
++	0,	/* XER encoding is XMLDelimitedItemList */
++};
++static /* Use -fall-defs-global to expose */
++asn_TYPE_descriptor_t asn_DEF_enctypes_3 = {
++	"enctypes",
++	"enctypes",
++	SEQUENCE_OF_free,
++	SEQUENCE_OF_print,
++	SEQUENCE_OF_constraint,
++	SEQUENCE_OF_decode_ber,
++	SEQUENCE_OF_encode_der,
++	SEQUENCE_OF_decode_xer,
++	SEQUENCE_OF_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_enctypes_tags_3,
++	sizeof(asn_DEF_enctypes_tags_3)
++		/sizeof(asn_DEF_enctypes_tags_3[0]), /* 2 */
++	asn_DEF_enctypes_tags_3,	/* Same as above */
++	sizeof(asn_DEF_enctypes_tags_3)
++		/sizeof(asn_DEF_enctypes_tags_3[0]), /* 2 */
++	0,	/* No PER visible constraints */
++	asn_MBR_enctypes_3,
++	1,	/* Single element */
++	&asn_SPC_enctypes_specs_3	/* Additional specs */
++};
++
++static asn_TYPE_member_t asn_MBR_GKNewKeys_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct GKNewKeys, serviceIdentity),
++		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_OCTET_STRING,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"serviceIdentity"
++		},
++	{ ATF_NOFLAGS, 0, offsetof(struct GKNewKeys, enctypes),
++		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_enctypes_3,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"enctypes"
++		},
++	{ ATF_POINTER, 1, offsetof(struct GKNewKeys, password),
++		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_OCTET_STRING,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"password"
++		},
++};
++static ber_tlv_tag_t asn_DEF_GKNewKeys_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_TYPE_tag2member_t asn_MAP_GKNewKeys_tag2el_1[] = {
++    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* serviceIdentity at 13 */
++    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* enctypes at 14 */
++    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* password at 15 */
++};
++static asn_SEQUENCE_specifics_t asn_SPC_GKNewKeys_specs_1 = {
++	sizeof(struct GKNewKeys),
++	offsetof(struct GKNewKeys, _asn_ctx),
++	asn_MAP_GKNewKeys_tag2el_1,
++	3,	/* Count of tags in the map */
++	0, 0, 0,	/* Optional elements (not needed) */
++	-1,	/* Start extensions */
++	-1	/* Stop extensions */
++};
++asn_TYPE_descriptor_t asn_DEF_GKNewKeys = {
++	"GKNewKeys",
++	"GKNewKeys",
++	SEQUENCE_free,
++	SEQUENCE_print,
++	SEQUENCE_constraint,
++	SEQUENCE_decode_ber,
++	SEQUENCE_encode_der,
++	SEQUENCE_decode_xer,
++	SEQUENCE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_GKNewKeys_tags_1,
++	sizeof(asn_DEF_GKNewKeys_tags_1)
++		/sizeof(asn_DEF_GKNewKeys_tags_1[0]), /* 1 */
++	asn_DEF_GKNewKeys_tags_1,	/* Same as above */
++	sizeof(asn_DEF_GKNewKeys_tags_1)
++		/sizeof(asn_DEF_GKNewKeys_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_GKNewKeys_1,
++	3,	/* Elements count */
++	&asn_SPC_GKNewKeys_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/GKNewKeys.h b/asn1/asn1c/GKNewKeys.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..2cd158dff9c36cd6f632448235e889f3c8ab937f
+--- /dev/null
++++ b/asn1/asn1c/GKNewKeys.h
+@@ -0,0 +1,47 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_GKNewKeys_H_
++#define	_GKNewKeys_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include <OCTET_STRING.h>
++#include "Int32.h"
++#include <asn_SEQUENCE_OF.h>
++#include <constr_SEQUENCE_OF.h>
++#include <constr_SEQUENCE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* GKNewKeys */
++typedef struct GKNewKeys {
++	OCTET_STRING_t	 serviceIdentity;
++	struct enctypes {
++		A_SEQUENCE_OF(Int32_t) list;
++		
++		/* Context for parsing across buffer boundaries */
++		asn_struct_ctx_t _asn_ctx;
++	} enctypes;
++	OCTET_STRING_t	*password	/* OPTIONAL */;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} GKNewKeys_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_GKNewKeys;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _GKNewKeys_H_ */
+diff --git a/asn1/asn1c/GKReply.c b/asn1/asn1c/GKReply.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..220c791e2d84b2ea9d889307403bc2b64781f3ce
+--- /dev/null
++++ b/asn1/asn1c/GKReply.c
+@@ -0,0 +1,115 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "GKReply.h"
++
++static asn_TYPE_member_t asn_MBR_keys_3[] = {
++	{ ATF_POINTER, 0, 0,
++		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
++		0,
++		&asn_DEF_KrbKey,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		""
++		},
++};
++static ber_tlv_tag_t asn_DEF_keys_tags_3[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_SET_OF_specifics_t asn_SPC_keys_specs_3 = {
++	sizeof(struct keys),
++	offsetof(struct keys, _asn_ctx),
++	0,	/* XER encoding is XMLDelimitedItemList */
++};
++static /* Use -fall-defs-global to expose */
++asn_TYPE_descriptor_t asn_DEF_keys_3 = {
++	"keys",
++	"keys",
++	SEQUENCE_OF_free,
++	SEQUENCE_OF_print,
++	SEQUENCE_OF_constraint,
++	SEQUENCE_OF_decode_ber,
++	SEQUENCE_OF_encode_der,
++	SEQUENCE_OF_decode_xer,
++	SEQUENCE_OF_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_keys_tags_3,
++	sizeof(asn_DEF_keys_tags_3)
++		/sizeof(asn_DEF_keys_tags_3[0]), /* 1 */
++	asn_DEF_keys_tags_3,	/* Same as above */
++	sizeof(asn_DEF_keys_tags_3)
++		/sizeof(asn_DEF_keys_tags_3[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_keys_3,
++	1,	/* Single element */
++	&asn_SPC_keys_specs_3	/* Additional specs */
++};
++
++static asn_TYPE_member_t asn_MBR_GKReply_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct GKReply, newkvno),
++		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
++		0,
++		&asn_DEF_Int32,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"newkvno"
++		},
++	{ ATF_NOFLAGS, 0, offsetof(struct GKReply, keys),
++		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
++		0,
++		&asn_DEF_keys_3,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"keys"
++		},
++};
++static ber_tlv_tag_t asn_DEF_GKReply_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_TYPE_tag2member_t asn_MAP_GKReply_tag2el_1[] = {
++    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* newkvno at 23 */
++    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 } /* keys at 25 */
++};
++static asn_SEQUENCE_specifics_t asn_SPC_GKReply_specs_1 = {
++	sizeof(struct GKReply),
++	offsetof(struct GKReply, _asn_ctx),
++	asn_MAP_GKReply_tag2el_1,
++	2,	/* Count of tags in the map */
++	0, 0, 0,	/* Optional elements (not needed) */
++	-1,	/* Start extensions */
++	-1	/* Stop extensions */
++};
++asn_TYPE_descriptor_t asn_DEF_GKReply = {
++	"GKReply",
++	"GKReply",
++	SEQUENCE_free,
++	SEQUENCE_print,
++	SEQUENCE_constraint,
++	SEQUENCE_decode_ber,
++	SEQUENCE_encode_der,
++	SEQUENCE_decode_xer,
++	SEQUENCE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_GKReply_tags_1,
++	sizeof(asn_DEF_GKReply_tags_1)
++		/sizeof(asn_DEF_GKReply_tags_1[0]), /* 1 */
++	asn_DEF_GKReply_tags_1,	/* Same as above */
++	sizeof(asn_DEF_GKReply_tags_1)
++		/sizeof(asn_DEF_GKReply_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_GKReply_1,
++	2,	/* Elements count */
++	&asn_SPC_GKReply_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/GKReply.h b/asn1/asn1c/GKReply.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..7f058f6bf481ee2e570138f06fdef3d913949e9f
+--- /dev/null
++++ b/asn1/asn1c/GKReply.h
+@@ -0,0 +1,51 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_GKReply_H_
++#define	_GKReply_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include "Int32.h"
++#include <asn_SEQUENCE_OF.h>
++#include <constr_SEQUENCE_OF.h>
++#include <constr_SEQUENCE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Forward declarations */
++struct KrbKey;
++
++/* GKReply */
++typedef struct GKReply {
++	Int32_t	 newkvno;
++	struct keys {
++		A_SEQUENCE_OF(struct KrbKey) list;
++		
++		/* Context for parsing across buffer boundaries */
++		asn_struct_ctx_t _asn_ctx;
++	} keys;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} GKReply_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_GKReply;
++
++#ifdef __cplusplus
++}
++#endif
++
++/* Referred external types */
++#include "KrbKey.h"
++
++#endif	/* _GKReply_H_ */
+diff --git a/asn1/asn1c/GetKeytabControl.c b/asn1/asn1c/GetKeytabControl.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..65b55d1ef34e31b81ef7b751608da4cc6c12020c
+--- /dev/null
++++ b/asn1/asn1c/GetKeytabControl.c
+@@ -0,0 +1,77 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "GetKeytabControl.h"
++
++static asn_TYPE_member_t asn_MBR_GetKeytabControl_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct GetKeytabControl, choice.newkeys),
++		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_GKNewKeys,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"newkeys"
++		},
++	{ ATF_NOFLAGS, 0, offsetof(struct GetKeytabControl, choice.curkeys),
++		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_GKCurrentKeys,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"curkeys"
++		},
++	{ ATF_NOFLAGS, 0, offsetof(struct GetKeytabControl, choice.reply),
++		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_GKReply,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"reply"
++		},
++};
++static asn_TYPE_tag2member_t asn_MAP_GetKeytabControl_tag2el_1[] = {
++    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* newkeys at 7 */
++    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* curkeys at 8 */
++    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* reply at 10 */
++};
++static asn_CHOICE_specifics_t asn_SPC_GetKeytabControl_specs_1 = {
++	sizeof(struct GetKeytabControl),
++	offsetof(struct GetKeytabControl, _asn_ctx),
++	offsetof(struct GetKeytabControl, present),
++	sizeof(((struct GetKeytabControl *)0)->present),
++	asn_MAP_GetKeytabControl_tag2el_1,
++	3,	/* Count of tags in the map */
++	0,
++	-1	/* Extensions start */
++};
++asn_TYPE_descriptor_t asn_DEF_GetKeytabControl = {
++	"GetKeytabControl",
++	"GetKeytabControl",
++	CHOICE_free,
++	CHOICE_print,
++	CHOICE_constraint,
++	CHOICE_decode_ber,
++	CHOICE_encode_der,
++	CHOICE_decode_xer,
++	CHOICE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	CHOICE_outmost_tag,
++	0,	/* No effective tags (pointer) */
++	0,	/* No effective tags (count) */
++	0,	/* No tags (pointer) */
++	0,	/* No tags (count) */
++	0,	/* No PER visible constraints */
++	asn_MBR_GetKeytabControl_1,
++	3,	/* Elements count */
++	&asn_SPC_GetKeytabControl_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/GetKeytabControl.h b/asn1/asn1c/GetKeytabControl.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..5f5fcd22e74f65e9356be886520b8ddd3cac348c
+--- /dev/null
++++ b/asn1/asn1c/GetKeytabControl.h
+@@ -0,0 +1,52 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_GetKeytabControl_H_
++#define	_GetKeytabControl_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include "GKNewKeys.h"
++#include "GKCurrentKeys.h"
++#include "GKReply.h"
++#include <constr_CHOICE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Dependencies */
++typedef enum GetKeytabControl_PR {
++	GetKeytabControl_PR_NOTHING,	/* No components present */
++	GetKeytabControl_PR_newkeys,
++	GetKeytabControl_PR_curkeys,
++	GetKeytabControl_PR_reply
++} GetKeytabControl_PR;
++
++/* GetKeytabControl */
++typedef struct GetKeytabControl {
++	GetKeytabControl_PR present;
++	union GetKeytabControl_u {
++		GKNewKeys_t	 newkeys;
++		GKCurrentKeys_t	 curkeys;
++		GKReply_t	 reply;
++	} choice;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} GetKeytabControl_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_GetKeytabControl;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _GetKeytabControl_H_ */
+diff --git a/asn1/asn1c/INTEGER.c b/asn1/asn1c/INTEGER.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..9c8b9ed3a5d778c30185842ca04cc5d8f9ca058b
+--- /dev/null
++++ b/asn1/asn1c/INTEGER.c
+@@ -0,0 +1,835 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <INTEGER.h>
++#include <asn_codecs_prim.h>	/* Encoder and decoder of a primitive type */
++#include <errno.h>
++
++/*
++ * INTEGER basic type description.
++ */
++static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
++};
++asn_TYPE_descriptor_t asn_DEF_INTEGER = {
++	"INTEGER",
++	"INTEGER",
++	ASN__PRIMITIVE_TYPE_free,
++	INTEGER_print,
++	asn_generic_no_constraint,
++	ber_decode_primitive,
++	INTEGER_encode_der,
++	INTEGER_decode_xer,
++	INTEGER_encode_xer,
++	INTEGER_decode_uper,	/* Unaligned PER decoder */
++	INTEGER_encode_uper,	/* Unaligned PER encoder */
++	0, /* Use generic outmost tag fetcher */
++	asn_DEF_INTEGER_tags,
++	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
++	asn_DEF_INTEGER_tags,	/* Same as above */
++	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	0	/* No specifics */
++};
++
++/*
++ * Encode INTEGER type using DER.
++ */
++asn_enc_rval_t
++INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	INTEGER_t *st = (INTEGER_t *)sptr;
++
++	ASN_DEBUG("%s %s as INTEGER (tm=%d)",
++		cb?"Encoding":"Estimating", td->name, tag_mode);
++
++	/*
++	 * Canonicalize integer in the buffer.
++	 * (Remove too long sign extension, remove some first 0x00 bytes)
++	 */
++	if(st->buf) {
++		uint8_t *buf = st->buf;
++		uint8_t *end1 = buf + st->size - 1;
++		int shift;
++
++		/* Compute the number of superfluous leading bytes */
++		for(; buf < end1; buf++) {
++			/*
++			 * If the contents octets of an integer value encoding
++			 * consist of more than one octet, then the bits of the
++			 * first octet and bit 8 of the second octet:
++			 * a) shall not all be ones; and
++			 * b) shall not all be zero.
++			 */
++			switch(*buf) {
++			case 0x00: if((buf[1] & 0x80) == 0)
++					continue;
++				break;
++			case 0xff: if((buf[1] & 0x80))
++					continue;
++				break;
++			}
++			break;
++		}
++
++		/* Remove leading superfluous bytes from the integer */
++		shift = buf - st->buf;
++		if(shift) {
++			uint8_t *nb = st->buf;
++			uint8_t *end;
++
++			st->size -= shift;	/* New size, minus bad bytes */
++			end = nb + st->size;
++
++			for(; nb < end; nb++, buf++)
++				*nb = *buf;
++		}
++
++	} /* if(1) */
++
++	return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
++}
++
++static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop);
++
++/*
++ * INTEGER specific human-readable output.
++ */
++static ssize_t
++INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
++	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
++	char scratch[32];	/* Enough for 64-bit integer */
++	uint8_t *buf = st->buf;
++	uint8_t *buf_end = st->buf + st->size;
++	signed long accum;
++	ssize_t wrote = 0;
++	char *p;
++	int ret;
++
++	/*
++	 * Advance buf pointer until the start of the value's body.
++	 * This will make us able to process large integers using simple case,
++	 * when the actual value is small
++	 * (0x0000000000abcdef would yield a fine 0x00abcdef)
++	 */
++	/* Skip the insignificant leading bytes */
++	for(; buf < buf_end-1; buf++) {
++		switch(*buf) {
++		case 0x00: if((buf[1] & 0x80) == 0) continue; break;
++		case 0xff: if((buf[1] & 0x80) != 0) continue; break;
++		}
++		break;
++	}
++
++	/* Simple case: the integer size is small */
++	if((size_t)(buf_end - buf) <= sizeof(accum)) {
++		const asn_INTEGER_enum_map_t *el;
++		size_t scrsize;
++		char *scr;
++
++		if(buf == buf_end) {
++			accum = 0;
++		} else {
++			accum = (*buf & 0x80) ? -1 : 0;
++			for(; buf < buf_end; buf++)
++				accum = (accum << 8) | *buf;
++		}
++
++		el = INTEGER_map_value2enum(specs, accum);
++		if(el) {
++			scrsize = el->enum_len + 32;
++			scr = (char *)alloca(scrsize);
++			if(plainOrXER == 0)
++				ret = snprintf(scr, scrsize,
++					"%ld (%s)", accum, el->enum_name);
++			else
++				ret = snprintf(scr, scrsize,
++					"<%s/>", el->enum_name);
++		} else if(plainOrXER && specs && specs->strict_enumeration) {
++			ASN_DEBUG("ASN.1 forbids dealing with "
++				"unknown value of ENUMERATED type");
++			errno = EPERM;
++			return -1;
++		} else {
++			scrsize = sizeof(scratch);
++			scr = scratch;
++			ret = snprintf(scr, scrsize, "%ld", accum);
++		}
++		assert(ret > 0 && (size_t)ret < scrsize);
++		return (cb(scr, ret, app_key) < 0) ? -1 : ret;
++	} else if(plainOrXER && specs && specs->strict_enumeration) {
++		/*
++		 * Here and earlier, we cannot encode the ENUMERATED values
++		 * if there is no corresponding identifier.
++		 */
++		ASN_DEBUG("ASN.1 forbids dealing with "
++			"unknown value of ENUMERATED type");
++		errno = EPERM;
++		return -1;
++	}
++
++	/* Output in the long xx:yy:zz... format */
++	/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
++	for(p = scratch; buf < buf_end; buf++) {
++		static const char *h2c = "0123456789ABCDEF";
++		if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
++			/* Flush buffer */
++			if(cb(scratch, p - scratch, app_key) < 0)
++				return -1;
++			wrote += p - scratch;
++			p = scratch;
++		}
++		*p++ = h2c[*buf >> 4];
++		*p++ = h2c[*buf & 0x0F];
++		*p++ = 0x3a;	/* ":" */
++	}
++	if(p != scratch)
++		p--;	/* Remove the last ":" */
++
++	wrote += p - scratch;
++	return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
++}
++
++/*
++ * INTEGER specific human-readable output.
++ */
++int
++INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	const INTEGER_t *st = (const INTEGER_t *)sptr;
++	ssize_t ret;
++
++	(void)td;
++	(void)ilevel;
++
++	if(!st || !st->buf)
++		ret = cb("<absent>", 8, app_key);
++	else
++		ret = INTEGER__dump(td, st, cb, app_key, 0);
++
++	return (ret < 0) ? -1 : 0;
++}
++
++struct e2v_key {
++	const char *start;
++	const char *stop;
++	asn_INTEGER_enum_map_t *vemap;
++	unsigned int *evmap;
++};
++static int
++INTEGER__compar_enum2value(const void *kp, const void *am) {
++	const struct e2v_key *key = (const struct e2v_key *)kp;
++	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
++	const char *ptr, *end, *name;
++
++	/* Remap the element (sort by different criterion) */
++	el = key->vemap + key->evmap[el - key->vemap];
++
++	/* Compare strings */
++	for(ptr = key->start, end = key->stop, name = el->enum_name;
++			ptr < end; ptr++, name++) {
++		if(*ptr != *name)
++			return *(const unsigned char *)ptr
++				- *(const unsigned char *)name;
++	}
++	return name[0] ? -1 : 0;
++}
++
++static const asn_INTEGER_enum_map_t *
++INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
++	asn_INTEGER_enum_map_t *el_found;
++	int count = specs ? specs->map_count : 0;
++	struct e2v_key key;
++	const char *lp;
++
++	if(!count) return NULL;
++
++	/* Guaranteed: assert(lstart < lstop); */
++	/* Figure out the tag name */
++	for(lstart++, lp = lstart; lp < lstop; lp++) {
++		switch(*lp) {
++		case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
++		case 0x2f: /* '/' */ case 0x3e: /* '>' */
++			break;
++		default:
++			continue;
++		}
++		break;
++	}
++	if(lp == lstop) return NULL;	/* No tag found */
++	lstop = lp;
++
++	key.start = lstart;
++	key.stop = lstop;
++	key.vemap = specs->value2enum;
++	key.evmap = specs->enum2value;
++	el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
++		specs->value2enum, count, sizeof(specs->value2enum[0]),
++		INTEGER__compar_enum2value);
++	if(el_found) {
++		/* Remap enum2value into value2enum */
++		el_found = key.vemap + key.evmap[el_found - key.vemap];
++	}
++	return el_found;
++}
++
++static int
++INTEGER__compar_value2enum(const void *kp, const void *am) {
++	long a = *(const long *)kp;
++	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
++	long b = el->nat_value;
++	if(a < b) return -1;
++	else if(a == b) return 0;
++	else return 1;
++}
++
++const asn_INTEGER_enum_map_t *
++INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
++	int count = specs ? specs->map_count : 0;
++	if(!count) return 0;
++	return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
++		count, sizeof(specs->value2enum[0]),
++		INTEGER__compar_value2enum);
++}
++
++static int
++INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
++	void *p = MALLOC(min_size + 1);
++	if(p) {
++		void *b = st->buf;
++		st->size = 0;
++		st->buf = p;
++		FREEMEM(b);
++		return 0;
++	} else {
++		return -1;
++	}
++}
++
++/*
++ * Decode the chunk of XML text encoding INTEGER.
++ */
++static enum xer_pbd_rval
++INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
++	INTEGER_t *st = (INTEGER_t *)sptr;
++	long sign = 1;
++	long value;
++	const char *lp;
++	const char *lstart = (const char *)chunk_buf;
++	const char *lstop = lstart + chunk_size;
++	enum {
++		ST_SKIPSPACE,
++		ST_SKIPSPHEX,
++		ST_WAITDIGITS,
++		ST_DIGITS,
++		ST_HEXDIGIT1,
++		ST_HEXDIGIT2,
++		ST_HEXCOLON,
++		ST_EXTRASTUFF
++	} state = ST_SKIPSPACE;
++
++	if(chunk_size)
++		ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x",
++			chunk_size, *lstart, lstop[-1]);
++
++	/*
++	 * We may have received a tag here. It will be processed inline.
++	 * Use strtoul()-like code and serialize the result.
++	 */
++	for(value = 0, lp = lstart; lp < lstop; lp++) {
++		int lv = *lp;
++		switch(lv) {
++		case 0x09: case 0x0a: case 0x0d: case 0x20:
++			switch(state) {
++			case ST_SKIPSPACE:
++			case ST_SKIPSPHEX:
++				continue;
++			case ST_HEXCOLON:
++				if(xer_is_whitespace(lp, lstop - lp)) {
++					lp = lstop - 1;
++					continue;
++				}
++				break;
++			default:
++				break;
++			}
++			break;
++		case 0x2d:	/* '-' */
++			if(state == ST_SKIPSPACE) {
++				sign = -1;
++				state = ST_WAITDIGITS;
++				continue;
++			}
++			break;
++		case 0x2b:	/* '+' */
++			if(state == ST_SKIPSPACE) {
++				state = ST_WAITDIGITS;
++				continue;
++			}
++			break;
++		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
++		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
++			switch(state) {
++			case ST_DIGITS: break;
++			case ST_SKIPSPHEX:	/* Fall through */
++			case ST_HEXDIGIT1:
++				value = (lv - 0x30) << 4;
++				state = ST_HEXDIGIT2;
++				continue;
++			case ST_HEXDIGIT2:
++				value += (lv - 0x30);
++				state = ST_HEXCOLON;
++				st->buf[st->size++] = value;
++				continue;
++			case ST_HEXCOLON:
++				return XPBD_BROKEN_ENCODING;
++			default:
++				state = ST_DIGITS;
++				break;
++			}
++
++		    {
++			long new_value = value * 10;
++
++			if(new_value / 10 != value)
++				/* Overflow */
++				return XPBD_DECODER_LIMIT;
++
++			value = new_value + (lv - 0x30);
++			/* Check for two's complement overflow */
++			if(value < 0) {
++				/* Check whether it is a LONG_MIN */
++				if(sign == -1
++				&& (unsigned long)value
++						== ~((unsigned long)-1 >> 1)) {
++					sign = 1;
++				} else {
++					/* Overflow */
++					return XPBD_DECODER_LIMIT;
++				}
++			}
++		    }
++			continue;
++		case 0x3c:	/* '<' */
++			if(state == ST_SKIPSPACE) {
++				const asn_INTEGER_enum_map_t *el;
++				el = INTEGER_map_enum2value(
++					(asn_INTEGER_specifics_t *)
++					td->specifics, lstart, lstop);
++				if(el) {
++					ASN_DEBUG("Found \"%s\" => %ld",
++						el->enum_name, el->nat_value);
++					state = ST_DIGITS;
++					value = el->nat_value;
++					lp = lstop - 1;
++					continue;
++				}
++				ASN_DEBUG("Unknown identifier for INTEGER");
++			}
++			return XPBD_BROKEN_ENCODING;
++		case 0x3a:	/* ':' */
++			if(state == ST_HEXCOLON) {
++				/* This colon is expected */
++				state = ST_HEXDIGIT1;
++				continue;
++			} else if(state == ST_DIGITS) {
++				/* The colon here means that we have
++				 * decoded the first two hexadecimal
++				 * places as a decimal value.
++				 * Switch decoding mode. */
++				ASN_DEBUG("INTEGER re-evaluate as hex form");
++				if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
++					return XPBD_SYSTEM_FAILURE;
++				state = ST_SKIPSPHEX;
++				lp = lstart - 1;
++				continue;
++			} else {
++				ASN_DEBUG("state %d at %d", state, lp - lstart);
++				break;
++			}
++		/* [A-Fa-f] */
++		case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
++		case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
++			switch(state) {
++			case ST_SKIPSPHEX:
++			case ST_SKIPSPACE: /* Fall through */
++			case ST_HEXDIGIT1:
++				value = lv - ((lv < 0x61) ? 0x41 : 0x61);
++				value += 10;
++				value <<= 4;
++				state = ST_HEXDIGIT2;
++				continue;
++			case ST_HEXDIGIT2:
++				value += lv - ((lv < 0x61) ? 0x41 : 0x61);
++				value += 10;
++				st->buf[st->size++] = value;
++				state = ST_HEXCOLON;
++				continue;
++			case ST_DIGITS:
++				ASN_DEBUG("INTEGER re-evaluate as hex form");
++				if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
++					return XPBD_SYSTEM_FAILURE;
++				state = ST_SKIPSPHEX;
++				lp = lstart - 1;
++				continue;
++			default:
++				break;
++			}
++			break;
++		}
++
++		/* Found extra non-numeric stuff */
++		ASN_DEBUG("Found non-numeric 0x%2x at %d",
++			lv, lp - lstart);
++		state = ST_EXTRASTUFF;
++		break;
++	}
++
++	switch(state) {
++	case ST_DIGITS:
++		/* Everything is cool */
++		break;
++	case ST_HEXCOLON:
++		st->buf[st->size] = 0;	/* Just in case termination */
++		return XPBD_BODY_CONSUMED;
++	case ST_HEXDIGIT1:
++	case ST_HEXDIGIT2:
++	case ST_SKIPSPHEX:
++		return XPBD_BROKEN_ENCODING;
++	default:
++		if(xer_is_whitespace(lp, lstop - lp)) {
++			if(state != ST_EXTRASTUFF)
++				return XPBD_NOT_BODY_IGNORE;
++			break;
++		} else {
++			ASN_DEBUG("INTEGER: No useful digits (state %d)",
++				state);
++			return XPBD_BROKEN_ENCODING;	/* No digits */
++		}
++		break;
++	}
++
++	value *= sign;	/* Change sign, if needed */
++
++	if(asn_long2INTEGER(st, value))
++		return XPBD_SYSTEM_FAILURE;
++
++	return XPBD_BODY_CONSUMED;
++}
++
++asn_dec_rval_t
++INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
++		const void *buf_ptr, size_t size) {
++
++	return xer_decode_primitive(opt_codec_ctx, td,
++		sptr, sizeof(INTEGER_t), opt_mname,
++		buf_ptr, size, INTEGER__xer_body_decode);
++}
++
++asn_enc_rval_t
++INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	const INTEGER_t *st = (const INTEGER_t *)sptr;
++	asn_enc_rval_t er;
++
++	(void)ilevel;
++	(void)flags;
++	
++	if(!st || !st->buf)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
++	if(er.encoded < 0) _ASN_ENCODE_FAILED;
++
++	_ASN_ENCODED_OK(er);
++}
++
++asn_dec_rval_t
++INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
++	asn_dec_rval_t rval = { RC_OK, 0 };
++	INTEGER_t *st = (INTEGER_t *)*sptr;
++	asn_per_constraint_t *ct;
++	int repeat;
++
++	(void)opt_codec_ctx;
++
++	if(!st) {
++		st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
++		if(!st) _ASN_DECODE_FAILED;
++	}
++
++	if(!constraints) constraints = td->per_constraints;
++	ct = constraints ? &constraints->value : 0;
++
++	if(ct && ct->flags & APC_EXTENSIBLE) {
++		int inext = per_get_few_bits(pd, 1);
++		if(inext < 0) _ASN_DECODE_STARVED;
++		if(inext) ct = 0;
++	}
++
++	FREEMEM(st->buf);
++	if(ct) {
++		if(ct->flags & APC_SEMI_CONSTRAINED) {
++			st->buf = (uint8_t *)CALLOC(1, 2);
++			if(!st->buf) _ASN_DECODE_FAILED;
++			st->size = 1;
++		} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
++			size_t size = (ct->range_bits + 7) >> 3;
++			st->buf = (uint8_t *)MALLOC(1 + size + 1);
++			if(!st->buf) _ASN_DECODE_FAILED;
++			st->size = size;
++		} else {
++			st->size = 0;
++		}
++	} else {
++		st->size = 0;
++	}
++
++	/* X.691, #12.2.2 */
++	if(ct && ct->flags != APC_UNCONSTRAINED) {
++		/* #10.5.6 */
++		ASN_DEBUG("Integer with range %d bits", ct->range_bits);
++		if(ct->range_bits >= 0) {
++			long value = per_get_few_bits(pd, ct->range_bits);
++			if(value < 0) _ASN_DECODE_STARVED;
++			ASN_DEBUG("Got value %ld + low %ld",
++				value, ct->lower_bound);
++			value += ct->lower_bound;
++			if(asn_long2INTEGER(st, value))
++				_ASN_DECODE_FAILED;
++			return rval;
++		}
++	} else {
++		ASN_DEBUG("Decoding unconstrained integer %s", td->name);
++	}
++
++	/* X.691, #12.2.3, #12.2.4 */
++	do {
++		ssize_t len;
++		void *p;
++		int ret;
++
++		/* Get the PER length */
++		len = uper_get_length(pd, -1, &repeat);
++		if(len < 0) _ASN_DECODE_STARVED;
++
++		p = REALLOC(st->buf, st->size + len + 1);
++		if(!p) _ASN_DECODE_FAILED;
++		st->buf = (uint8_t *)p;
++
++		ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
++		if(ret < 0) _ASN_DECODE_STARVED;
++		st->size += len;
++	} while(repeat);
++	st->buf[st->size] = 0;	/* JIC */
++
++	/* #12.2.3 */
++	if(ct && ct->lower_bound) {
++		/*
++		 * TODO: replace by in-place arithmetics.
++		 */
++		long value;
++		if(asn_INTEGER2long(st, &value))
++			_ASN_DECODE_FAILED;
++		if(asn_long2INTEGER(st, value + ct->lower_bound))
++			_ASN_DECODE_FAILED;
++	}
++
++	return rval;
++}
++
++asn_enc_rval_t
++INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_enc_rval_t er;
++	INTEGER_t *st = (INTEGER_t *)sptr;
++	const uint8_t *buf;
++	const uint8_t *end;
++	asn_per_constraint_t *ct;
++	long value = 0;
++
++	if(!st || st->size == 0) _ASN_ENCODE_FAILED;
++
++	if(!constraints) constraints = td->per_constraints;
++	ct = constraints ? &constraints->value : 0;
++
++	er.encoded = 0;
++
++	if(ct) {
++		int inext = 0;
++		if(asn_INTEGER2long(st, &value))
++			_ASN_ENCODE_FAILED;
++		/* Check proper range */
++		if(ct->flags & APC_SEMI_CONSTRAINED) {
++			if(value < ct->lower_bound)
++				inext = 1;
++		} else if(ct->range_bits >= 0) {
++			if(value < ct->lower_bound
++			|| value > ct->upper_bound)
++				inext = 1;
++		}
++		ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
++			value, st->buf[0], st->size,
++			ct->lower_bound, ct->upper_bound,
++			inext ? "ext" : "fix");
++		if(ct->flags & APC_EXTENSIBLE) {
++			if(per_put_few_bits(po, inext, 1))
++				_ASN_ENCODE_FAILED;
++			if(inext) ct = 0;
++		} else if(inext) {
++			_ASN_ENCODE_FAILED;
++		}
++	}
++
++
++	/* X.691, #12.2.2 */
++	if(ct && ct->range_bits >= 0) {
++		/* #10.5.6 */
++		ASN_DEBUG("Encoding integer with range %d bits",
++			ct->range_bits);
++		if(per_put_few_bits(po, value - ct->lower_bound,
++				ct->range_bits))
++			_ASN_ENCODE_FAILED;
++		_ASN_ENCODED_OK(er);
++	}
++
++	if(ct && ct->lower_bound) {
++		ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
++		/* TODO: adjust lower bound */
++		_ASN_ENCODE_FAILED;
++	}
++
++	for(buf = st->buf, end = st->buf + st->size; buf < end;) {
++		ssize_t mayEncode = uper_put_length(po, end - buf);
++		if(mayEncode < 0)
++			_ASN_ENCODE_FAILED;
++		if(per_put_many_bits(po, buf, 8 * mayEncode))
++			_ASN_ENCODE_FAILED;
++		buf += mayEncode;
++	}
++
++	_ASN_ENCODED_OK(er);
++}
++
++int
++asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
++	uint8_t *b, *end;
++	size_t size;
++	long l;
++
++	/* Sanity checking */
++	if(!iptr || !iptr->buf || !lptr) {
++		errno = EINVAL;
++		return -1;
++	}
++
++	/* Cache the begin/end of the buffer */
++	b = iptr->buf;	/* Start of the INTEGER buffer */
++	size = iptr->size;
++	end = b + size;	/* Where to stop */
++
++	if(size > sizeof(long)) {
++		uint8_t *end1 = end - 1;
++		/*
++		 * Slightly more advanced processing,
++		 * able to >sizeof(long) bytes,
++		 * when the actual value is small
++		 * (0x0000000000abcdef would yield a fine 0x00abcdef)
++		 */
++		/* Skip out the insignificant leading bytes */
++		for(; b < end1; b++) {
++			switch(*b) {
++			case 0x00: if((b[1] & 0x80) == 0) continue; break;
++			case 0xff: if((b[1] & 0x80) != 0) continue; break;
++			}
++			break;
++		}
++
++		size = end - b;
++		if(size > sizeof(long)) {
++			/* Still cannot fit the long */
++			errno = ERANGE;
++			return -1;
++		}
++	}
++
++	/* Shortcut processing of a corner case */
++	if(end == b) {
++		*lptr = 0;
++		return 0;
++	}
++
++	/* Perform the sign initialization */
++	/* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
++	if((*b >> 7)) l = -1; else l = 0;
++
++	/* Conversion engine */
++	for(; b < end; b++)
++		l = (l << 8) | *b;
++
++	*lptr = l;
++	return 0;
++}
++
++int
++asn_long2INTEGER(INTEGER_t *st, long value) {
++	uint8_t *buf, *bp;
++	uint8_t *p;
++	uint8_t *pstart;
++	uint8_t *pend1;
++	int littleEndian = 1;	/* Run-time detection */
++	int add;
++
++	if(!st) {
++		errno = EINVAL;
++		return -1;
++	}
++
++	buf = (uint8_t *)MALLOC(sizeof(value));
++	if(!buf) return -1;
++
++	if(*(char *)&littleEndian) {
++		pstart = (uint8_t *)&value + sizeof(value) - 1;
++		pend1 = (uint8_t *)&value;
++		add = -1;
++	} else {
++		pstart = (uint8_t *)&value;
++		pend1 = pstart + sizeof(value) - 1;
++		add = 1;
++	}
++
++	/*
++	 * If the contents octet consists of more than one octet,
++	 * then bits of the first octet and bit 8 of the second octet:
++	 * a) shall not all be ones; and
++	 * b) shall not all be zero.
++	 */
++	for(p = pstart; p != pend1; p += add) {
++		switch(*p) {
++		case 0x00: if((*(p+add) & 0x80) == 0)
++				continue;
++			break;
++		case 0xff: if((*(p+add) & 0x80))
++				continue;
++			break;
++		}
++		break;
++	}
++	/* Copy the integer body */
++	for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
++		*bp++ = *p;
++
++	if(st->buf) FREEMEM(st->buf);
++	st->buf = buf;
++	st->size = bp - buf;
++
++	return 0;
++}
+diff --git a/asn1/asn1c/INTEGER.h b/asn1/asn1c/INTEGER.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..62832b12e1271e1f27a5edd5b4a0f82986ff2fc3
+--- /dev/null
++++ b/asn1/asn1c/INTEGER.h
+@@ -0,0 +1,65 @@
++/*-
++ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_INTEGER_H_
++#define	_INTEGER_H_
++
++#include <asn_application.h>
++#include <asn_codecs_prim.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
++
++extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
++
++/* Map with <tag> to integer value association */
++typedef struct asn_INTEGER_enum_map_s {
++	long		 nat_value;	/* associated native integer value */
++	size_t		 enum_len;	/* strlen("tag") */
++	const char	*enum_name;	/* "tag" */
++} asn_INTEGER_enum_map_t;
++
++/* This type describes an enumeration for INTEGER and ENUMERATED types */
++typedef struct asn_INTEGER_specifics_s {
++	asn_INTEGER_enum_map_t *value2enum;	/* N -> "tag"; sorted by N */
++	unsigned int *enum2value;		/* "tag" => N; sorted by tag */
++	int map_count;				/* Elements in either map */
++	int extension;				/* This map is extensible */
++	int strict_enumeration;			/* Enumeration set is fixed */
++} asn_INTEGER_specifics_t;
++
++asn_struct_print_f INTEGER_print;
++ber_type_decoder_f INTEGER_decode_ber;
++der_type_encoder_f INTEGER_encode_der;
++xer_type_decoder_f INTEGER_decode_xer;
++xer_type_encoder_f INTEGER_encode_xer;
++per_type_decoder_f INTEGER_decode_uper;
++per_type_encoder_f INTEGER_encode_uper;
++
++/***********************************
++ * Some handy conversion routines. *
++ ***********************************/
++
++/*
++ * Returns 0 if it was possible to convert, -1 otherwise.
++ * -1/EINVAL: Mandatory argument missing
++ * -1/ERANGE: Value encoded is out of range for long representation
++ * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
++ */
++int asn_INTEGER2long(const INTEGER_t *i, long *l);
++int asn_long2INTEGER(INTEGER_t *i, long l);
++
++/*
++ * Convert the integer value into the corresponding enumeration map entry.
++ */
++const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _INTEGER_H_ */
+diff --git a/asn1/asn1c/Int32.c b/asn1/asn1c/Int32.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..600934beed3fcff4527de4969c1d3effd272355e
+--- /dev/null
++++ b/asn1/asn1c/Int32.c
+@@ -0,0 +1,127 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "Int32.h"
++
++int
++Int32_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
++			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
++	long value;
++	
++	if(!sptr) {
++		_ASN_CTFAIL(app_key, td, sptr,
++			"%s: value not given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++	
++	value = *(const long *)sptr;
++	
++	if((value >= -2147483648 && value <= 2147483647)) {
++		/* Constraint check succeeded */
++		return 0;
++	} else {
++		_ASN_CTFAIL(app_key, td, sptr,
++			"%s: constraint failed (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++}
++
++/*
++ * This type is implemented using NativeInteger,
++ * so here we adjust the DEF accordingly.
++ */
++static void
++Int32_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
++	td->free_struct    = asn_DEF_NativeInteger.free_struct;
++	td->print_struct   = asn_DEF_NativeInteger.print_struct;
++	td->ber_decoder    = asn_DEF_NativeInteger.ber_decoder;
++	td->der_encoder    = asn_DEF_NativeInteger.der_encoder;
++	td->xer_decoder    = asn_DEF_NativeInteger.xer_decoder;
++	td->xer_encoder    = asn_DEF_NativeInteger.xer_encoder;
++	td->uper_decoder   = asn_DEF_NativeInteger.uper_decoder;
++	td->uper_encoder   = asn_DEF_NativeInteger.uper_encoder;
++	if(!td->per_constraints)
++		td->per_constraints = asn_DEF_NativeInteger.per_constraints;
++	td->elements       = asn_DEF_NativeInteger.elements;
++	td->elements_count = asn_DEF_NativeInteger.elements_count;
++	td->specifics      = asn_DEF_NativeInteger.specifics;
++}
++
++void
++Int32_free(asn_TYPE_descriptor_t *td,
++		void *struct_ptr, int contents_only) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	td->free_struct(td, struct_ptr, contents_only);
++}
++
++int
++Int32_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
++		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
++}
++
++asn_dec_rval_t
++Int32_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++		void **structure, const void *bufptr, size_t size, int tag_mode) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
++}
++
++asn_enc_rval_t
++Int32_encode_der(asn_TYPE_descriptor_t *td,
++		void *structure, int tag_mode, ber_tlv_tag_t tag,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
++}
++
++asn_dec_rval_t
++Int32_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
++}
++
++asn_enc_rval_t
++Int32_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
++		int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	Int32_1_inherit_TYPE_descriptor(td);
++	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
++}
++
++static ber_tlv_tag_t asn_DEF_Int32_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
++};
++asn_TYPE_descriptor_t asn_DEF_Int32 = {
++	"Int32",
++	"Int32",
++	Int32_free,
++	Int32_print,
++	Int32_constraint,
++	Int32_decode_ber,
++	Int32_encode_der,
++	Int32_decode_xer,
++	Int32_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_Int32_tags_1,
++	sizeof(asn_DEF_Int32_tags_1)
++		/sizeof(asn_DEF_Int32_tags_1[0]), /* 1 */
++	asn_DEF_Int32_tags_1,	/* Same as above */
++	sizeof(asn_DEF_Int32_tags_1)
++		/sizeof(asn_DEF_Int32_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	0	/* No specifics */
++};
++
+diff --git a/asn1/asn1c/Int32.h b/asn1/asn1c/Int32.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..9ee672ec9b5d49cfaddd2bf0bfb5ab2c5015d498
+--- /dev/null
++++ b/asn1/asn1c/Int32.h
+@@ -0,0 +1,38 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_Int32_H_
++#define	_Int32_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include <NativeInteger.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Int32 */
++typedef long	 Int32_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_Int32;
++asn_struct_free_f Int32_free;
++asn_struct_print_f Int32_print;
++asn_constr_check_f Int32_constraint;
++ber_type_decoder_f Int32_decode_ber;
++der_type_encoder_f Int32_encode_der;
++xer_type_decoder_f Int32_decode_xer;
++xer_type_encoder_f Int32_encode_xer;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _Int32_H_ */
+diff --git a/asn1/asn1c/KrbKey.c b/asn1/asn1c/KrbKey.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..3abbdf1b6e42ee759c149b6cbfa4b53695a2f0a3
+--- /dev/null
++++ b/asn1/asn1c/KrbKey.c
+@@ -0,0 +1,81 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "KrbKey.h"
++
++static asn_TYPE_member_t asn_MBR_KrbKey_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct KrbKey, key),
++		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_TypeValuePair,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"key"
++		},
++	{ ATF_POINTER, 2, offsetof(struct KrbKey, salt),
++		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_TypeValuePair,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"salt"
++		},
++	{ ATF_POINTER, 1, offsetof(struct KrbKey, s2kparams),
++		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_OCTET_STRING,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"s2kparams"
++		},
++};
++static ber_tlv_tag_t asn_DEF_KrbKey_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_TYPE_tag2member_t asn_MAP_KrbKey_tag2el_1[] = {
++    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* key at 28 */
++    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* salt at 29 */
++    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* s2kparams at 30 */
++};
++static asn_SEQUENCE_specifics_t asn_SPC_KrbKey_specs_1 = {
++	sizeof(struct KrbKey),
++	offsetof(struct KrbKey, _asn_ctx),
++	asn_MAP_KrbKey_tag2el_1,
++	3,	/* Count of tags in the map */
++	0, 0, 0,	/* Optional elements (not needed) */
++	-1,	/* Start extensions */
++	-1	/* Stop extensions */
++};
++asn_TYPE_descriptor_t asn_DEF_KrbKey = {
++	"KrbKey",
++	"KrbKey",
++	SEQUENCE_free,
++	SEQUENCE_print,
++	SEQUENCE_constraint,
++	SEQUENCE_decode_ber,
++	SEQUENCE_encode_der,
++	SEQUENCE_decode_xer,
++	SEQUENCE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_KrbKey_tags_1,
++	sizeof(asn_DEF_KrbKey_tags_1)
++		/sizeof(asn_DEF_KrbKey_tags_1[0]), /* 1 */
++	asn_DEF_KrbKey_tags_1,	/* Same as above */
++	sizeof(asn_DEF_KrbKey_tags_1)
++		/sizeof(asn_DEF_KrbKey_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_KrbKey_1,
++	3,	/* Elements count */
++	&asn_SPC_KrbKey_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/KrbKey.h b/asn1/asn1c/KrbKey.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..3134be528d1b9848b17d5eaee941aeef6fbd91b6
+--- /dev/null
++++ b/asn1/asn1c/KrbKey.h
+@@ -0,0 +1,46 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_KrbKey_H_
++#define	_KrbKey_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include "TypeValuePair.h"
++#include <OCTET_STRING.h>
++#include <constr_SEQUENCE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Forward declarations */
++struct TypeValuePair;
++
++/* KrbKey */
++typedef struct KrbKey {
++	TypeValuePair_t	 key;
++	struct TypeValuePair	*salt	/* OPTIONAL */;
++	OCTET_STRING_t	*s2kparams	/* OPTIONAL */;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} KrbKey_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_KrbKey;
++
++#ifdef __cplusplus
++}
++#endif
++
++/* Referred external types */
++#include "TypeValuePair.h"
++
++#endif	/* _KrbKey_H_ */
+diff --git a/asn1/asn1c/Makefile.am b/asn1/asn1c/Makefile.am
+new file mode 100644
+index 0000000000000000000000000000000000000000..e4ed6ab79fa776131b5baaaf7b5d254850c966c2
+--- /dev/null
++++ b/asn1/asn1c/Makefile.am
+@@ -0,0 +1,93 @@
++NULL =
++
++ASN1C_SOURCES =			\
++	INTEGER.c		\
++	NativeEnumerated.c	\
++	NativeInteger.c		\
++	asn_SEQUENCE_OF.c	\
++	asn_SET_OF.c		\
++	constr_CHOICE.c		\
++	constr_SEQUENCE.c	\
++	constr_SEQUENCE_OF.c	\
++	constr_SET_OF.c		\
++	OCTET_STRING.c		\
++	BIT_STRING.c		\
++	asn_codecs_prim.c	\
++	ber_tlv_length.c	\
++	ber_tlv_tag.c		\
++	ber_decoder.c		\
++	der_encoder.c		\
++	constr_TYPE.c		\
++	constraints.c		\
++	xer_support.c		\
++	xer_decoder.c		\
++	xer_encoder.c		\
++	per_support.c		\
++	per_decoder.c		\
++	per_encoder.c		\
++	$(NULL)
++
++ASN1C_HEADERS =
++	INTEGER.h		\
++	NativeEnumerated.h	\
++	NativeInteger.h		\
++	asn_SEQUENCE_OF.h	\
++	asn_SET_OF.h		\
++	constr_CHOICE.h		\
++	constr_SEQUENCE.h	\
++	constr_SEQUENCE_OF.h	\
++	constr_SET_OF.h		\
++	asn_application.h	\
++	asn_system.h		\
++	asn_codecs.h		\
++	asn_internal.h		\
++	OCTET_STRING.h		\
++	BIT_STRING.h		\
++	asn_codecs_prim.h	\
++	ber_tlv_length.h	\
++	ber_tlv_tag.h		\
++	ber_decoder.h		\
++	der_encoder.h		\
++	constr_TYPE.h		\
++	constraints.h		\
++	xer_support.h		\
++	xer_decoder.h		\
++	xer_encoder.h		\
++	per_support.h		\
++	per_decoder.h		\
++	per_encoder.h		\
++	$(NULL)
++
++ASN1Cdir = .
++
++IPAASN1_SOURCES=		\
++	Int32.c			\
++	GetKeytabControl.c	\
++	GKNewKeys.c		\
++	GKCurrentKeys.c		\
++	GKReply.c		\
++	KrbKey.c		\
++	TypeValuePair.c		\
++	$(NULL)
++
++IPAASN1_HEADERS=		\
++	Int32.h			\
++	GetKeytabControl.h	\
++	GKNewKeys.h		\
++	GKCurrentKeys.h		\
++	GKReply.h		\
++	KrbKey.h		\
++	TypeValuePair.h		\
++	$(NULL)
++
++IPAASN1dir = .
++
++AM_CPPFLAGS = -I../../util
++
++noinst_LTLIBRARIES=libasn1c.la
++noinst_HEADERS=$(ASN1C_HEADERS) $(IPAASN1_HEADERS)
++libasn1c_la_SOURCES=$(ASN1C_SOURCES) $(IPAASN1_SOURCES)
++
++regenerate:
++	asn1c -fskeletons-copy -fnative-types ipa.asn1
++	rm -f converter-sample.c Makefile.am.sample
+diff --git a/asn1/asn1c/NativeEnumerated.c b/asn1/asn1c/NativeEnumerated.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..e3af1ca49b2c722513876e70219bb0ac8e74cbd9
+--- /dev/null
++++ b/asn1/asn1c/NativeEnumerated.c
+@@ -0,0 +1,204 @@
++/*-
++ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * Read the NativeInteger.h for the explanation wrt. differences between
++ * INTEGER and NativeInteger.
++ * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
++ * implementation deals with the standard (machine-specific) representation
++ * of them instead of using the platform-independent buffer.
++ */
++#include <asn_internal.h>
++#include <NativeEnumerated.h>
++
++/*
++ * NativeEnumerated basic type description.
++ */
++static ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
++};
++asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
++	"ENUMERATED",			/* The ASN.1 type is still ENUMERATED */
++	"ENUMERATED",
++	NativeInteger_free,
++	NativeInteger_print,
++	asn_generic_no_constraint,
++	NativeInteger_decode_ber,
++	NativeInteger_encode_der,
++	NativeInteger_decode_xer,
++	NativeEnumerated_encode_xer,
++	NativeEnumerated_decode_uper,
++	NativeEnumerated_encode_uper,
++	0, /* Use generic outmost tag fetcher */
++	asn_DEF_NativeEnumerated_tags,
++	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
++	asn_DEF_NativeEnumerated_tags,	/* Same as above */
++	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	0	/* No specifics */
++};
++
++asn_enc_rval_t
++NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++        int ilevel, enum xer_encoder_flags_e flags,
++                asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
++        asn_enc_rval_t er;
++        const long *native = (const long *)sptr;
++	const asn_INTEGER_enum_map_t *el;
++
++        (void)ilevel;
++        (void)flags;
++
++        if(!native) _ASN_ENCODE_FAILED;
++
++	el = INTEGER_map_value2enum(specs, *native);
++	if(el) {
++		size_t srcsize = el->enum_len + 5;
++		char *src = (char *)alloca(srcsize);
++
++		er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
++		assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
++		if(cb(src, er.encoded, app_key) < 0) _ASN_ENCODE_FAILED;
++		_ASN_ENCODED_OK(er);
++	} else {
++		ASN_DEBUG("ASN.1 forbids dealing with "
++			"unknown value of ENUMERATED type");
++		_ASN_ENCODE_FAILED;
++	}
++}
++
++asn_dec_rval_t
++NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
++	void **sptr, asn_per_data_t *pd) {
++	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
++	asn_dec_rval_t rval = { RC_OK, 0 };
++	long *native = (long *)*sptr;
++	asn_per_constraint_t *ct;
++	long value;
++
++	(void)opt_codec_ctx;
++
++	if(constraints) ct = &constraints->value;
++	else if(td->per_constraints) ct = &td->per_constraints->value;
++	else _ASN_DECODE_FAILED;	/* Mandatory! */
++	if(!specs) _ASN_DECODE_FAILED;
++
++	if(!native) {
++		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
++		if(!native) _ASN_DECODE_FAILED;
++	}
++
++	ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
++
++	if(ct->flags & APC_EXTENSIBLE) {
++		int inext = per_get_few_bits(pd, 1);
++		if(inext < 0) _ASN_DECODE_STARVED;
++		if(inext) ct = 0;
++	}
++
++	if(ct && ct->range_bits >= 0) {
++		value = per_get_few_bits(pd, ct->range_bits);
++		if(value < 0) _ASN_DECODE_STARVED;
++		if(value >= (specs->extension
++			? specs->extension - 1 : specs->map_count))
++			_ASN_DECODE_FAILED;
++	} else {
++		if(!specs->extension)
++			_ASN_DECODE_FAILED;
++		/*
++		 * X.691, #10.6: normally small non-negative whole number;
++		 */
++		value = uper_get_nsnnwn(pd);
++		if(value < 0) _ASN_DECODE_STARVED;
++		value += specs->extension - 1;
++		if(value >= specs->map_count)
++			_ASN_DECODE_FAILED;
++	}
++
++	*native = specs->value2enum[value].nat_value;
++	ASN_DEBUG("Decoded %s = %ld", td->name, *native);
++
++	return rval;
++}
++
++static int
++NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
++	const asn_INTEGER_enum_map_t *a = ap;
++	const asn_INTEGER_enum_map_t *b = bp;
++	if(a->nat_value == b->nat_value)
++		return 0;
++	if(a->nat_value < b->nat_value)
++		return -1;
++	return 1;
++}
++
++asn_enc_rval_t
++NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
++	asn_enc_rval_t er;
++	long native, value;
++	asn_per_constraint_t *ct;
++	int inext = 0;
++	asn_INTEGER_enum_map_t key;
++	asn_INTEGER_enum_map_t *kf;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++	if(!specs) _ASN_ENCODE_FAILED;
++
++	if(constraints) ct = &constraints->value;
++	else if(td->per_constraints) ct = &td->per_constraints->value;
++	else _ASN_ENCODE_FAILED;	/* Mandatory! */
++
++	ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
++
++	er.encoded = 0;
++
++	native = *(long *)sptr;
++	if(native < 0) _ASN_ENCODE_FAILED;
++
++	key.nat_value = native;
++	kf = bsearch(&key, specs->value2enum, specs->map_count,
++		sizeof(key), NativeEnumerated__compar_value2enum);
++	if(!kf) {
++		ASN_DEBUG("No element corresponds to %ld", native);
++		_ASN_ENCODE_FAILED;
++	}
++	value = kf - specs->value2enum;
++
++	if(ct->range_bits >= 0) {
++		int cmpWith = specs->extension
++				? specs->extension - 1 : specs->map_count;
++		if(value >= cmpWith)
++			inext = 1;
++	}
++	if(ct->flags & APC_EXTENSIBLE) {
++		if(per_put_few_bits(po, inext, 0))
++			_ASN_ENCODE_FAILED;
++		ct = 0;
++	} else if(inext) {
++		_ASN_ENCODE_FAILED;
++	}
++
++	if(ct && ct->range_bits >= 0) {
++		if(per_put_few_bits(po, value, ct->range_bits))
++			_ASN_ENCODE_FAILED;
++		_ASN_ENCODED_OK(er);
++	}
++
++	if(!specs->extension)
++		_ASN_ENCODE_FAILED;
++
++	/*
++	 * X.691, #10.6: normally small non-negative whole number;
++	 */
++	if(uper_put_nsnnwn(po, value - (specs->extension - 1)))
++		_ASN_ENCODE_FAILED;
++
++	_ASN_ENCODED_OK(er);
++}
++
+diff --git a/asn1/asn1c/NativeEnumerated.h b/asn1/asn1c/NativeEnumerated.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..c59bb1ba9438f85d3c42c99bba3a02aa917f0837
+--- /dev/null
++++ b/asn1/asn1c/NativeEnumerated.h
+@@ -0,0 +1,32 @@
++/*-
++ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * This type differs from the standard ENUMERATED in that it is modelled using
++ * the fixed machine type (long, int, short), so it can hold only values of
++ * limited length. There is no type (i.e., NativeEnumerated_t, any integer type
++ * will do).
++ * This type may be used when integer range is limited by subtype constraints.
++ */
++#ifndef	_NativeEnumerated_H_
++#define	_NativeEnumerated_H_
++
++#include <NativeInteger.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
++
++xer_type_encoder_f NativeEnumerated_encode_xer;
++per_type_decoder_f NativeEnumerated_decode_uper;
++per_type_encoder_f NativeEnumerated_encode_uper;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _NativeEnumerated_H_ */
+diff --git a/asn1/asn1c/NativeInteger.c b/asn1/asn1c/NativeInteger.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..34599f6186cd77d38106e171ec3b24cb29638afa
+--- /dev/null
++++ b/asn1/asn1c/NativeInteger.c
+@@ -0,0 +1,314 @@
++/*-
++ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * Read the NativeInteger.h for the explanation wrt. differences between
++ * INTEGER and NativeInteger.
++ * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
++ * implementation deals with the standard (machine-specific) representation
++ * of them instead of using the platform-independent buffer.
++ */
++#include <asn_internal.h>
++#include <NativeInteger.h>
++
++/*
++ * NativeInteger basic type description.
++ */
++static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
++};
++asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
++	"INTEGER",			/* The ASN.1 type is still INTEGER */
++	"INTEGER",
++	NativeInteger_free,
++	NativeInteger_print,
++	asn_generic_no_constraint,
++	NativeInteger_decode_ber,
++	NativeInteger_encode_der,
++	NativeInteger_decode_xer,
++	NativeInteger_encode_xer,
++	NativeInteger_decode_uper,	/* Unaligned PER decoder */
++	NativeInteger_encode_uper,	/* Unaligned PER encoder */
++	0, /* Use generic outmost tag fetcher */
++	asn_DEF_NativeInteger_tags,
++	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
++	asn_DEF_NativeInteger_tags,	/* Same as above */
++	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	0	/* No specifics */
++};
++
++/*
++ * Decode INTEGER type.
++ */
++asn_dec_rval_t
++NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td,
++	void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
++	long *native = (long *)*nint_ptr;
++	asn_dec_rval_t rval;
++	ber_tlv_len_t length;
++
++	/*
++	 * If the structure is not there, allocate it.
++	 */
++	if(native == NULL) {
++		native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
++		if(native == NULL) {
++			rval.code = RC_FAIL;
++			rval.consumed = 0;
++			return rval;
++		}
++	}
++
++	ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
++		td->name, tag_mode);
++
++	/*
++	 * Check tags.
++	 */
++	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
++			tag_mode, 0, &length, 0);
++	if(rval.code != RC_OK)
++		return rval;
++
++	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
++
++	/*
++	 * Make sure we have this length.
++	 */
++	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
++	size -= rval.consumed;
++	if(length > (ber_tlv_len_t)size) {
++		rval.code = RC_WMORE;
++		rval.consumed = 0;
++		return rval;
++	}
++
++	/*
++	 * ASN.1 encoded INTEGER: buf_ptr, length
++	 * Fill the native, at the same time checking for overflow.
++	 * If overflow occured, return with RC_FAIL.
++	 */
++	{
++		INTEGER_t tmp;
++		union {
++			const void *constbuf;
++			void *nonconstbuf;
++		} unconst_buf;
++		long l;
++
++		unconst_buf.constbuf = buf_ptr;
++		tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
++		tmp.size = length;
++
++		if(asn_INTEGER2long(&tmp, &l)) {
++			rval.code = RC_FAIL;
++			rval.consumed = 0;
++			return rval;
++		}
++
++		*native = l;
++	}
++
++	rval.code = RC_OK;
++	rval.consumed += length;
++
++	ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
++		(long)rval.consumed, (long)length, td->name, (long)*native);
++
++	return rval;
++}
++
++/*
++ * Encode the NativeInteger using the standard INTEGER type DER encoder.
++ */
++asn_enc_rval_t
++NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	unsigned long native = *(unsigned long *)ptr;	/* Disable sign ext. */
++	asn_enc_rval_t erval;
++	INTEGER_t tmp;
++
++#ifdef	WORDS_BIGENDIAN		/* Opportunistic optimization */
++
++	tmp.buf = (uint8_t *)&native;
++	tmp.size = sizeof(native);
++
++#else	/* Works even if WORDS_BIGENDIAN is not set where should've been */
++	uint8_t buf[sizeof(native)];
++	uint8_t *p;
++
++	/* Prepare a fake INTEGER */
++	for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
++		*p = native;
++
++	tmp.buf = buf;
++	tmp.size = sizeof(buf);
++#endif	/* WORDS_BIGENDIAN */
++	
++	/* Encode fake INTEGER */
++	erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
++	if(erval.encoded == -1) {
++		assert(erval.structure_ptr == &tmp);
++		erval.structure_ptr = ptr;
++	}
++	return erval;
++}
++
++/*
++ * Decode the chunk of XML text encoding INTEGER.
++ */
++asn_dec_rval_t
++NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
++		const void *buf_ptr, size_t size) {
++	asn_dec_rval_t rval;
++	INTEGER_t st;
++	void *st_ptr = (void *)&st;
++	long *native = (long *)*sptr;
++
++	if(!native) {
++		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
++		if(!native) _ASN_DECODE_FAILED;
++	}
++
++	memset(&st, 0, sizeof(st));
++	rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, 
++		opt_mname, buf_ptr, size);
++	if(rval.code == RC_OK) {
++		long l;
++		if(asn_INTEGER2long(&st, &l)) {
++			rval.code = RC_FAIL;
++			rval.consumed = 0;
++		} else {
++			*native = l;
++		}
++	} else {
++		/*
++		 * Cannot restart from the middle;
++		 * there is no place to save state in the native type.
++		 * Request a continuation from the very beginning.
++		 */
++		rval.consumed = 0;
++	}
++	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
++	return rval;
++}
++
++
++asn_enc_rval_t
++NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	char scratch[32];	/* Enough for 64-bit int */
++	asn_enc_rval_t er;
++	const long *native = (const long *)sptr;
++
++	(void)ilevel;
++	(void)flags;
++
++	if(!native) _ASN_ENCODE_FAILED;
++
++	er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native);
++	if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
++		|| cb(scratch, er.encoded, app_key) < 0)
++		_ASN_ENCODE_FAILED;
++
++	_ASN_ENCODED_OK(er);
++}
++
++asn_dec_rval_t
++NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
++
++	asn_dec_rval_t rval;
++	long *native = (long *)*sptr;
++	INTEGER_t tmpint;
++	void *tmpintptr = &tmpint;
++
++	(void)opt_codec_ctx;
++	ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
++
++	if(!native) {
++		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
++		if(!native) _ASN_DECODE_FAILED;
++	}
++
++	memset(&tmpint, 0, sizeof tmpint);
++	rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
++				   &tmpintptr, pd);
++	if(rval.code == RC_OK) {
++		if(asn_INTEGER2long(&tmpint, native))
++			rval.code = RC_FAIL;
++		else
++			ASN_DEBUG("NativeInteger %s got value %ld",
++				td->name, *native);
++	}
++	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
++
++	return rval;
++}
++
++asn_enc_rval_t
++NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_enc_rval_t er;
++	long native;
++	INTEGER_t tmpint;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++
++	native = *(long *)sptr;
++
++	ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
++
++	memset(&tmpint, 0, sizeof(tmpint));
++	if(asn_long2INTEGER(&tmpint, native))
++		_ASN_ENCODE_FAILED;
++	er = INTEGER_encode_uper(td, constraints, &tmpint, po);
++	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
++	return er;
++}
++
++/*
++ * INTEGER specific human-readable output.
++ */
++int
++NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	const long *native = (const long *)sptr;
++	char scratch[32];	/* Enough for 64-bit int */
++	int ret;
++
++	(void)td;	/* Unused argument */
++	(void)ilevel;	/* Unused argument */
++
++	if(native) {
++		ret = snprintf(scratch, sizeof(scratch), "%ld", *native);
++		assert(ret > 0 && (size_t)ret < sizeof(scratch));
++		return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
++	} else {
++		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++	}
++}
++
++void
++NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
++
++	if(!td || !ptr)
++		return;
++
++	ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
++		td->name, contents_only, ptr);
++
++	if(!contents_only) {
++		FREEMEM(ptr);
++	}
++}
++
+diff --git a/asn1/asn1c/NativeInteger.h b/asn1/asn1c/NativeInteger.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..4e63a8355d12b7c90ce53a23a43cb5583f811257
+--- /dev/null
++++ b/asn1/asn1c/NativeInteger.h
+@@ -0,0 +1,37 @@
++/*-
++ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * This type differs from the standard INTEGER in that it is modelled using
++ * the fixed machine type (long, int, short), so it can hold only values of
++ * limited length. There is no type (i.e., NativeInteger_t, any integer type
++ * will do).
++ * This type may be used when integer range is limited by subtype constraints.
++ */
++#ifndef	_NativeInteger_H_
++#define	_NativeInteger_H_
++
++#include <asn_application.h>
++#include <INTEGER.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
++
++asn_struct_free_f  NativeInteger_free;
++asn_struct_print_f NativeInteger_print;
++ber_type_decoder_f NativeInteger_decode_ber;
++der_type_encoder_f NativeInteger_encode_der;
++xer_type_decoder_f NativeInteger_decode_xer;
++xer_type_encoder_f NativeInteger_encode_xer;
++per_type_decoder_f NativeInteger_decode_uper;
++per_type_encoder_f NativeInteger_encode_uper;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _NativeInteger_H_ */
+diff --git a/asn1/asn1c/OCTET_STRING.c b/asn1/asn1c/OCTET_STRING.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..3a83bd98c5b30a10b5fb12b78bd4f317e8abb27a
+--- /dev/null
++++ b/asn1/asn1c/OCTET_STRING.c
+@@ -0,0 +1,1550 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <OCTET_STRING.h>
++#include <BIT_STRING.h>	/* for .bits_unused member */
++#include <errno.h>
++
++/*
++ * OCTET STRING basic type description.
++ */
++static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
++};
++static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
++	sizeof(OCTET_STRING_t),
++	offsetof(OCTET_STRING_t, _asn_ctx),
++	0
++};
++static asn_per_constraint_t asn_DEF_OCTET_STRING_constraint = {
++	APC_SEMI_CONSTRAINED, -1, -1, 0, 0
++};
++asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
++	"OCTET STRING",		/* Canonical name */
++	"OCTET_STRING",		/* XML tag name */
++	OCTET_STRING_free,
++	OCTET_STRING_print,	/* non-ascii stuff, generally */
++	asn_generic_no_constraint,
++	OCTET_STRING_decode_ber,
++	OCTET_STRING_encode_der,
++	OCTET_STRING_decode_xer_hex,
++	OCTET_STRING_encode_xer,
++	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
++	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
++	0, /* Use generic outmost tag fetcher */
++	asn_DEF_OCTET_STRING_tags,
++	sizeof(asn_DEF_OCTET_STRING_tags)
++	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
++	asn_DEF_OCTET_STRING_tags,	/* Same as above */
++	sizeof(asn_DEF_OCTET_STRING_tags)
++	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
++	0,	/* No PER visible constraints */
++	0, 0,	/* No members */
++	&asn_DEF_OCTET_STRING_specs
++};
++
++#undef	_CH_PHASE
++#undef	NEXT_PHASE
++#undef	PREV_PHASE
++#define	_CH_PHASE(ctx, inc) do {					\
++		if(ctx->phase == 0)					\
++			ctx->context = 0;				\
++		ctx->phase += inc;					\
++	} while(0)
++#define	NEXT_PHASE(ctx)	_CH_PHASE(ctx, +1)
++#define	PREV_PHASE(ctx)	_CH_PHASE(ctx, -1)
++
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {					\
++		size_t num = (num_bytes);				\
++		buf_ptr = ((const char *)buf_ptr) + num;		\
++		size -= num;						\
++		consumed_myself += num;					\
++	} while(0)
++
++#undef	RETURN
++#define	RETURN(_code)	do {						\
++		asn_dec_rval_t tmprval;					\
++		tmprval.code = _code;					\
++		tmprval.consumed = consumed_myself;			\
++		return tmprval;						\
++	} while(0)
++
++#undef	APPEND
++#define	APPEND(bufptr, bufsize)	do {					\
++		size_t _bs = (bufsize);		/* Append size */	\
++		size_t _ns = ctx->context;	/* Allocated now */	\
++		size_t _es = st->size + _bs;	/* Expected size */	\
++		/* int is really a typeof(st->size): */			\
++		if((int)_es < 0) RETURN(RC_FAIL);			\
++		if(_ns <= _es) {					\
++			void *ptr;					\
++			/* Be nice and round to the memory allocator */	\
++			do { _ns = _ns ? _ns << 1 : 16; }		\
++			    while(_ns <= _es);				\
++			/* int is really a typeof(st->size): */		\
++			if((int)_ns < 0) RETURN(RC_FAIL);		\
++			ptr = REALLOC(st->buf, _ns);			\
++			if(ptr) {					\
++				st->buf = (uint8_t *)ptr;		\
++				ctx->context = _ns;			\
++			} else {					\
++				RETURN(RC_FAIL);			\
++			}						\
++			ASN_DEBUG("Reallocating into %ld", (long)_ns);	\
++		}							\
++		memcpy(st->buf + st->size, bufptr, _bs);		\
++		/* Convenient nul-termination */			\
++		st->buf[_es] = '\0';					\
++		st->size = _es;						\
++	} while(0)
++
++/*
++ * Internal variant of the OCTET STRING.
++ */
++typedef enum OS_type {
++	_TT_GENERIC	= 0,	/* Just a random OCTET STRING */
++	_TT_BIT_STRING	= 1,	/* BIT STRING type, a special case */
++	_TT_ANY		= 2	/* ANY type, a special case too */
++} OS_type_e;
++
++/*
++ * The main reason why ASN.1 is still alive is that too much time and effort
++ * is necessary for learning it more or less adequately, thus creating a gut
++ * necessity to demonstrate that aquired skill everywhere afterwards.
++ * No, I am not going to explain what the following stuff is.
++ */
++struct _stack_el {
++	ber_tlv_len_t	left;	/* What's left to read (or -1) */
++	ber_tlv_len_t	got;	/* What was actually processed */
++	int	cont_level;	/* Depth of subcontainment */
++	int	want_nulls;	/* Want null "end of content" octets? */
++	int	bits_chopped;	/* Flag in BIT STRING mode */
++	ber_tlv_tag_t	tag;	/* For debugging purposes */
++	struct _stack_el *prev;
++	struct _stack_el *next;
++};
++struct _stack {
++	struct _stack_el *tail;
++	struct _stack_el *cur_ptr;
++};
++
++static struct _stack_el *
++OS__add_stack_el(struct _stack *st) {
++	struct _stack_el *nel;
++
++	/*
++	 * Reuse the old stack frame or allocate a new one.
++	 */
++	if(st->cur_ptr && st->cur_ptr->next) {
++		nel = st->cur_ptr->next;
++		nel->bits_chopped = 0;
++		nel->got = 0;
++		/* Retain the nel->cont_level, it's correct. */
++	} else {
++		nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
++		if(nel == NULL)
++			return NULL;
++	
++		if(st->tail) {
++			/* Increase a subcontainment depth */
++			nel->cont_level = st->tail->cont_level + 1;
++			st->tail->next = nel;
++		}
++		nel->prev = st->tail;
++		st->tail = nel;
++	}
++
++	st->cur_ptr = nel;
++
++	return nel;
++}
++
++static struct _stack *
++_new_stack() {
++	return (struct _stack *)CALLOC(1, sizeof(struct _stack));
++}
++
++/*
++ * Decode OCTET STRING type.
++ */
++asn_dec_rval_t
++OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td,
++	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++				? (asn_OCTET_STRING_specifics_t *)td->specifics
++				: &asn_DEF_OCTET_STRING_specs;
++	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
++	asn_dec_rval_t rval;
++	asn_struct_ctx_t *ctx;
++	ssize_t consumed_myself = 0;
++	struct _stack *stck;		/* Expectations stack structure */
++	struct _stack_el *sel = 0;	/* Stack element */
++	int tlv_constr;
++	OS_type_e type_variant = (OS_type_e)specs->subvariant;
++
++	ASN_DEBUG("Decoding %s as %s (frame %ld)",
++		td->name,
++		(type_variant == _TT_GENERIC) ?
++			"OCTET STRING" : "OS-SpecialCase",
++		(long)size);
++
++	/*
++	 * Create the string if does not exist.
++	 */
++	if(st == NULL) {
++		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
++		if(st == NULL) RETURN(RC_FAIL);
++	}
++
++	/* Restore parsing context */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++
++	switch(ctx->phase) {
++	case 0:
++		/*
++		 * Check tags.
++		 */
++		rval = ber_check_tags(opt_codec_ctx, td, ctx,
++			buf_ptr, size, tag_mode, -1,
++			&ctx->left, &tlv_constr);
++		if(rval.code != RC_OK)
++			return rval;
++
++		if(tlv_constr) {
++			/*
++			 * Complex operation, requires stack of expectations.
++			 */
++			ctx->ptr = _new_stack();
++			if(ctx->ptr) {
++				stck = (struct _stack *)ctx->ptr;
++			} else {
++				RETURN(RC_FAIL);
++			}
++		} else {
++			/*
++			 * Jump into stackless primitive decoding.
++			 */
++			_CH_PHASE(ctx, 3);
++			if(type_variant == _TT_ANY && tag_mode != 1)
++				APPEND(buf_ptr, rval.consumed);
++			ADVANCE(rval.consumed);
++			goto phase3;
++		}
++
++		NEXT_PHASE(ctx);
++		/* Fall through */
++	case 1:
++	phase1:
++		/*
++		 * Fill the stack with expectations.
++		 */
++		stck = (struct _stack *)ctx->ptr;
++		sel = stck->cur_ptr;
++	  do {
++		ber_tlv_tag_t tlv_tag;
++		ber_tlv_len_t tlv_len;
++		ber_tlv_tag_t expected_tag;
++		ssize_t tl, ll, tlvl;
++				/* This one works even if (sel->left == -1) */
++		ssize_t Left = ((!sel||(size_t)sel->left >= size)
++					?(ssize_t)size:sel->left);
++
++
++		ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
++			(long)(sel?sel->left:0),
++			(long)(sel?sel->want_nulls:0),
++			(long)(sel?sel->got:0)
++		);
++		if(sel && sel->left <= 0 && sel->want_nulls == 0) {
++			if(sel->prev) {
++				struct _stack_el *prev = sel->prev;
++				if(prev->left != -1) {
++					if(prev->left < sel->got)
++						RETURN(RC_FAIL);
++					prev->left -= sel->got;
++				}
++				prev->got += sel->got;
++				sel = stck->cur_ptr = prev;
++				if(!sel) break;
++				tlv_constr = 1;
++				continue;
++			} else {
++				sel = stck->cur_ptr = 0;
++				break;	/* Nothing to wait */
++			}
++		}
++
++		tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
++		ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
++			(long)size, (long)Left, sel?"":"!",
++			(long)(sel?sel->left:0),
++			(long)(sel?sel->want_nulls:0),
++			(long)tl);
++		switch(tl) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++
++		tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
++
++		ll = ber_fetch_length(tlv_constr,
++				(const char *)buf_ptr + tl,Left - tl,&tlv_len);
++		ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
++			ber_tlv_tag_string(tlv_tag), tlv_constr,
++				(long)Left, (long)tl, (long)tlv_len, (long)ll);
++		switch(ll) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++
++		if(sel && sel->want_nulls
++			&& ((const uint8_t *)buf_ptr)[0] == 0
++			&& ((const uint8_t *)buf_ptr)[1] == 0)
++		{
++
++			ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
++
++			if(type_variant == _TT_ANY
++			&& (tag_mode != 1 || sel->cont_level))
++				APPEND("\0\0", 2);
++
++			ADVANCE(2);
++			sel->got += 2;
++			if(sel->left != -1) {
++				sel->left -= 2;	/* assert(sel->left >= 2) */
++			}
++
++			sel->want_nulls--;
++			if(sel->want_nulls == 0) {
++				/* Move to the next expectation */
++				sel->left = 0;
++				tlv_constr = 1;
++			}
++
++			continue;
++		}
++
++		/*
++		 * Set up expected tags,
++		 * depending on ASN.1 type being decoded.
++		 */
++		switch(type_variant) {
++		case _TT_BIT_STRING:
++			/* X.690: 8.6.4.1, NOTE 2 */
++			/* Fall through */
++		case _TT_GENERIC:
++		default:
++			if(sel) {
++				int level = sel->cont_level;
++				if(level < td->all_tags_count) {
++					expected_tag = td->all_tags[level];
++					break;
++				} else if(td->all_tags_count) {
++					expected_tag = td->all_tags
++						[td->all_tags_count - 1];
++					break;
++				}
++				/* else, Fall through */
++			}
++			/* Fall through */
++		case _TT_ANY:
++			expected_tag = tlv_tag;
++			break;
++		}
++
++
++		if(tlv_tag != expected_tag) {
++			char buf[2][32];
++			ber_tlv_tag_snprint(tlv_tag,
++				buf[0], sizeof(buf[0]));
++			ber_tlv_tag_snprint(td->tags[td->tags_count-1],
++				buf[1], sizeof(buf[1]));
++			ASN_DEBUG("Tag does not match expectation: %s != %s",
++				buf[0], buf[1]);
++			RETURN(RC_FAIL);
++		}
++
++		tlvl = tl + ll;	/* Combined length of T and L encoding */
++		if((tlv_len + tlvl) < 0) {
++			/* tlv_len value is too big */
++			ASN_DEBUG("TLV encoding + length (%ld) is too big",
++				(long)tlv_len);
++			RETURN(RC_FAIL);
++		}
++
++		/*
++		 * Append a new expectation.
++		 */
++		sel = OS__add_stack_el(stck);
++		if(!sel) RETURN(RC_FAIL);
++
++		sel->tag = tlv_tag;
++
++		sel->want_nulls = (tlv_len==-1);
++		if(sel->prev && sel->prev->left != -1) {
++			/* Check that the parent frame is big enough */
++			if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
++				RETURN(RC_FAIL);
++			if(tlv_len == -1)
++				sel->left = sel->prev->left - tlvl;
++			else
++				sel->left = tlv_len;
++		} else {
++			sel->left = tlv_len;
++		}
++		if(type_variant == _TT_ANY
++		&& (tag_mode != 1 || sel->cont_level))
++			APPEND(buf_ptr, tlvl);
++		sel->got += tlvl;
++		ADVANCE(tlvl);
++
++		ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
++			(long)sel->got, (long)sel->left,
++			sel->want_nulls, sel->cont_level);
++
++	  } while(tlv_constr);
++		if(sel == NULL) {
++			/* Finished operation, "phase out" */
++			ASN_DEBUG("Phase out");
++			_CH_PHASE(ctx, +3);
++			break;
++		}
++
++		NEXT_PHASE(ctx);
++		/* Fall through */
++	case 2:
++		stck = (struct _stack *)ctx->ptr;
++		sel = stck->cur_ptr;
++		ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
++			(long)sel->left, (long)size, (long)sel->got,
++				sel->want_nulls);
++	    {
++		ber_tlv_len_t len;
++
++		assert(sel->left >= 0);
++
++		len = ((ber_tlv_len_t)size < sel->left)
++				? (ber_tlv_len_t)size : sel->left;
++		if(len > 0) {
++			if(type_variant == _TT_BIT_STRING
++			&& sel->bits_chopped == 0) {
++				/* Put the unused-bits-octet away */
++				st->bits_unused = *(const uint8_t *)buf_ptr;
++				APPEND(((const char *)buf_ptr+1), (len - 1));
++				sel->bits_chopped = 1;
++			} else {
++				APPEND(buf_ptr, len);
++			}
++			ADVANCE(len);
++			sel->left -= len;
++			sel->got += len;
++		}
++
++		if(sel->left) {
++			ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
++				(long)sel->left, (long)size, sel->want_nulls);
++			RETURN(RC_WMORE);
++		}
++
++		PREV_PHASE(ctx);
++		goto phase1;
++	    }
++		break;
++	case 3:
++	phase3:
++		/*
++		 * Primitive form, no stack required.
++		 */
++		assert(ctx->left >= 0);
++
++		if(size < (size_t)ctx->left) {
++			if(!size) RETURN(RC_WMORE);
++			if(type_variant == _TT_BIT_STRING && !ctx->context) {
++				st->bits_unused = *(const uint8_t *)buf_ptr;
++				ctx->left--;
++				ADVANCE(1);
++			}
++			APPEND(buf_ptr, size);
++			assert(ctx->context > 0);
++			ctx->left -= size;
++			ADVANCE(size);
++			RETURN(RC_WMORE);
++		} else {
++			if(type_variant == _TT_BIT_STRING
++			&& !ctx->context && ctx->left) {
++				st->bits_unused = *(const uint8_t *)buf_ptr;
++				ctx->left--;
++				ADVANCE(1);
++			}
++			APPEND(buf_ptr, ctx->left);
++			ADVANCE(ctx->left);
++			ctx->left = 0;
++
++			NEXT_PHASE(ctx);
++		}
++		break;
++	}
++
++	if(sel) {
++		ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
++			sel->prev, sel->want_nulls,
++			(long)sel->left, (long)sel->got, (long)size);
++		if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
++			RETURN(RC_WMORE);
++		}
++	}
++
++	/*
++	 * BIT STRING-specific processing.
++	 */
++	if(type_variant == _TT_BIT_STRING && st->size) {
++		/* Finalize BIT STRING: zero out unused bits. */
++		st->buf[st->size-1] &= 0xff << st->bits_unused;
++	}
++
++	ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
++		(long)consumed_myself, td->name,
++		(type_variant == _TT_GENERIC) ? (char *)st->buf : "<data>",
++		(long)st->size);
++
++
++	RETURN(RC_OK);
++}
++
++/*
++ * Encode OCTET STRING type using DER.
++ */
++asn_enc_rval_t
++OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er;
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++				? (asn_OCTET_STRING_specifics_t *)td->specifics
++				: &asn_DEF_OCTET_STRING_specs;
++	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
++	OS_type_e type_variant = (OS_type_e)specs->subvariant;
++	int fix_last_byte = 0;
++
++	ASN_DEBUG("%s %s as OCTET STRING",
++		cb?"Estimating":"Encoding", td->name);
++
++	/*
++	 * Write tags.
++	 */
++	if(type_variant != _TT_ANY || tag_mode == 1) {
++		er.encoded = der_write_tags(td,
++				(type_variant == _TT_BIT_STRING) + st->size,
++			tag_mode, type_variant == _TT_ANY, tag, cb, app_key);
++		if(er.encoded == -1) {
++			er.failed_type = td;
++			er.structure_ptr = sptr;
++			return er;
++		}
++	} else {
++		/* Disallow: [<tag>] IMPLICIT ANY */
++		assert(type_variant != _TT_ANY || tag_mode != -1);
++		er.encoded = 0;
++	}
++
++	if(!cb) {
++		er.encoded += (type_variant == _TT_BIT_STRING) + st->size;
++		_ASN_ENCODED_OK(er);
++	}
++
++	/*
++	 * Prepare to deal with the last octet of BIT STRING.
++	 */
++	if(type_variant == _TT_BIT_STRING) {
++		uint8_t b = st->bits_unused & 0x07;
++		if(b && st->size) fix_last_byte = 1;
++		_ASN_CALLBACK(&b, 1);
++		er.encoded++;
++	}
++
++	/* Invoke callback for the main part of the buffer */
++	_ASN_CALLBACK(st->buf, st->size - fix_last_byte);
++
++	/* The last octet should be stripped off the unused bits */
++	if(fix_last_byte) {
++		uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
++		_ASN_CALLBACK(&b, 1);
++	}
++
++	er.encoded += st->size;
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++asn_enc_rval_t
++OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	static const char *h2c = "0123456789ABCDEF";
++	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
++	asn_enc_rval_t er;
++	char scratch[16 * 3 + 4];
++	char *p = scratch;
++	uint8_t *buf;
++	uint8_t *end;
++	size_t i;
++
++	if(!st || !st->buf)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = 0;
++
++	/*
++	 * Dump the contents of the buffer in hexadecimal.
++	 */
++	buf = st->buf;
++	end = buf + st->size;
++	if(flags & XER_F_CANONICAL) {
++		char *scend = scratch + (sizeof(scratch) - 2);
++		for(; buf < end; buf++) {
++			if(p >= scend) {
++				_ASN_CALLBACK(scratch, p - scratch);
++				er.encoded += p - scratch;
++				p = scratch;
++			}
++			*p++ = h2c[(*buf >> 4) & 0x0F];
++			*p++ = h2c[*buf & 0x0F];
++		}
++
++		_ASN_CALLBACK(scratch, p-scratch);	/* Dump the rest */
++		er.encoded += p - scratch;
++	} else {
++		for(i = 0; buf < end; buf++, i++) {
++			if(!(i % 16) && (i || st->size > 16)) {
++				_ASN_CALLBACK(scratch, p-scratch);
++				er.encoded += (p-scratch);
++				p = scratch;
++				_i_ASN_TEXT_INDENT(1, ilevel);
++			}
++			*p++ = h2c[(*buf >> 4) & 0x0F];
++			*p++ = h2c[*buf & 0x0F];
++			*p++ = 0x20;
++		}
++		if(p - scratch) {
++			p--;	/* Remove the tail space */
++			_ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
++			er.encoded += p - scratch;
++			if(st->size > 16)
++				_i_ASN_TEXT_INDENT(1, ilevel-1);
++		}
++	}
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++static struct OCTET_STRING__xer_escape_table_s {
++	char *string;
++	int size;
++} OCTET_STRING__xer_escape_table[] = {
++#define	OSXET(s)	{ s, sizeof(s) - 1 }
++	OSXET("\074\156\165\154\057\076"),	/* <nul/> */
++	OSXET("\074\163\157\150\057\076"),	/* <soh/> */
++	OSXET("\074\163\164\170\057\076"),	/* <stx/> */
++	OSXET("\074\145\164\170\057\076"),	/* <etx/> */
++	OSXET("\074\145\157\164\057\076"),	/* <eot/> */
++	OSXET("\074\145\156\161\057\076"),	/* <enq/> */
++	OSXET("\074\141\143\153\057\076"),	/* <ack/> */
++	OSXET("\074\142\145\154\057\076"),	/* <bel/> */
++	OSXET("\074\142\163\057\076"),		/* <bs/> */
++	OSXET("\011"),				/* \t */
++	OSXET("\012"),				/* \n */
++	OSXET("\074\166\164\057\076"),		/* <vt/> */
++	OSXET("\074\146\146\057\076"),		/* <ff/> */
++	OSXET("\015"),				/* \r */
++	OSXET("\074\163\157\057\076"),		/* <so/> */
++	OSXET("\074\163\151\057\076"),		/* <si/> */
++	OSXET("\074\144\154\145\057\076"),	/* <dle/> */
++	OSXET("\074\144\143\061\057\076"),	/* <de1/> */
++	OSXET("\074\144\143\062\057\076"),	/* <de2/> */
++	OSXET("\074\144\143\063\057\076"),	/* <de3/> */
++	OSXET("\074\144\143\064\057\076"),	/* <de4/> */
++	OSXET("\074\156\141\153\057\076"),	/* <nak/> */
++	OSXET("\074\163\171\156\057\076"),	/* <syn/> */
++	OSXET("\074\145\164\142\057\076"),	/* <etb/> */
++	OSXET("\074\143\141\156\057\076"),	/* <can/> */
++	OSXET("\074\145\155\057\076"),		/* <em/> */
++	OSXET("\074\163\165\142\057\076"),	/* <sub/> */
++	OSXET("\074\145\163\143\057\076"),	/* <esc/> */
++	OSXET("\074\151\163\064\057\076"),	/* <is4/> */
++	OSXET("\074\151\163\063\057\076"),	/* <is3/> */
++	OSXET("\074\151\163\062\057\076"),	/* <is2/> */
++	OSXET("\074\151\163\061\057\076"),	/* <is1/> */
++	{ 0, 0 },	/* " " */
++	{ 0, 0 },	/* ! */
++	{ 0, 0 },	/* \" */
++	{ 0, 0 },	/* # */
++	{ 0, 0 },	/* $ */
++	{ 0, 0 },	/* % */
++	OSXET("\046\141\155\160\073"),	/* &amp; */
++	{ 0, 0 },	/* ' */
++	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
++	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
++	{0,0},{0,0},{0,0},{0,0},			 /* 89:; */
++	OSXET("\046\154\164\073"),	/* &lt; */
++	{ 0, 0 },	/* = */
++	OSXET("\046\147\164\073"),	/* &gt; */
++};
++
++static int
++OS__check_escaped_control_char(const void *buf, int size) {
++	size_t i;
++	/*
++	 * Inefficient algorithm which translates the escape sequences
++	 * defined above into characters. Returns -1 if not found.
++	 * TODO: replace by a faster algorithm (bsearch(), hash or
++	 * nested table lookups).
++	 */
++	for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
++		struct OCTET_STRING__xer_escape_table_s *el;
++		el = &OCTET_STRING__xer_escape_table[i];
++		if(el->size == size && memcmp(buf, el->string, size) == 0)
++			return i;
++	}
++	return -1;
++}
++
++static int
++OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
++	/*
++	 * This might be one of the escape sequences
++	 * for control characters. Check it out.
++	 * #11.15.5
++	 */
++	int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
++	if(control_char >= 0) {
++		OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
++		void *p = REALLOC(st->buf, st->size + 2);
++		if(p) {
++			st->buf = (uint8_t *)p;
++			st->buf[st->size++] = control_char;
++			st->buf[st->size] = '\0';	/* nul-termination */
++			return 0;
++		}
++	}
++	
++	return -1;	/* No, it's not */
++}
++
++asn_enc_rval_t
++OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
++	asn_enc_rval_t er;
++	uint8_t *buf, *end;
++	uint8_t *ss;	/* Sequence start */
++	ssize_t encoded_len = 0;
++
++	(void)ilevel;	/* Unused argument */
++	(void)flags;	/* Unused argument */
++
++	if(!st || !st->buf)
++		_ASN_ENCODE_FAILED;
++
++	buf = st->buf;
++	end = buf + st->size;
++	for(ss = buf; buf < end; buf++) {
++		unsigned int ch = *buf;
++		int s_len;	/* Special encoding sequence length */
++
++		/*
++		 * Escape certain characters: X.680/11.15
++		 */
++		if(ch < sizeof(OCTET_STRING__xer_escape_table)
++			/sizeof(OCTET_STRING__xer_escape_table[0])
++		&& (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
++			if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
++			|| cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
++					app_key) < 0)
++				_ASN_ENCODE_FAILED;
++			encoded_len += (buf - ss) + s_len;
++			ss = buf + 1;
++		}
++	}
++
++	encoded_len += (buf - ss);
++	if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = encoded_len;
++	_ASN_ENCODED_OK(er);
++}
++
++/*
++ * Convert from hexadecimal format (cstring): "AB CD EF"
++ */
++static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
++	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
++	const char *chunk_stop = (const char *)chunk_buf;
++	const char *p = chunk_stop;
++	const char *pend = p + chunk_size;
++	unsigned int clv = 0;
++	int half = 0;	/* Half bit */
++	uint8_t *buf;
++
++	/* Reallocate buffer according to high cap estimation */
++	ssize_t _ns = st->size + (chunk_size + 1) / 2;
++	void *nptr = REALLOC(st->buf, _ns + 1);
++	if(!nptr) return -1;
++	st->buf = (uint8_t *)nptr;
++	buf = st->buf + st->size;
++
++	/*
++	 * If something like " a b c " appears here, the " a b":3 will be
++	 * converted, and the rest skipped. That is, unless buf_size is greater
++	 * than chunk_size, then it'll be equivalent to "ABC0".
++	 */
++	for(; p < pend; p++) {
++		int ch = *(const unsigned char *)p;
++		switch(ch) {
++		case 0x09: case 0x0a: case 0x0c: case 0x0d:
++		case 0x20:
++			/* Ignore whitespace */
++			continue;
++		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
++		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
++			clv = (clv << 4) + (ch - 0x30);
++			break;
++		case 0x41: case 0x42: case 0x43:	/* ABC */
++		case 0x44: case 0x45: case 0x46:	/* DEF */
++			clv = (clv << 4) + (ch - 0x41 + 10);
++			break;
++		case 0x61: case 0x62: case 0x63:	/* abc */
++		case 0x64: case 0x65: case 0x66:	/* def */
++			clv = (clv << 4) + (ch - 0x61 + 10);
++			break;
++		default:
++			*buf = 0;	/* JIC */
++			return -1;
++		}
++		if(half++) {
++			half = 0;
++			*buf++ = clv;
++			chunk_stop = p + 1;
++		}
++	}
++
++	/*
++	 * Check partial decoding.
++	 */
++	if(half) {
++		if(have_more) {
++			/*
++			 * Partial specification is fine,
++			 * because no more more PXER_TEXT data is available.
++			 */
++			*buf++ = clv << 4;
++			chunk_stop = p;
++		}
++	} else {
++		chunk_stop = p;
++	}
++
++	st->size = buf - st->buf;	/* Adjust the buffer size */
++	assert(st->size <= _ns);
++	st->buf[st->size] = 0;		/* Courtesy termination */
++
++	return (chunk_stop - (const char *)chunk_buf);	/* Converted size */
++}
++
++/*
++ * Convert from binary format: "00101011101"
++ */
++static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
++	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
++	const char *p = (const char *)chunk_buf;
++	const char *pend = p + chunk_size;
++	int bits_unused = st->bits_unused & 0x7;
++	uint8_t *buf;
++
++	/* Reallocate buffer according to high cap estimation */
++	ssize_t _ns = st->size + (chunk_size + 7) / 8;
++	void *nptr = REALLOC(st->buf, _ns + 1);
++	if(!nptr) return -1;
++	st->buf = (uint8_t *)nptr;
++	buf = st->buf + st->size;
++
++	(void)have_more;
++
++	if(bits_unused == 0)
++		bits_unused = 8;
++	else if(st->size)
++		buf--;
++
++	/*
++	 * Convert series of 0 and 1 into the octet string.
++	 */
++	for(; p < pend; p++) {
++		int ch = *(const unsigned char *)p;
++		switch(ch) {
++		case 0x09: case 0x0a: case 0x0c: case 0x0d:
++		case 0x20:
++			/* Ignore whitespace */
++			break;
++		case 0x30:
++		case 0x31:
++			if(bits_unused-- <= 0) {
++				*++buf = 0;	/* Clean the cell */
++				bits_unused = 7;
++			}
++			*buf |= (ch&1) << bits_unused;
++			break;
++		default:
++			st->bits_unused = bits_unused;
++			return -1;
++		}
++	}
++
++	if(bits_unused == 8) {
++		st->size = buf - st->buf;
++		st->bits_unused = 0;
++	} else {
++		st->size = buf - st->buf + 1;
++		st->bits_unused = bits_unused;
++	}
++
++	assert(st->size <= _ns);
++	st->buf[st->size] = 0;		/* Courtesy termination */
++
++	return chunk_size;	/* Converted in full */
++}
++
++/*
++ * Something like strtod(), but with stricter rules.
++ */
++static int
++OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
++	int32_t val = 0;
++	const char *p;
++
++	for(p = buf; p < end; p++) {
++		int ch = *p;
++
++		/* Strange huge value */
++		if((val * base + base) < 0)
++			return -1;
++
++		switch(ch) {
++		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
++		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
++			val = val * base + (ch - 0x30);
++			break;
++		case 0x41: case 0x42: case 0x43:	/* ABC */
++		case 0x44: case 0x45: case 0x46:	/* DEF */
++			val = val * base + (ch - 0x41 + 10);
++			break;
++		case 0x61: case 0x62: case 0x63:	/* abc */
++		case 0x64: case 0x65: case 0x66:	/* def */
++			val = val * base + (ch - 0x61 + 10);
++			break;
++		case 0x3b:	/* ';' */
++			*ret_value = val;
++			return (p - buf) + 1;
++		default:
++			return -1;	/* Character set error */
++		}
++	}
++
++	*ret_value = -1;
++	return (p - buf);
++}
++
++/*
++ * Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
++ */
++static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
++	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
++	const char *p = (const char *)chunk_buf;
++	const char *pend = p + chunk_size;
++	uint8_t *buf;
++
++	/* Reallocate buffer */
++	ssize_t _ns = st->size + chunk_size;
++	void *nptr = REALLOC(st->buf, _ns + 1);
++	if(!nptr) return -1;
++	st->buf = (uint8_t *)nptr;
++	buf = st->buf + st->size;
++
++	/*
++	 * Convert series of 0 and 1 into the octet string.
++	 */
++	for(; p < pend; p++) {
++		int ch = *(const unsigned char *)p;
++		int len;	/* Length of the rest of the chunk */
++
++		if(ch != 0x26 /* '&' */) {
++			*buf++ = ch;
++			continue;	/* That was easy... */
++		}
++
++		/*
++		 * Process entity reference.
++		 */
++		len = chunk_size - (p - (const char *)chunk_buf);
++		if(len == 1 /* "&" */) goto want_more;
++		if(p[1] == 0x23 /* '#' */) {
++			const char *pval;	/* Pointer to start of digits */
++			int32_t val = 0;	/* Entity reference value */
++			int base;
++
++			if(len == 2 /* "&#" */) goto want_more;
++			if(p[2] == 0x78 /* 'x' */)
++				pval = p + 3, base = 16;
++			else
++				pval = p + 2, base = 10;
++			len = OS__strtoent(base, pval, p + len, &val);
++			if(len == -1) {
++				/* Invalid charset. Just copy verbatim. */
++				*buf++ = ch;
++				continue;
++			}
++			if(!len || pval[len-1] != 0x3b) goto want_more;
++			assert(val > 0);
++			p += (pval - p) + len - 1; /* Advance past entref */
++
++			if(val < 0x80) {
++				*buf++ = (char)val;
++			} else if(val < 0x800) {
++				*buf++ = 0xc0 | ((val >> 6));
++				*buf++ = 0x80 | ((val & 0x3f));
++			} else if(val < 0x10000) {
++				*buf++ = 0xe0 | ((val >> 12));
++				*buf++ = 0x80 | ((val >> 6) & 0x3f);
++				*buf++ = 0x80 | ((val & 0x3f));
++			} else if(val < 0x200000) {
++				*buf++ = 0xf0 | ((val >> 18));
++				*buf++ = 0x80 | ((val >> 12) & 0x3f);
++				*buf++ = 0x80 | ((val >> 6) & 0x3f);
++				*buf++ = 0x80 | ((val & 0x3f));
++			} else if(val < 0x4000000) {
++				*buf++ = 0xf8 | ((val >> 24));
++				*buf++ = 0x80 | ((val >> 18) & 0x3f);
++				*buf++ = 0x80 | ((val >> 12) & 0x3f);
++				*buf++ = 0x80 | ((val >> 6) & 0x3f);
++				*buf++ = 0x80 | ((val & 0x3f));
++			} else {
++				*buf++ = 0xfc | ((val >> 30) & 0x1);
++				*buf++ = 0x80 | ((val >> 24) & 0x3f);
++				*buf++ = 0x80 | ((val >> 18) & 0x3f);
++				*buf++ = 0x80 | ((val >> 12) & 0x3f);
++				*buf++ = 0x80 | ((val >> 6) & 0x3f);
++				*buf++ = 0x80 | ((val & 0x3f));
++			}
++		} else {
++			/*
++			 * Ugly, limited parsing of &amp; &gt; &lt;
++			 */
++			char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
++			if(!sc) goto want_more;
++			if((sc - p) == 4
++				&& p[1] == 0x61	/* 'a' */
++				&& p[2] == 0x6d	/* 'm' */
++				&& p[3] == 0x70	/* 'p' */) {
++				*buf++ = 0x26;
++				p = sc;
++				continue;
++			}
++			if((sc - p) == 3) {
++				if(p[1] == 0x6c) {
++					*buf = 0x3c;	/* '<' */
++				} else if(p[1] == 0x67) {
++					*buf = 0x3e;	/* '>' */
++				} else {
++					/* Unsupported entity reference */
++					*buf++ = ch;
++					continue;
++				}
++				if(p[2] != 0x74) {
++					/* Unsupported entity reference */
++					*buf++ = ch;
++					continue;
++				}
++				buf++;
++				p = sc;
++				continue;
++			}
++			/* Unsupported entity reference */
++			*buf++ = ch;
++		}
++
++		continue;
++	want_more:
++		if(have_more) {
++			/*
++			 * We know that no more data (of the same type)
++			 * is coming. Copy the rest verbatim.
++			 */
++			*buf++ = ch;
++			continue;
++		}
++		chunk_size = (p - (const char *)chunk_buf);
++		/* Processing stalled: need more data */
++		break;
++	}
++
++	st->size = buf - st->buf;
++	assert(st->size <= _ns);
++	st->buf[st->size] = 0;		/* Courtesy termination */
++
++	return chunk_size;	/* Converted in full */
++}
++
++/*
++ * Decode OCTET STRING from the XML element's body.
++ */
++static asn_dec_rval_t
++OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr,
++	const char *opt_mname, const void *buf_ptr, size_t size,
++	int (*opt_unexpected_tag_decoder)
++		(void *struct_ptr, const void *chunk_buf, size_t chunk_size),
++	ssize_t (*body_receiver)
++		(void *struct_ptr, const void *chunk_buf, size_t chunk_size,
++			int have_more)
++) {
++	OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++				? (asn_OCTET_STRING_specifics_t *)td->specifics
++				: &asn_DEF_OCTET_STRING_specs;
++	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
++	asn_struct_ctx_t *ctx;		/* Per-structure parser context */
++	asn_dec_rval_t rval;		/* Return value from the decoder */
++	int st_allocated;
++
++	/*
++	 * Create the string if does not exist.
++	 */
++	if(!st) {
++		st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
++		*sptr = (void *)st;
++		if(!st) goto sta_failed;
++		st_allocated = 1;
++	} else {
++		st_allocated = 0;
++	}
++	if(!st->buf) {
++		/* This is separate from above section */
++		st->buf = (uint8_t *)CALLOC(1, 1);
++		if(!st->buf) {
++			if(st_allocated) {
++				*sptr = 0;
++				goto stb_failed;
++			} else {
++				goto sta_failed;
++			}
++		}
++	}
++
++	/* Restore parsing context */
++	ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
++
++	return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
++		buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
++
++stb_failed:
++	FREEMEM(st);
++sta_failed:
++	rval.code = RC_FAIL;
++	rval.consumed = 0;
++	return rval;
++}
++
++/*
++ * Decode OCTET STRING from the hexadecimal data.
++ */
++asn_dec_rval_t
++OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr,
++		const char *opt_mname, const void *buf_ptr, size_t size) {
++	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
++		buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
++}
++
++/*
++ * Decode OCTET STRING from the binary (0/1) data.
++ */
++asn_dec_rval_t
++OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr,
++		const char *opt_mname, const void *buf_ptr, size_t size) {
++	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
++		buf_ptr, size, 0, OCTET_STRING__convert_binary);
++}
++
++/*
++ * Decode OCTET STRING from the string (ASCII/UTF-8) data.
++ */
++asn_dec_rval_t
++OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, void **sptr,
++		const char *opt_mname, const void *buf_ptr, size_t size) {
++	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
++		buf_ptr, size,
++		OCTET_STRING__handle_control_chars,
++		OCTET_STRING__convert_entrefs);
++}
++
++asn_dec_rval_t
++OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
++	void **sptr, asn_per_data_t *pd) {
++
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++		? (asn_OCTET_STRING_specifics_t *)td->specifics
++		: &asn_DEF_OCTET_STRING_specs;
++	asn_per_constraint_t *ct = constraints ? &constraints->size
++				: (td->per_constraints
++					? &td->per_constraints->size
++					: &asn_DEF_OCTET_STRING_constraint);
++	asn_dec_rval_t rval = { RC_OK, 0 };
++	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
++	ssize_t consumed_myself = 0;
++	int repeat;
++	int unit_bits = (specs->subvariant != 1) * 7 + 1;
++
++	(void)opt_codec_ctx;
++
++	/*
++	 * Allocate the string.
++	 */
++	if(!st) {
++		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
++		if(!st) RETURN(RC_FAIL);
++	}
++
++	ASN_DEBUG("PER Decoding %s %ld .. %ld bits %d",
++		ct->flags & APC_EXTENSIBLE ? "extensible" : "fixed",
++		ct->lower_bound, ct->upper_bound, ct->effective_bits);
++
++	if(ct->flags & APC_EXTENSIBLE) {
++		int inext = per_get_few_bits(pd, 1);
++		if(inext < 0) RETURN(RC_WMORE);
++		if(inext) ct = &asn_DEF_OCTET_STRING_constraint;
++		consumed_myself = 0;
++	}
++
++	if(ct->effective_bits >= 0
++	&& (!st->buf || st->size < ct->upper_bound)) {
++		FREEMEM(st->buf);
++		if(unit_bits == 1) {
++			st->size = (ct->upper_bound + 7) >> 3;
++		} else {
++			st->size = ct->upper_bound;
++		}
++		st->buf = (uint8_t *)MALLOC(st->size + 1);
++		if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
++	}
++
++	/* X.691, #16.5: zero-length encoding */
++	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
++	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
++	if(ct->effective_bits == 0) {
++		int ret = per_get_many_bits(pd, st->buf, 0,
++					    unit_bits * ct->upper_bound);
++		if(ret < 0) RETURN(RC_WMORE);
++		consumed_myself += unit_bits * ct->upper_bound;
++		st->buf[st->size] = 0;
++		if(unit_bits == 1 && (ct->upper_bound & 0x7))
++			st->bits_unused = 8 - (ct->upper_bound & 0x7);
++		RETURN(RC_OK);
++	}
++
++	st->size = 0;
++	do {
++		ssize_t len_bytes;
++		ssize_t len_bits;
++		void *p;
++		int ret;
++
++		/* Get the PER length */
++		len_bits = uper_get_length(pd, ct->effective_bits, &repeat);
++		if(len_bits < 0) RETURN(RC_WMORE);
++		len_bits += ct->lower_bound;
++
++		ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
++			(long)ct->effective_bits, (long)len_bits,
++			repeat ? "repeat" : "once", td->name);
++		if(unit_bits == 1) {
++			len_bytes = (len_bits + 7) >> 3;
++			if(len_bits & 0x7)
++				st->bits_unused = 8 - (len_bits & 0x7);
++			/* len_bits be multiple of 16K if repeat is set */
++		} else {
++			len_bytes = len_bits;
++			len_bits = len_bytes << 3;
++		}
++		p = REALLOC(st->buf, st->size + len_bytes + 1);
++		if(!p) RETURN(RC_FAIL);
++		st->buf = (uint8_t *)p;
++
++		ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
++		if(ret < 0) RETURN(RC_WMORE);
++		st->size += len_bytes;
++	} while(repeat);
++	st->buf[st->size] = 0;	/* nul-terminate */
++
++	return rval;
++}
++
++asn_enc_rval_t
++OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
++        asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++		? (asn_OCTET_STRING_specifics_t *)td->specifics
++		: &asn_DEF_OCTET_STRING_specs;
++	asn_per_constraint_t *ct = constraints ? &constraints->size
++				: (td->per_constraints
++					? &td->per_constraints->size
++					: &asn_DEF_OCTET_STRING_constraint);
++	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
++	int unit_bits = (specs->subvariant != 1) * 7 + 1;
++	asn_enc_rval_t er;
++	int ct_extensible = ct->flags & APC_EXTENSIBLE;
++	int inext = 0;		/* Lies not within extension root */
++	int sizeinunits = st->size;
++	const uint8_t *buf;
++	int ret;
++
++	if(!st || !st->buf)
++		_ASN_ENCODE_FAILED;
++
++	if(unit_bits == 1) {
++		ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
++				sizeinunits, st->bits_unused);
++		sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
++	}
++
++	ASN_DEBUG("Encoding %s into %d units of %d bits"
++		" (%d..%d, effective %d)%s",
++		td->name, sizeinunits, unit_bits,
++		ct->lower_bound, ct->upper_bound,
++		ct->effective_bits, ct_extensible ? " EXT" : "");
++
++	/* Figure out wheter size lies within PER visible consrtaint */
++
++	if(ct->effective_bits >= 0) {
++		if(sizeinunits < ct->lower_bound
++		|| sizeinunits > ct->upper_bound) {
++			if(ct_extensible) {
++				ct = &asn_DEF_OCTET_STRING_constraint;
++				inext = 1;
++			} else
++				_ASN_ENCODE_FAILED;
++		}
++	} else {
++		inext = 0;
++	}
++
++	if(ct_extensible) {
++		/* Declare whether length is [not] within extension root */
++		if(per_put_few_bits(po, inext, 1))
++			_ASN_ENCODE_FAILED;
++	}
++
++	/* X.691, #16.5: zero-length encoding */
++	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
++	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
++	if(ct->effective_bits >= 0) {
++		ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
++				st->size, sizeinunits - ct->lower_bound,
++				ct->effective_bits);
++		ret = per_put_few_bits(po, sizeinunits - ct->lower_bound,
++				ct->effective_bits);
++		if(ret) _ASN_ENCODE_FAILED;
++		ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits);
++		if(ret) _ASN_ENCODE_FAILED;
++		_ASN_ENCODED_OK(er);
++	}
++
++	ASN_DEBUG("Encoding %d bytes", st->size);
++
++	if(sizeinunits == 0) {
++		if(uper_put_length(po, 0))
++			_ASN_ENCODE_FAILED;
++		_ASN_ENCODED_OK(er);
++	}
++
++	buf = st->buf;
++	while(sizeinunits) {
++		ssize_t maySave = uper_put_length(po, sizeinunits);
++		if(maySave < 0) _ASN_ENCODE_FAILED;
++
++		ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
++
++		ret = per_put_many_bits(po, buf, maySave * unit_bits);
++		if(ret) _ASN_ENCODE_FAILED;
++
++		if(unit_bits == 1)
++			buf += maySave >> 3;
++		else
++			buf += maySave;
++		sizeinunits -= maySave;
++		assert(!(maySave & 0x07) || !sizeinunits);
++	}
++
++	_ASN_ENCODED_OK(er);
++}
++
++int
++OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	static const char *h2c = "0123456789ABCDEF";
++	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
++	char scratch[16 * 3 + 4];
++	char *p = scratch;
++	uint8_t *buf;
++	uint8_t *end;
++	size_t i;
++
++	(void)td;	/* Unused argument */
++
++	if(!st || !st->buf) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++
++	/*
++	 * Dump the contents of the buffer in hexadecimal.
++	 */
++	buf = st->buf;
++	end = buf + st->size;
++	for(i = 0; buf < end; buf++, i++) {
++		if(!(i % 16) && (i || st->size > 16)) {
++			if(cb(scratch, p - scratch, app_key) < 0)
++				return -1;
++			_i_INDENT(1);
++			p = scratch;
++		}
++		*p++ = h2c[(*buf >> 4) & 0x0F];
++		*p++ = h2c[*buf & 0x0F];
++		*p++ = 0x20;
++	}
++
++	if(p > scratch) {
++		p--;	/* Remove the tail space */
++		if(cb(scratch, p - scratch, app_key) < 0)
++			return -1;
++	}
++
++	return 0;
++}
++
++int
++OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
++		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
++	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
++
++	(void)td;	/* Unused argument */
++	(void)ilevel;	/* Unused argument */
++
++	if(st && st->buf) {
++		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
++	} else {
++		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++	}
++}
++
++void
++OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
++	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++				? (asn_OCTET_STRING_specifics_t *)td->specifics
++				: &asn_DEF_OCTET_STRING_specs;
++	asn_struct_ctx_t *ctx = (asn_struct_ctx_t *)
++					((char *)st + specs->ctx_offset);
++	struct _stack *stck;
++
++	if(!td || !st)
++		return;
++
++	ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
++
++	if(st->buf) {
++		FREEMEM(st->buf);
++	}
++
++	/*
++	 * Remove decode-time stack.
++	 */
++	stck = (struct _stack *)ctx->ptr;
++	if(stck) {
++		while(stck->tail) {
++			struct _stack_el *sel = stck->tail;
++			stck->tail = sel->prev;
++			FREEMEM(sel);
++		}
++		FREEMEM(stck);
++	}
++
++	if(!contents_only) {
++		FREEMEM(st);
++	}
++}
++
++/*
++ * Conversion routines.
++ */
++int
++OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
++	void *buf;
++
++	if(st == 0 || (str == 0 && len)) {
++		errno = EINVAL;
++		return -1;
++	}
++
++	/*
++	 * Clear the OCTET STRING.
++	 */
++	if(str == NULL) {
++		FREEMEM(st->buf);
++		st->buf = 0;
++		st->size = 0;
++		return 0;
++	}
++
++	/* Determine the original string size, if not explicitly given */
++	if(len < 0)
++		len = strlen(str);
++
++	/* Allocate and fill the memory */
++	buf = MALLOC(len + 1);
++	if(buf == NULL)
++		return -1;
++
++	memcpy(buf, str, len);
++	((uint8_t *)buf)[len] = '\0';	/* Couldn't use memcpy(len+1)! */
++	FREEMEM(st->buf);
++	st->buf = (uint8_t *)buf;
++	st->size = len;
++
++	return 0;
++}
++
++OCTET_STRING_t *
++OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
++	asn_OCTET_STRING_specifics_t *specs = td->specifics
++				? (asn_OCTET_STRING_specifics_t *)td->specifics
++				: &asn_DEF_OCTET_STRING_specs;
++	OCTET_STRING_t *st;
++
++	st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
++	if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
++		FREEMEM(st);
++		st = NULL;
++	}
++
++	return st;
++}
++
+diff --git a/asn1/asn1c/OCTET_STRING.h b/asn1/asn1c/OCTET_STRING.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..5150161a7a1a19e8e7c123776684e66c1cd429cf
+--- /dev/null
++++ b/asn1/asn1c/OCTET_STRING.h
+@@ -0,0 +1,80 @@
++/*-
++ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_OCTET_STRING_H_
++#define	_OCTET_STRING_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct OCTET_STRING {
++	uint8_t *buf;	/* Buffer with consecutive OCTET_STRING bits */
++	int size;	/* Size of the buffer */
++
++	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
++} OCTET_STRING_t;
++
++extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
++
++asn_struct_free_f OCTET_STRING_free;
++asn_struct_print_f OCTET_STRING_print;
++asn_struct_print_f OCTET_STRING_print_utf8;
++ber_type_decoder_f OCTET_STRING_decode_ber;
++der_type_encoder_f OCTET_STRING_encode_der;
++xer_type_decoder_f OCTET_STRING_decode_xer_hex;		/* Hexadecimal */
++xer_type_decoder_f OCTET_STRING_decode_xer_binary;	/* 01010111010 */
++xer_type_decoder_f OCTET_STRING_decode_xer_utf8;	/* ASCII/UTF-8 */
++xer_type_encoder_f OCTET_STRING_encode_xer;
++xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
++per_type_decoder_f OCTET_STRING_decode_uper;
++per_type_encoder_f OCTET_STRING_encode_uper;
++
++/******************************
++ * Handy conversion routines. *
++ ******************************/
++
++/*
++ * This function clears the previous value of the OCTET STRING (if any)
++ * and then allocates a new memory with the specified content (str/size).
++ * If size = -1, the size of the original string will be determined
++ * using strlen(str).
++ * If str equals to NULL, the function will silently clear the
++ * current contents of the OCTET STRING.
++ * Returns 0 if it was possible to perform operation, -1 otherwise.
++ */
++int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
++
++/* Handy conversion from the C string into the OCTET STRING. */
++#define	OCTET_STRING_fromString(s, str)	OCTET_STRING_fromBuf(s, str, -1)
++
++/*
++ * Allocate and fill the new OCTET STRING and return a pointer to the newly
++ * allocated object. NULL is permitted in str: the function will just allocate
++ * empty OCTET STRING.
++ */
++OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
++	const char *str, int size);
++
++/****************************
++ * Internally useful stuff. *
++ ****************************/
++
++typedef struct asn_OCTET_STRING_specifics_s {
++	/*
++	 * Target structure description.
++	 */
++	int struct_size;	/* Size of the structure */
++	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
++
++	int subvariant;		/* {0,1,2} for O-S, BIT STRING or ANY */
++} asn_OCTET_STRING_specifics_t;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _OCTET_STRING_H_ */
+diff --git a/asn1/asn1c/TypeValuePair.c b/asn1/asn1c/TypeValuePair.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..707eef3f65c4bf0a64b4864391e64865cc19d7ca
+--- /dev/null
++++ b/asn1/asn1c/TypeValuePair.c
+@@ -0,0 +1,71 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#include <asn_internal.h>
++
++#include "TypeValuePair.h"
++
++static asn_TYPE_member_t asn_MBR_TypeValuePair_1[] = {
++	{ ATF_NOFLAGS, 0, offsetof(struct TypeValuePair, type),
++		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_Int32,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"type"
++		},
++	{ ATF_NOFLAGS, 0, offsetof(struct TypeValuePair, value),
++		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
++		+1,	/* EXPLICIT tag at current level */
++		&asn_DEF_OCTET_STRING,
++		0,	/* Defer constraints checking to the member type */
++		0,	/* PER is not compiled, use -gen-PER */
++		0,
++		"value"
++		},
++};
++static ber_tlv_tag_t asn_DEF_TypeValuePair_tags_1[] = {
++	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
++};
++static asn_TYPE_tag2member_t asn_MAP_TypeValuePair_tag2el_1[] = {
++    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* type at 34 */
++    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* value at 35 */
++};
++static asn_SEQUENCE_specifics_t asn_SPC_TypeValuePair_specs_1 = {
++	sizeof(struct TypeValuePair),
++	offsetof(struct TypeValuePair, _asn_ctx),
++	asn_MAP_TypeValuePair_tag2el_1,
++	2,	/* Count of tags in the map */
++	0, 0, 0,	/* Optional elements (not needed) */
++	-1,	/* Start extensions */
++	-1	/* Stop extensions */
++};
++asn_TYPE_descriptor_t asn_DEF_TypeValuePair = {
++	"TypeValuePair",
++	"TypeValuePair",
++	SEQUENCE_free,
++	SEQUENCE_print,
++	SEQUENCE_constraint,
++	SEQUENCE_decode_ber,
++	SEQUENCE_encode_der,
++	SEQUENCE_decode_xer,
++	SEQUENCE_encode_xer,
++	0, 0,	/* No PER support, use "-gen-PER" to enable */
++	0,	/* Use generic outmost tag fetcher */
++	asn_DEF_TypeValuePair_tags_1,
++	sizeof(asn_DEF_TypeValuePair_tags_1)
++		/sizeof(asn_DEF_TypeValuePair_tags_1[0]), /* 1 */
++	asn_DEF_TypeValuePair_tags_1,	/* Same as above */
++	sizeof(asn_DEF_TypeValuePair_tags_1)
++		/sizeof(asn_DEF_TypeValuePair_tags_1[0]), /* 1 */
++	0,	/* No PER visible constraints */
++	asn_MBR_TypeValuePair_1,
++	2,	/* Elements count */
++	&asn_SPC_TypeValuePair_specs_1	/* Additional specs */
++};
++
+diff --git a/asn1/asn1c/TypeValuePair.h b/asn1/asn1c/TypeValuePair.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..538b4609c5f0fe051988885c84c3caf6d8b85452
+--- /dev/null
++++ b/asn1/asn1c/TypeValuePair.h
+@@ -0,0 +1,39 @@
++/*
++ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
++ * From ASN.1 module "KeytabModule"
++ * 	found in "ipa.asn1"
++ * 	`asn1c -fskeletons-copy`
++ */
++
++#ifndef	_TypeValuePair_H_
++#define	_TypeValuePair_H_
++
++
++#include <asn_application.h>
++
++/* Including external dependencies */
++#include "Int32.h"
++#include <OCTET_STRING.h>
++#include <constr_SEQUENCE.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* TypeValuePair */
++typedef struct TypeValuePair {
++	Int32_t	 type;
++	OCTET_STRING_t	 value;
++	
++	/* Context for parsing across buffer boundaries */
++	asn_struct_ctx_t _asn_ctx;
++} TypeValuePair_t;
++
++/* Implementation */
++extern asn_TYPE_descriptor_t asn_DEF_TypeValuePair;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _TypeValuePair_H_ */
+diff --git a/asn1/asn1c/asn_SEQUENCE_OF.c b/asn1/asn1c/asn_SEQUENCE_OF.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..ec952fc99936ab1464d76ac75821fc19e47995cb
+--- /dev/null
++++ b/asn1/asn1c/asn_SEQUENCE_OF.c
+@@ -0,0 +1,41 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <asn_SEQUENCE_OF.h>
++
++typedef A_SEQUENCE_OF(void) asn_sequence;
++
++void
++asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) {
++	asn_sequence *as = (asn_sequence *)asn_sequence_of_x;
++
++	if(as) {
++		void *ptr;
++		int n;
++
++		if(number < 0 || number >= as->count)
++			return;	/* Nothing to delete */
++
++		if(_do_free && as->free) {
++			ptr = as->array[number];
++		} else {
++			ptr = 0;
++		}
++
++		/*
++		 * Shift all elements to the left to hide the gap.
++		 */
++		--as->count;
++		for(n = number; n < as->count; n++)
++			as->array[n] = as->array[n+1];
++
++		/*
++		 * Invoke the third-party function only when the state
++		 * of the parent structure is consistent.
++		 */
++		if(ptr) as->free(ptr);
++	}
++}
++
+diff --git a/asn1/asn1c/asn_SEQUENCE_OF.h b/asn1/asn1c/asn_SEQUENCE_OF.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..e678f0347221f96698668bf6d8461655f8e40d82
+--- /dev/null
++++ b/asn1/asn1c/asn_SEQUENCE_OF.h
+@@ -0,0 +1,52 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	ASN_SEQUENCE_OF_H
++#define	ASN_SEQUENCE_OF_H
++
++#include <asn_SET_OF.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * SEQUENCE OF is the same as SET OF with a tiny difference:
++ * the delete operation preserves the initial order of elements
++ * and thus MAY operate in non-constant time.
++ */
++#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
++
++#define	ASN_SEQUENCE_ADD(headptr, ptr)		\
++	asn_sequence_add((headptr), (ptr))
++
++/***********************************************
++ * Implementation of the SEQUENCE OF structure.
++ */
++
++#define	asn_sequence_add	asn_set_add
++#define	asn_sequence_empty	asn_set_empty
++
++/*
++ * Delete the element from the set by its number (base 0).
++ * This is NOT a constant-time operation.
++ * The order of elements is preserved.
++ * If _do_free is given AND the (*free) is initialized, the element
++ * will be freed using the custom (*free) function as well.
++ */
++void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free);
++
++/*
++ * Cope with different conversions requirements to/from void in C and C++.
++ * This is mostly useful for support library.
++ */
++typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_;
++#define _A_SEQUENCE_FROM_VOID(ptr)	((asn_anonymous_sequence_ *)(ptr))
++#define _A_CSEQUENCE_FROM_VOID(ptr) 	((const asn_anonymous_sequence_ *)(ptr))
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* ASN_SEQUENCE_OF_H */
+diff --git a/asn1/asn1c/asn_SET_OF.c b/asn1/asn1c/asn_SET_OF.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..944f2cb8ad70a166e65dbb3536ef62fc34a8e74c
+--- /dev/null
++++ b/asn1/asn1c/asn_SET_OF.c
+@@ -0,0 +1,88 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <asn_SET_OF.h>
++#include <errno.h>
++
++/*
++ * Add another element into the set.
++ */
++int
++asn_set_add(void *asn_set_of_x, void *ptr) {
++	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
++
++	if(as == 0 || ptr == 0) {
++		errno = EINVAL;		/* Invalid arguments */
++		return -1;
++	}
++
++	/*
++	 * Make sure there's enough space to insert an element.
++	 */
++	if(as->count == as->size) {
++		int _newsize = as->size ? (as->size << 1) : 4;
++		void *_new_arr;
++		_new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0]));
++		if(_new_arr) {
++			as->array = (void **)_new_arr;
++			as->size = _newsize;
++		} else {
++			/* ENOMEM */
++			return -1;
++		}
++	}
++
++	as->array[as->count++] = ptr;
++
++	return 0;
++}
++
++void
++asn_set_del(void *asn_set_of_x, int number, int _do_free) {
++	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
++
++	if(as) {
++		void *ptr;
++		if(number < 0 || number >= as->count)
++			return;
++
++		if(_do_free && as->free) {
++			ptr = as->array[number];
++		} else {
++			ptr = 0;
++		}
++
++		as->array[number] = as->array[--as->count];
++
++		/*
++		 * Invoke the third-party function only when the state
++		 * of the parent structure is consistent.
++		 */
++		if(ptr) as->free(ptr);
++	}
++}
++
++/*
++ * Free the contents of the set, do not free the set itself.
++ */
++void
++asn_set_empty(void *asn_set_of_x) {
++	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
++
++	if(as) {
++		if(as->array) {
++			if(as->free) {
++				while(as->count--)
++					as->free(as->array[as->count]);
++			}
++			FREEMEM(as->array);
++			as->array = 0;
++		}
++		as->count = 0;
++		as->size = 0;
++	}
++
++}
++
+diff --git a/asn1/asn1c/asn_SET_OF.h b/asn1/asn1c/asn_SET_OF.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..7edf14b51b984d545b818fcf3a93204935d46a80
+--- /dev/null
++++ b/asn1/asn1c/asn_SET_OF.h
+@@ -0,0 +1,62 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	ASN_SET_OF_H
++#define	ASN_SET_OF_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define	A_SET_OF(type)					\
++	struct {					\
++		type **array;				\
++		int count;	/* Meaningful size */	\
++		int size;	/* Allocated size */	\
++		void (*free)(type *);			\
++	}
++
++#define	ASN_SET_ADD(headptr, ptr)		\
++	asn_set_add((headptr), (ptr))
++
++/*******************************************
++ * Implementation of the SET OF structure.
++ */
++
++/*
++ * Add another structure into the set by its pointer.
++ * RETURN VALUES:
++ * 0 for success and -1/errno for failure.
++ */
++int  asn_set_add(void *asn_set_of_x, void *ptr);
++
++/*
++ * Delete the element from the set by its number (base 0).
++ * This is a constant-time operation. The order of elements before the
++ * deleted ones is guaranteed, the order of elements after the deleted
++ * one is NOT guaranteed.
++ * If _do_free is given AND the (*free) is initialized, the element
++ * will be freed using the custom (*free) function as well.
++ */
++void asn_set_del(void *asn_set_of_x, int number, int _do_free);
++
++/*
++ * Empty the contents of the set. Will free the elements, if (*free) is given.
++ * Will NOT free the set itself.
++ */
++void asn_set_empty(void *asn_set_of_x);
++
++/*
++ * Cope with different conversions requirements to/from void in C and C++.
++ * This is mostly useful for support library.
++ */
++typedef A_SET_OF(void) asn_anonymous_set_;
++#define _A_SET_FROM_VOID(ptr)		((asn_anonymous_set_ *)(ptr))
++#define _A_CSET_FROM_VOID(ptr)		((const asn_anonymous_set_ *)(ptr))
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* ASN_SET_OF_H */
+diff --git a/asn1/asn1c/asn_application.h b/asn1/asn1c/asn_application.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..f40cd86ad3c63a7a0a07214addecb57d087abe25
+--- /dev/null
++++ b/asn1/asn1c/asn_application.h
+@@ -0,0 +1,47 @@
++/*-
++ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * Application-level ASN.1 callbacks.
++ */
++#ifndef	_ASN_APPLICATION_H_
++#define	_ASN_APPLICATION_H_
++
++#include "asn_system.h"		/* for platform-dependent types */
++#include "asn_codecs.h"		/* for ASN.1 codecs specifics */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Generic type of an application-defined callback to return various
++ * types of data to the application.
++ * EXPECTED RETURN VALUES:
++ *  -1: Failed to consume bytes. Abort the mission.
++ * Non-negative return values indicate success, and ignored.
++ */
++typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size,
++	void *application_specific_key);
++
++/*
++ * A callback of this type is called whenever constraint validation fails
++ * on some ASN.1 type. See "constraints.h" for more details on constraint
++ * validation.
++ * This callback specifies a descriptor of the ASN.1 type which failed
++ * the constraint check, as well as human readable message on what
++ * particular constraint has failed.
++ */
++typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
++	struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
++	const void *structure_which_failed_ptr,
++	const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
++
++#ifdef __cplusplus
++}
++#endif
++
++#include "constr_TYPE.h"	/* for asn_TYPE_descriptor_t */
++
++#endif	/* _ASN_APPLICATION_H_ */
+diff --git a/asn1/asn1c/asn_codecs.h b/asn1/asn1c/asn_codecs.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..4a251d940880a03b24dc9f3fe41f2febb9b49211
+--- /dev/null
++++ b/asn1/asn1c/asn_codecs.h
+@@ -0,0 +1,109 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_ASN_CODECS_H_
++#define	_ASN_CODECS_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/*
++ * This structure defines a set of parameters that may be passed
++ * to every ASN.1 encoder or decoder function.
++ * WARNING: if max_stack_size member is set, and you are calling the
++ *   function pointers of the asn_TYPE_descriptor_t directly,
++ *   this structure must be ALLOCATED ON THE STACK!
++ *   If you can't always satisfy this requirement, use ber_decode(),
++ *   xer_decode() and uper_decode() functions instead.
++ */
++typedef struct asn_codec_ctx_s {
++	/*
++	 * Limit the decoder routines to use no (much) more stack than a given
++	 * number of bytes. Most of decoders are stack-based, and this
++	 * would protect against stack overflows if the number of nested
++	 * encodings is high.
++	 * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based,
++	 * and are safe from this kind of overflow.
++	 * A value from getrlimit(RLIMIT_STACK) may be used to initialize
++	 * this variable. Be careful in multithreaded environments, as the
++	 * stack size is rather limited.
++	 */
++	size_t  max_stack_size; /* 0 disables stack bounds checking */
++} asn_codec_ctx_t;
++
++/*
++ * Type of the return value of the encoding functions (der_encode, xer_encode).
++ */
++typedef struct asn_enc_rval_s {
++	/*
++	 * Number of bytes encoded.
++	 * -1 indicates failure to encode the structure.
++	 * In this case, the members below this one are meaningful.
++	 */
++	ssize_t encoded;
++
++	/*
++	 * Members meaningful when (encoded == -1), for post mortem analysis.
++	 */
++
++	/* Type which cannot be encoded */
++	struct asn_TYPE_descriptor_s *failed_type;
++
++	/* Pointer to the structure of that type */
++	void *structure_ptr;
++} asn_enc_rval_t;
++#define	_ASN_ENCODE_FAILED do {					\
++	asn_enc_rval_t tmp_error;				\
++	tmp_error.encoded = -1;					\
++	tmp_error.failed_type = td;				\
++	tmp_error.structure_ptr = sptr;				\
++	ASN_DEBUG("Failed to encode element %s", td->name);	\
++	return tmp_error;					\
++} while(0)
++#define	_ASN_ENCODED_OK(rval) do {				\
++	rval.structure_ptr = 0;					\
++	rval.failed_type = 0;					\
++	return rval;						\
++} while(0)
++
++/*
++ * Type of the return value of the decoding functions (ber_decode, xer_decode)
++ * 
++ * Please note that the number of consumed bytes is ALWAYS meaningful,
++ * even if code==RC_FAIL. This is to indicate the number of successfully
++ * decoded bytes, hence providing a possibility to fail with more diagnostics
++ * (i.e., print the offending remainder of the buffer).
++ */
++enum asn_dec_rval_code_e {
++	RC_OK,		/* Decoded successfully */
++	RC_WMORE,	/* More data expected, call again */
++	RC_FAIL		/* Failure to decode data */
++};
++typedef struct asn_dec_rval_s {
++	enum asn_dec_rval_code_e code;	/* Result code */
++	size_t consumed;		/* Number of bytes consumed */
++} asn_dec_rval_t;
++#define	_ASN_DECODE_FAILED do {					\
++	asn_dec_rval_t tmp_error;				\
++	tmp_error.code = RC_FAIL;				\
++	tmp_error.consumed = 0;					\
++	ASN_DEBUG("Failed to decode element %s", td->name);	\
++	return tmp_error;					\
++} while(0)
++#define	_ASN_DECODE_STARVED do {				\
++	asn_dec_rval_t tmp_error;				\
++	tmp_error.code = RC_WMORE;				\
++	tmp_error.consumed = 0;					\
++	return tmp_error;					\
++} while(0)
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _ASN_CODECS_H_ */
+diff --git a/asn1/asn1c/asn_codecs_prim.c b/asn1/asn1c/asn_codecs_prim.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..4e5c63937adafc40a56b67fe5b3d9482220907d5
+--- /dev/null
++++ b/asn1/asn1c/asn_codecs_prim.c
+@@ -0,0 +1,295 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <asn_codecs_prim.h>
++#include <errno.h>
++
++/*
++ * Decode an always-primitive type.
++ */
++asn_dec_rval_t
++ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td,
++	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
++	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
++	asn_dec_rval_t rval;
++	ber_tlv_len_t length;
++
++	/*
++	 * If the structure is not there, allocate it.
++	 */
++	if(st == NULL) {
++		st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
++		if(st == NULL) _ASN_DECODE_FAILED;
++		*sptr = (void *)st;
++	}
++
++	ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
++		td->name, tag_mode);
++
++	/*
++	 * Check tags and extract value length.
++	 */
++	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
++			tag_mode, 0, &length, 0);
++	if(rval.code != RC_OK)
++		return rval;
++
++	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
++
++	/*
++	 * Make sure we have this length.
++	 */
++	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
++	size -= rval.consumed;
++	if(length > (ber_tlv_len_t)size) {
++		rval.code = RC_WMORE;
++		rval.consumed = 0;
++		return rval;
++	}
++
++	st->size = (int)length;
++	/* The following better be optimized away. */
++	if(sizeof(st->size) != sizeof(length)
++			&& (ber_tlv_len_t)st->size != length) {
++		st->size = 0;
++		_ASN_DECODE_FAILED;
++	}
++
++	st->buf = (uint8_t *)MALLOC(length + 1);
++	if(!st->buf) {
++		st->size = 0;
++		_ASN_DECODE_FAILED;
++	}
++
++	memcpy(st->buf, buf_ptr, length);
++	st->buf[length] = '\0';		/* Just in case */
++
++	rval.code = RC_OK;
++	rval.consumed += length;
++
++	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
++		(long)rval.consumed,
++		(long)length, td->name);
++
++	return rval;
++}
++
++/*
++ * Encode an always-primitive type using DER.
++ */
++asn_enc_rval_t
++der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t erval;
++	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
++
++	ASN_DEBUG("%s %s as a primitive type (tm=%d)",
++		cb?"Encoding":"Estimating", td->name, tag_mode);
++
++	erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
++		cb, app_key);
++	ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
++	if(erval.encoded == -1) {
++		erval.failed_type = td;
++		erval.structure_ptr = sptr;
++		return erval;
++	}
++
++	if(cb && st->buf) {
++		if(cb(st->buf, st->size, app_key) < 0) {
++			erval.encoded = -1;
++			erval.failed_type = td;
++			erval.structure_ptr = sptr;
++			return erval;
++		}
++	} else {
++		assert(st->buf || st->size == 0);
++	}
++
++	erval.encoded += st->size;
++	_ASN_ENCODED_OK(erval);
++}
++
++void
++ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
++		int contents_only) {
++	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
++
++	if(!td || !sptr)
++		return;
++
++	ASN_DEBUG("Freeing %s as a primitive type", td->name);
++
++	if(st->buf)
++		FREEMEM(st->buf);
++
++	if(!contents_only)
++		FREEMEM(st);
++}
++
++
++/*
++ * Local internal type passed around as an argument.
++ */
++struct xdp_arg_s {
++	asn_TYPE_descriptor_t *type_descriptor;
++	void *struct_key;
++	xer_primitive_body_decoder_f *prim_body_decoder;
++	int decoded_something;
++	int want_more;
++};
++
++
++static int
++xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
++	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
++	enum xer_pbd_rval bret;
++
++	if(arg->decoded_something) {
++		if(xer_is_whitespace(chunk_buf, chunk_size))
++			return 0;	/* Skip it. */
++		/*
++		 * Decoding was done once already. Prohibit doing it again.
++		 */
++		return -1;
++	}
++
++	bret = arg->prim_body_decoder(arg->type_descriptor,
++		arg->struct_key, chunk_buf, chunk_size);
++	switch(bret) {
++	case XPBD_SYSTEM_FAILURE:
++	case XPBD_DECODER_LIMIT:
++	case XPBD_BROKEN_ENCODING:
++		break;
++	case XPBD_BODY_CONSUMED:
++		/* Tag decoded successfully */
++		arg->decoded_something = 1;
++		/* Fall through */
++	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
++		return 0;
++	}
++
++	return -1;
++}
++
++static ssize_t
++xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
++	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
++	enum xer_pbd_rval bret;
++
++	if(arg->decoded_something) {
++		if(xer_is_whitespace(chunk_buf, chunk_size))
++			return chunk_size;
++		/*
++		 * Decoding was done once already. Prohibit doing it again.
++		 */
++		return -1;
++	}
++
++	if(!have_more) {
++		/*
++		 * If we've received something like "1", we can't really
++		 * tell whether it is really `1` or `123`, until we know
++		 * that there is no more data coming.
++		 * The have_more argument will be set to 1 once something
++		 * like this is available to the caller of this callback:
++		 * "1<tag_start..."
++		 */
++		arg->want_more = 1;
++		return -1;
++	}
++
++	bret = arg->prim_body_decoder(arg->type_descriptor,
++		arg->struct_key, chunk_buf, chunk_size);
++	switch(bret) {
++	case XPBD_SYSTEM_FAILURE:
++	case XPBD_DECODER_LIMIT:
++	case XPBD_BROKEN_ENCODING:
++		break;
++	case XPBD_BODY_CONSUMED:
++		/* Tag decoded successfully */
++		arg->decoded_something = 1;
++		/* Fall through */
++	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
++		return chunk_size;
++	}
++
++	return -1;
++}
++
++
++asn_dec_rval_t
++xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *td,
++	void **sptr,
++	size_t struct_size,
++	const char *opt_mname,
++	const void *buf_ptr, size_t size,
++	xer_primitive_body_decoder_f *prim_body_decoder
++) {
++	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
++	asn_struct_ctx_t s_ctx;
++	struct xdp_arg_s s_arg;
++	asn_dec_rval_t rc;
++
++	/*
++	 * Create the structure if does not exist.
++	 */
++	if(!*sptr) {
++		*sptr = CALLOC(1, struct_size);
++		if(!*sptr) _ASN_DECODE_FAILED;
++	}
++
++	memset(&s_ctx, 0, sizeof(s_ctx));
++	s_arg.type_descriptor = td;
++	s_arg.struct_key = *sptr;
++	s_arg.prim_body_decoder = prim_body_decoder;
++	s_arg.decoded_something = 0;
++	s_arg.want_more = 0;
++
++	rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
++		xml_tag, buf_ptr, size,
++		xer_decode__unexpected_tag, xer_decode__body);
++	switch(rc.code) {
++	case RC_OK:
++		if(!s_arg.decoded_something) {
++			char ch;
++			ASN_DEBUG("Primitive body is not recognized, "
++				"supplying empty one");
++			/*
++			 * Decoding opportunity has come and gone.
++			 * Where's the result?
++			 * Try to feed with empty body, see if it eats it.
++			 */
++			if(prim_body_decoder(s_arg.type_descriptor,
++				s_arg.struct_key, &ch, 0)
++					!= XPBD_BODY_CONSUMED) {
++				/*
++				 * This decoder does not like empty stuff.
++				 */
++				_ASN_DECODE_FAILED;
++			}
++		}
++		break;
++	case RC_WMORE:
++		/*
++		 * Redo the whole thing later.
++		 * We don't have a context to save intermediate parsing state.
++		 */
++		rc.consumed = 0;
++		break;
++	case RC_FAIL:
++		rc.consumed = 0;
++		if(s_arg.want_more)
++			rc.code = RC_WMORE;
++		else
++			_ASN_DECODE_FAILED;
++		break;
++	}
++	return rc;
++}
++
+diff --git a/asn1/asn1c/asn_codecs_prim.h b/asn1/asn1c/asn_codecs_prim.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..0f683fdd0ac7d5be56c55b1363fa4fddb0d48198
+--- /dev/null
++++ b/asn1/asn1c/asn_codecs_prim.h
+@@ -0,0 +1,53 @@
++/*-
++ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	ASN_CODECS_PRIM_H
++#define	ASN_CODECS_PRIM_H
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct ASN__PRIMITIVE_TYPE_s {
++	uint8_t *buf;	/* Buffer with consecutive primitive encoding bytes */
++	int size;	/* Size of the buffer */
++} ASN__PRIMITIVE_TYPE_t;	/* Do not use this type directly! */
++
++asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
++ber_type_decoder_f ber_decode_primitive;
++der_type_encoder_f der_encode_primitive;
++
++/*
++ * A callback specification for the xer_decode_primitive() function below.
++ */
++enum xer_pbd_rval {
++	XPBD_SYSTEM_FAILURE,	/* System failure (memory shortage, etc) */
++	XPBD_DECODER_LIMIT,	/* Hit some decoder limitation or deficiency */
++	XPBD_BROKEN_ENCODING,	/* Encoding of a primitive body is broken */
++	XPBD_NOT_BODY_IGNORE,	/* Not a body format, but safe to ignore */
++	XPBD_BODY_CONSUMED	/* Body is recognized and consumed */
++};
++typedef enum xer_pbd_rval (xer_primitive_body_decoder_f)
++	(asn_TYPE_descriptor_t *td, void *struct_ptr,
++		const void *chunk_buf, size_t chunk_size);
++
++/*
++ * Specific function to decode simple primitive types.
++ * Also see xer_decode_general() in xer_decoder.h
++ */
++asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *type_descriptor,
++	void **struct_ptr, size_t struct_size,
++	const char *opt_mname,
++	const void *buf_ptr, size_t size,
++	xer_primitive_body_decoder_f *prim_body_decoder
++);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* ASN_CODECS_PRIM_H */
+diff --git a/asn1/asn1c/asn_internal.h b/asn1/asn1c/asn_internal.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..67f055a62fbf74c397d2c108469549291ef9e6af
+--- /dev/null
++++ b/asn1/asn1c/asn_internal.h
+@@ -0,0 +1,111 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * Declarations internally useful for the ASN.1 support code.
++ */
++#ifndef	_ASN_INTERNAL_H_
++#define	_ASN_INTERNAL_H_
++
++#include "asn_application.h"	/* Application-visible API */
++
++#ifndef	__NO_ASSERT_H__		/* Include assert.h only for internal use. */
++#include <assert.h>		/* for assert() macro */
++#endif
++
++#ifdef	__cplusplus
++extern "C" {
++#endif
++
++/* Environment version might be used to avoid running with the old library */
++#define	ASN1C_ENVIRONMENT_VERSION	920	/* Compile-time version */
++int get_asn1c_environment_version(void);	/* Run-time version */
++
++#define	CALLOC(nmemb, size)	calloc(nmemb, size)
++#define	MALLOC(size)		malloc(size)
++#define	REALLOC(oldptr, size)	realloc(oldptr, size)
++#define	FREEMEM(ptr)		free(ptr)
++
++/*
++ * A macro for debugging the ASN.1 internals.
++ * You may enable or override it.
++ */
++#ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
++#if	EMIT_ASN_DEBUG == 1	/* And it was asked to emit this code... */
++#ifdef	__GNUC__
++#define	ASN_DEBUG(fmt, args...)	do {		\
++		fprintf(stderr, fmt, ##args);	\
++		fprintf(stderr, " (%s:%d)\n",	\
++			__FILE__, __LINE__);	\
++	} while(0)
++#else	/* !__GNUC__ */
++void ASN_DEBUG_f(const char *fmt, ...);
++#define	ASN_DEBUG	ASN_DEBUG_f
++#endif	/* __GNUC__ */
++#else	/* EMIT_ASN_DEBUG != 1 */
++static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
++#endif	/* EMIT_ASN_DEBUG */
++#endif	/* ASN_DEBUG */
++
++/*
++ * Invoke the application-supplied callback and fail, if something is wrong.
++ */
++#define	__ASN_E_cbc(buf, size)	(cb((buf), (size), app_key) < 0)
++#define	_ASN_E_CALLBACK(foo)	do {					\
++		if(foo)	goto cb_failed;					\
++	} while(0)
++#define	_ASN_CALLBACK(buf, size)					\
++	_ASN_E_CALLBACK(__ASN_E_cbc(buf, size))
++#define	_ASN_CALLBACK2(buf1, size1, buf2, size2)			\
++	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2))
++#define	_ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3)		\
++	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1)			\
++		|| __ASN_E_cbc(buf2, size2)				\
++		|| __ASN_E_cbc(buf3, size3))
++
++#define	_i_ASN_TEXT_INDENT(nl, level) do {				\
++	int __level = (level);						\
++	int __nl = ((nl) != 0);						\
++	int __i;							\
++	if(__nl) _ASN_CALLBACK("\n", 1);				\
++	for(__i = 0; __i < __level; __i++)				\
++		_ASN_CALLBACK("    ", 4);				\
++	er.encoded += __nl + 4 * __level;				\
++} while(0)
++
++#define	_i_INDENT(nl)	do {						\
++	int __i;							\
++	if((nl) && cb("\n", 1, app_key) < 0) return -1;			\
++	for(__i = 0; __i < ilevel; __i++)				\
++		if(cb("    ", 4, app_key) < 0) return -1;		\
++} while(0)
++
++/*
++ * Check stack against overflow, if limit is set.
++ */
++#define	_ASN_DEFAULT_STACK_MAX	(30000)
++static inline int
++_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
++	if(ctx && ctx->max_stack_size) {
++
++		/* ctx MUST be allocated on the stack */
++		ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
++		if(usedstack > 0) usedstack = -usedstack; /* grows up! */
++
++		/* double negative required to avoid int wrap-around */
++		if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
++			ASN_DEBUG("Stack limit %ld reached",
++				(long)ctx->max_stack_size);
++			return -1;
++		}
++	}
++	return 0;
++}
++
++#ifdef	__cplusplus
++}
++#endif
++
++#endif	/* _ASN_INTERNAL_H_ */
+diff --git a/asn1/asn1c/asn_system.h b/asn1/asn1c/asn_system.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..d7ebdaa4e16a2636184db6ba4fe34fda5860a6bc
+--- /dev/null
++++ b/asn1/asn1c/asn_system.h
+@@ -0,0 +1,104 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * Miscellaneous system-dependent types.
++ */
++#ifndef	_ASN_SYSTEM_H_
++#define	_ASN_SYSTEM_H_
++
++#ifdef	HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <stdio.h>	/* For snprintf(3) */
++#include <stdlib.h>	/* For *alloc(3) */
++#include <string.h>	/* For memcpy(3) */
++#include <sys/types.h>	/* For size_t */
++#include <stdarg.h>	/* For va_start */
++#include <stddef.h>	/* for offsetof and ptrdiff_t */
++
++#ifdef	WIN32
++
++#include <malloc.h>
++#include <stdint.h>
++#define	 snprintf	_snprintf
++#define	 vsnprintf	_vsnprintf
++
++#ifdef _MSC_VER			/* MSVS.Net */
++#ifndef __cplusplus
++#define inline __inline
++#endif
++#define	ssize_t		SSIZE_T
++typedef	char		int8_t;
++typedef	short		int16_t;
++typedef	int		int32_t;
++typedef	unsigned char	uint8_t;
++typedef	unsigned short	uint16_t;
++typedef	unsigned int	uint32_t;
++#define WIN32_LEAN_AND_MEAN
++#include <windows.h>
++#include <float.h>
++#define isnan _isnan
++#define finite _finite
++#define copysign _copysign
++#define	ilogb	_logb
++#endif	/* _MSC_VER */
++
++#else	/* !WIN32 */
++
++#if defined(__vxworks)
++#include <types/vxTypes.h>
++#else	/* !defined(__vxworks) */
++
++#include <inttypes.h>	/* C99 specifies this file */
++/*
++ * 1. Earlier FreeBSD version didn't have <stdint.h>,
++ * but <inttypes.h> was present.
++ * 2. Sun Solaris requires <alloca.h> for alloca(3),
++ * but does not have <stdint.h>.
++ */
++#if	(!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
++#if	defined(sun)
++#include <alloca.h>	/* For alloca(3) */
++#include <ieeefp.h>	/* for finite(3) */
++#elif	defined(__hpux)
++#ifdef	__GNUC__
++#include <alloca.h>	/* For alloca(3) */
++#else	/* !__GNUC__ */
++#define inline
++#endif	/* __GNUC__ */
++#else
++#include <stdint.h>	/* SUSv2+ and C99 specify this file, for uintXX_t */
++#endif	/* defined(sun) */
++#endif
++
++#endif	/* defined(__vxworks) */
++
++#endif	/* WIN32 */
++
++#if	__GNUC__ >= 3
++#ifndef	GCC_PRINTFLIKE
++#define	GCC_PRINTFLIKE(fmt,var)	__attribute__((format(printf,fmt,var)))
++#endif
++#else
++#ifndef	GCC_PRINTFLIKE
++#define	GCC_PRINTFLIKE(fmt,var)	/* nothing */
++#endif
++#endif
++
++#ifndef	offsetof	/* If not defined by <stddef.h> */
++#define	offsetof(s, m)	((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
++#endif	/* offsetof */
++
++#ifndef	MIN		/* Suitable for comparing primitive types (integers) */
++#if defined(__GNUC__)
++#define	MIN(a,b)	({ __typeof a _a = a; __typeof b _b = b;	\
++	((_a)<(_b)?(_a):(_b)); })
++#else	/* !__GNUC__ */
++#define	MIN(a,b)	((a)<(b)?(a):(b))	/* Unsafe variant */
++#endif /* __GNUC__ */
++#endif	/* MIN */
++
++#endif	/* _ASN_SYSTEM_H_ */
+diff --git a/asn1/asn1c/ber_decoder.c b/asn1/asn1c/ber_decoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..601f66c0b0274b74dcb56e7eca469ded9b076b2c
+--- /dev/null
++++ b/asn1/asn1c/ber_decoder.c
+@@ -0,0 +1,283 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {					\
++		size_t num = num_bytes;					\
++		ptr = ((const char *)ptr) + num;			\
++		size -= num;						\
++		consumed_myself += num;					\
++	} while(0)
++#undef	RETURN
++#define	RETURN(_code)	do {						\
++		asn_dec_rval_t rval;					\
++		rval.code = _code;					\
++		if(opt_ctx) opt_ctx->step = step; /* Save context */	\
++		if(_code == RC_OK || opt_ctx)				\
++			rval.consumed = consumed_myself;		\
++		else							\
++			rval.consumed = 0;	/* Context-free */	\
++		return rval;						\
++	} while(0)
++
++/*
++ * The BER decoder of any type.
++ */
++asn_dec_rval_t
++ber_decode(asn_codec_ctx_t *opt_codec_ctx,
++	asn_TYPE_descriptor_t *type_descriptor,
++	void **struct_ptr, const void *ptr, size_t size) {
++	asn_codec_ctx_t s_codec_ctx;
++
++	/*
++	 * Stack checker requires that the codec context
++	 * must be allocated on the stack.
++	 */
++	if(opt_codec_ctx) {
++		if(opt_codec_ctx->max_stack_size) {
++			s_codec_ctx = *opt_codec_ctx;
++			opt_codec_ctx = &s_codec_ctx;
++		}
++	} else {
++		/* If context is not given, be security-conscious anyway */
++		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
++		s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
++		opt_codec_ctx = &s_codec_ctx;
++	}
++
++	/*
++	 * Invoke type-specific decoder.
++	 */
++	return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
++		struct_ptr,	/* Pointer to the destination structure */
++		ptr, size,	/* Buffer and its size */
++		0		/* Default tag mode is 0 */
++		);
++}
++
++/*
++ * Check the set of <TL<TL<TL...>>> tags matches the definition.
++ */
++asn_dec_rval_t
++ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
++		asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
++		const void *ptr, size_t size, int tag_mode, int last_tag_form,
++		ber_tlv_len_t *last_length, int *opt_tlv_form) {
++	ssize_t consumed_myself = 0;
++	ssize_t tag_len;
++	ssize_t len_len;
++	ber_tlv_tag_t tlv_tag;
++	ber_tlv_len_t tlv_len;
++	ber_tlv_len_t limit_len = -1;
++	int expect_00_terminators = 0;
++	int tlv_constr = -1;	/* If CHOICE, opt_tlv_form is not given */
++	int step = opt_ctx ? opt_ctx->step : 0;	/* Where we left previously */
++	int tagno;
++
++	/*
++	 * Make sure we didn't exceed the maximum stack size.
++	 */
++	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
++		RETURN(RC_FAIL);
++
++	/*
++	 * So what does all this implicit skip stuff mean?
++	 * Imagine two types,
++	 * 	A ::= [5] IMPLICIT	T
++	 * 	B ::= [2] EXPLICIT	T
++	 * Where T is defined as
++	 *	T ::= [4] IMPLICIT SEQUENCE { ... }
++	 * 
++	 * Let's say, we are starting to decode type A, given the
++	 * following TLV stream: <5> <0>. What does this mean?
++	 * It means that the type A contains type T which is,
++	 * in turn, empty.
++	 * Remember though, that we are still in A. We cannot
++	 * just pass control to the type T decoder. Why? Because
++	 * the type T decoder expects <4> <0>, not <5> <0>.
++	 * So, we must make sure we are going to receive <5> while
++	 * still in A, then pass control to the T decoder, indicating
++	 * that the tag <4> was implicitly skipped. The decoder of T
++	 * hence will be prepared to treat <4> as valid tag, and decode
++	 * it appropriately.
++	 */
++
++	tagno = step	/* Continuing where left previously */
++		+ (tag_mode==1?-1:0)
++		;
++	ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
++		td->name, (long)size, tag_mode, step, tagno);
++	/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
++
++	if(tag_mode == 0 && tagno == td->tags_count) {
++		/*
++		 * This must be the _untagged_ ANY type,
++		 * which outermost tag isn't known in advance.
++		 * Fetch the tag and length separately.
++		 */
++		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
++		switch(tag_len) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
++		len_len = ber_fetch_length(tlv_constr,
++			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
++		switch(len_len) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++		ASN_DEBUG("Advancing %ld in ANY case",
++			(long)(tag_len + len_len));
++		ADVANCE(tag_len + len_len);
++	} else {
++		assert(tagno < td->tags_count);	/* At least one loop */
++	}
++	for((void)tagno; tagno < td->tags_count; tagno++, step++) {
++
++		/*
++		 * Fetch and process T from TLV.
++		 */
++		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
++			ASN_DEBUG("Fetching tag from {%p,%ld}: "
++				"len %ld, step %d, tagno %d got %s",
++				ptr, (long)size,
++				(long)tag_len, step, tagno,
++				ber_tlv_tag_string(tlv_tag));
++		switch(tag_len) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++
++		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
++
++		/*
++		 * If {I}, don't check anything.
++		 * If {I,B,C}, check B and C unless we're at I.
++		 */
++		if(tag_mode != 0 && step == 0) {
++			/*
++			 * We don't expect tag to match here.
++			 * It's just because we don't know how the tag
++			 * is supposed to look like.
++			 */
++		} else {
++		    assert(tagno >= 0);	/* Guaranteed by the code above */
++		    if(tlv_tag != td->tags[tagno]) {
++			/*
++			 * Unexpected tag. Too bad.
++			 */
++		    	ASN_DEBUG("Expected: %s, "
++				"expectation failed (tn=%d, tm=%d)",
++				ber_tlv_tag_string(td->tags[tagno]),
++				tagno, tag_mode
++			);
++			RETURN(RC_FAIL);
++		    }
++		}
++
++		/*
++		 * Attention: if there are more tags expected,
++		 * ensure that the current tag is presented
++		 * in constructed form (it contains other tags!).
++		 * If this one is the last one, check that the tag form
++		 * matches the one given in descriptor.
++		 */
++		if(tagno < (td->tags_count - 1)) {
++			if(tlv_constr == 0) {
++				ASN_DEBUG("tlv_constr = %d, expfail",
++					tlv_constr);
++				RETURN(RC_FAIL);
++			}
++		} else {
++			if(last_tag_form != tlv_constr
++			&& last_tag_form != -1) {
++				ASN_DEBUG("last_tag_form %d != %d",
++					last_tag_form, tlv_constr);
++				RETURN(RC_FAIL);
++			}
++		}
++
++		/*
++		 * Fetch and process L from TLV.
++		 */
++		len_len = ber_fetch_length(tlv_constr,
++			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
++		ASN_DEBUG("Fetchinig len = %ld", (long)len_len);
++		switch(len_len) {
++		case -1: RETURN(RC_FAIL);
++		case 0: RETURN(RC_WMORE);
++		}
++
++		/*
++		 * FIXME
++		 * As of today, the chain of tags
++		 * must either contain several indefinite length TLVs,
++		 * or several definite length ones.
++		 * No mixing is allowed.
++		 */
++		if(tlv_len == -1) {
++			/*
++			 * Indefinite length.
++			 */
++			if(limit_len == -1) {
++				expect_00_terminators++;
++			} else {
++				ASN_DEBUG("Unexpected indefinite length "
++					"in a chain of definite lengths");
++				RETURN(RC_FAIL);
++			}
++			ADVANCE(tag_len + len_len);
++			continue;
++		} else {
++			if(expect_00_terminators) {
++				ASN_DEBUG("Unexpected definite length "
++					"in a chain of indefinite lengths");
++				RETURN(RC_FAIL);
++			}
++		}
++
++		/*
++		 * Check that multiple TLVs specify ever decreasing length,
++		 * which is consistent.
++		 */
++		if(limit_len == -1) {
++			limit_len    = tlv_len + tag_len + len_len;
++			if(limit_len < 0) {
++				/* Too great tlv_len value? */
++				RETURN(RC_FAIL);
++			}
++		} else if(limit_len != tlv_len + tag_len + len_len) {
++			/*
++			 * Inner TLV specifies length which is inconsistent
++			 * with the outer TLV's length value.
++			 */
++			ASN_DEBUG("Outer TLV is %ld and inner is %ld",
++				(long)limit_len, (long)tlv_len);
++			RETURN(RC_FAIL);
++		}
++
++		ADVANCE(tag_len + len_len);
++
++		limit_len -= (tag_len + len_len);
++		if((ssize_t)size > limit_len) {
++			/*
++			 * Make sure that we won't consume more bytes
++			 * from the parent frame than the inferred limit.
++			 */
++			size = limit_len;
++		}
++	}
++
++	if(opt_tlv_form)
++		*opt_tlv_form = tlv_constr;
++	if(expect_00_terminators)
++		*last_length = -expect_00_terminators;
++	else
++		*last_length = tlv_len;
++
++	RETURN(RC_OK);
++}
+diff --git a/asn1/asn1c/ber_decoder.h b/asn1/asn1c/ber_decoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..768133b67e75b4eb18e523e1943245e17ce9b3aa
+--- /dev/null
++++ b/asn1/asn1c/ber_decoder.h
+@@ -0,0 +1,63 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_BER_DECODER_H_
++#define	_BER_DECODER_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++struct asn_codec_ctx_s;		/* Forward declaration */
++
++/*
++ * The BER decoder of any type.
++ * This function may be invoked directly from the application.
++ */
++asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
++	struct asn_TYPE_descriptor_s *type_descriptor,
++	void **struct_ptr,	/* Pointer to a target structure's pointer */
++	const void *buffer,	/* Data to be decoded */
++	size_t size		/* Size of that buffer */
++	);
++
++/*
++ * Type of generic function which decodes the byte stream into the structure.
++ */
++typedef asn_dec_rval_t (ber_type_decoder_f)(
++		struct asn_codec_ctx_s *opt_codec_ctx,
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void **struct_ptr, const void *buf_ptr, size_t size,
++		int tag_mode);
++
++/*******************************
++ * INTERNALLY USEFUL FUNCTIONS *
++ *******************************/
++
++/*
++ * Check that all tags correspond to the type definition (as given in head).
++ * On return, last_length would contain either a non-negative length of the
++ * value part of the last TLV, or the negative number of expected
++ * "end of content" sequences. The number may only be negative if the
++ * head->last_tag_form is non-zero.
++ */
++asn_dec_rval_t ber_check_tags(
++		struct asn_codec_ctx_s *opt_codec_ctx,	/* codec options */
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		asn_struct_ctx_t *opt_ctx,	/* saved decoding context */
++		const void *ptr, size_t size,
++		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
++		int last_tag_form,	/* {-1,0:1}: any, primitive, constr */
++		ber_tlv_len_t *last_length,
++		int *opt_tlv_form	/* optional tag form */
++	);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _BER_DECODER_H_ */
+diff --git a/asn1/asn1c/ber_tlv_length.c b/asn1/asn1c/ber_tlv_length.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..b87e75e0469887ee7d06bfb5f83b99b8120a5374
+--- /dev/null
++++ b/asn1/asn1c/ber_tlv_length.c
+@@ -0,0 +1,178 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <ber_tlv_length.h>
++#include <ber_tlv_tag.h>
++
++ssize_t
++ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
++		ber_tlv_len_t *len_r) {
++	const uint8_t *buf = (const uint8_t *)bufptr;
++	unsigned oct;
++
++	if(size == 0)
++		return 0;	/* Want more */
++
++	oct = *(const uint8_t *)buf;
++	if((oct & 0x80) == 0) {
++		/*
++		 * Short definite length.
++		 */
++		*len_r = oct;	/* & 0x7F */
++		return 1;
++	} else {
++		ber_tlv_len_t len;
++		size_t skipped;
++
++		if(_is_constructed && oct == 0x80) {
++			*len_r = -1;	/* Indefinite length */
++			return 1;
++		}
++
++		if(oct == 0xff) {
++			/* Reserved in standard for future use. */
++			return -1;
++		}
++
++		oct &= 0x7F;	/* Leave only the 7 LS bits */
++		for(len = 0, buf++, skipped = 1;
++			oct && (++skipped <= size); buf++, oct--) {
++
++			len = (len << 8) | *buf;
++			if(len < 0
++			|| (len >> ((8 * sizeof(len)) - 8) && oct > 1)) {
++				/*
++				 * Too large length value.
++				 */
++				return -1;
++			}
++		}
++
++		if(oct == 0) {
++			ber_tlv_len_t lenplusepsilon = (size_t)len + 1024;
++			/*
++			 * Here length may be very close or equal to 2G.
++			 * However, the arithmetics used in some decoders
++			 * may add some (small) quantities to the length,
++			 * to check the resulting value against some limits.
++			 * This may result in integer wrap-around, which
++			 * we try to avoid by checking it earlier here.
++			 */
++			if(lenplusepsilon < 0) {
++				/* Too large length value */
++				return -1;
++			}
++
++			*len_r = len;
++			return skipped;
++		}
++
++		return 0;	/* Want more */
++	}
++
++}
++
++ssize_t
++ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
++		int _is_constructed, const void *ptr, size_t size) {
++	ber_tlv_len_t vlen;	/* Length of V in TLV */
++	ssize_t tl;		/* Length of L in TLV */
++	ssize_t ll;		/* Length of L in TLV */
++	size_t skip;
++
++	/*
++	 * Make sure we didn't exceed the maximum stack size.
++	 */
++	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
++		return -1;
++
++	/*
++	 * Determine the size of L in TLV.
++	 */
++	ll = ber_fetch_length(_is_constructed, ptr, size, &vlen);
++	if(ll <= 0) return ll;
++
++	/*
++	 * Definite length.
++	 */
++	if(vlen >= 0) {
++		skip = ll + vlen;
++		if(skip > size)
++			return 0;	/* Want more */
++		return skip;
++	}
++
++	/*
++	 * Indefinite length!
++	 */
++	ASN_DEBUG("Skipping indefinite length");
++	for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) {
++		ber_tlv_tag_t tag;
++
++		/* Fetch the tag */
++		tl = ber_fetch_tag(ptr, size, &tag);
++		if(tl <= 0) return tl;
++
++		ll = ber_skip_length(opt_codec_ctx,
++			BER_TLV_CONSTRUCTED(ptr),
++			((const char *)ptr) + tl, size - tl);
++		if(ll <= 0) return ll;
++
++		skip += tl + ll;
++
++		/*
++		 * This may be the end of the indefinite length structure,
++		 * two consecutive 0 octets.
++		 * Check if it is true.
++		 */
++		if(((const uint8_t *)ptr)[0] == 0
++		&& ((const uint8_t *)ptr)[1] == 0)
++			return skip;
++
++		ptr = ((const char *)ptr) + tl + ll;
++		size -= tl + ll;
++ 	}
++
++	/* UNREACHABLE */
++}
++
++size_t
++der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) {
++	size_t required_size;	/* Size of len encoding */
++	uint8_t *buf = (uint8_t *)bufp;
++	uint8_t *end;
++	size_t i;
++
++	if(len <= 127) {
++		/* Encoded in 1 octet */
++		if(size) *buf = (uint8_t)len;
++		return 1;
++	}
++
++	/*
++	 * Compute the size of the subsequent bytes.
++	 */
++	for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) {
++		if(len >> i)
++			required_size++;
++		else
++			break;
++	}
++
++	if(size <= required_size)
++		return required_size + 1;
++
++	*buf++ = (uint8_t)(0x80 | required_size);  /* Length of the encoding */
++
++	/*
++	 * Produce the len encoding, space permitting.
++	 */
++	end = buf + required_size;
++	for(i -= 8; buf < end; i -= 8, buf++)
++		*buf = (uint8_t)(len >> i);
++
++	return required_size + 1;
++}
++
+diff --git a/asn1/asn1c/ber_tlv_length.h b/asn1/asn1c/ber_tlv_length.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..3496802244013c6c3652d5d067bccdf022e719cf
+--- /dev/null
++++ b/asn1/asn1c/ber_tlv_length.h
+@@ -0,0 +1,50 @@
++/*-
++ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_BER_TLV_LENGTH_H_
++#define	_BER_TLV_LENGTH_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef ssize_t ber_tlv_len_t;
++
++/*
++ * This function tries to fetch the length of the BER TLV value and place it
++ * in *len_r.
++ * RETURN VALUES:
++ *	 0:	More data expected than bufptr contains.
++ *	-1:	Fatal error deciphering length.
++ *	>0:	Number of bytes used from bufptr.
++ * On return with >0, len_r is constrained as -1..MAX, where -1 mean
++ * that the value is of indefinite length.
++ */
++ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
++	ber_tlv_len_t *len_r);
++
++/*
++ * This function expects bufptr to be positioned over L in TLV.
++ * It returns number of bytes occupied by L and V together, suitable
++ * for skipping. The function properly handles indefinite length.
++ * RETURN VALUES:
++ * 	Standard {-1,0,>0} convention.
++ */
++ssize_t ber_skip_length(
++	struct asn_codec_ctx_s *opt_codec_ctx,	/* optional context */
++	int _is_constructed, const void *bufptr, size_t size);
++
++/*
++ * This function serializes the length (L from TLV) in DER format.
++ * It always returns number of bytes necessary to represent the length,
++ * it is a caller's responsibility to check the return value
++ * against the supplied buffer's size.
++ */
++size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _BER_TLV_LENGTH_H_ */
+diff --git a/asn1/asn1c/ber_tlv_tag.c b/asn1/asn1c/ber_tlv_tag.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..42708760e089948b405743678efbc56ddd836c87
+--- /dev/null
++++ b/asn1/asn1c/ber_tlv_tag.c
+@@ -0,0 +1,144 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <ber_tlv_tag.h>
++#include <errno.h>
++
++ssize_t
++ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
++	ber_tlv_tag_t val;
++	ber_tlv_tag_t tclass;
++	size_t skipped;
++
++	if(size == 0)
++		return 0;
++
++	val = *(const uint8_t *)ptr;
++	tclass = (val >> 6);
++	if((val &= 0x1F) != 0x1F) {
++		/*
++		 * Simple form: everything encoded in a single octet.
++		 * Tag Class is encoded using two least significant bits.
++		 */
++		*tag_r = (val << 2) | tclass;
++		return 1;
++	}
++
++	/*
++	 * Each octet contains 7 bits of useful information.
++	 * The MSB is 0 if it is the last octet of the tag.
++	 */
++	for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2;
++			skipped <= size;
++				ptr = ((const char *)ptr) + 1, skipped++) {
++		unsigned int oct = *(const uint8_t *)ptr;
++		if(oct & 0x80) {
++			val = (val << 7) | (oct & 0x7F);
++			/*
++			 * Make sure there are at least 9 bits spare
++			 * at the MS side of a value.
++			 */
++			if(val >> ((8 * sizeof(val)) - 9)) {
++				/*
++				 * We would not be able to accomodate
++				 * any more tag bits.
++				 */
++				return -1;
++			}
++		} else {
++			val = (val << 7) | oct;
++			*tag_r = (val << 2) | tclass;
++			return skipped;
++		}
++	}
++
++	return 0;	/* Want more */
++}
++
++
++ssize_t
++ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
++	char buf[sizeof("[APPLICATION ]") + 32];
++	ssize_t ret;
++
++	ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));
++	if(ret >= (ssize_t)sizeof(buf) || ret < 2) {
++		errno = EPERM;
++		return -1;
++	}
++
++	return fwrite(buf, 1, ret, f);
++}
++
++ssize_t
++ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
++	char *type = 0;
++	int ret;
++
++	switch(tag & 0x3) {
++	case ASN_TAG_CLASS_UNIVERSAL:	type = "UNIVERSAL ";	break;
++	case ASN_TAG_CLASS_APPLICATION:	type = "APPLICATION ";	break;
++	case ASN_TAG_CLASS_CONTEXT:	type = "";		break;
++	case ASN_TAG_CLASS_PRIVATE:	type = "PRIVATE ";	break;
++	}
++
++	ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2);
++	if(ret <= 0 && size) buf[0] = '\0';	/* against broken libc's */
++
++	return ret;
++}
++
++char *
++ber_tlv_tag_string(ber_tlv_tag_t tag) {
++	static char buf[sizeof("[APPLICATION ]") + 32];
++
++	(void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
++
++	return buf;
++}
++
++
++size_t
++ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
++	int tclass = BER_TAG_CLASS(tag);
++	ber_tlv_tag_t tval = BER_TAG_VALUE(tag);
++	uint8_t *buf = (uint8_t *)bufp;
++	uint8_t *end;
++	size_t required_size;
++	size_t i;
++
++	if(tval <= 30) {
++		/* Encoded in 1 octet */
++		if(size) buf[0] = (tclass << 6) | tval;
++		return 1;
++	} else if(size) {
++		*buf++ = (tclass << 6) | 0x1F;
++		size--;
++	}
++
++	/*
++	 * Compute the size of the subsequent bytes.
++	 */
++	for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) {
++		if(tval >> i)
++			required_size++;
++		else
++			break;
++	}
++
++	if(size < required_size)
++		return required_size + 1;
++
++	/*
++	 * Fill in the buffer, space permitting.
++	 */
++	end = buf + required_size - 1;
++	for(i -= 7; buf < end; i -= 7, buf++)
++		*buf = 0x80 | ((tval >> i) & 0x7F);
++	*buf = (tval & 0x7F);	/* Last octet without high bit */
++
++	return required_size + 1;
++}
++
+diff --git a/asn1/asn1c/ber_tlv_tag.h b/asn1/asn1c/ber_tlv_tag.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..60e866861b28b3861f1e482452dcde1c844e5253
+--- /dev/null
++++ b/asn1/asn1c/ber_tlv_tag.h
+@@ -0,0 +1,60 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_BER_TLV_TAG_H_
++#define	_BER_TLV_TAG_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++enum asn_tag_class {
++	ASN_TAG_CLASS_UNIVERSAL		= 0,	/* 0b00 */
++	ASN_TAG_CLASS_APPLICATION	= 1,	/* 0b01 */
++	ASN_TAG_CLASS_CONTEXT		= 2,	/* 0b10 */
++	ASN_TAG_CLASS_PRIVATE		= 3	/* 0b11 */
++};
++typedef unsigned ber_tlv_tag_t;	/* BER TAG from Tag-Length-Value */
++
++/*
++ * Tag class is encoded together with tag value for optimization purposes.
++ */
++#define	BER_TAG_CLASS(tag)	((tag) & 0x3)
++#define	BER_TAG_VALUE(tag)	((tag) >> 2)
++#define	BER_TLV_CONSTRUCTED(tagptr)	(((*(const uint8_t *)tagptr)&0x20)?1:0)
++
++#define	BER_TAGS_EQUAL(tag1, tag2)	((tag1) == (tag2))
++
++/*
++ * Several functions for printing the TAG in the canonical form
++ * (i.e. "[PRIVATE 0]").
++ * Return values correspond to their libc counterparts (if any).
++ */
++ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen);
++ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *);
++char *ber_tlv_tag_string(ber_tlv_tag_t tag);
++
++
++/*
++ * This function tries to fetch the tag from the input stream.
++ * RETURN VALUES:
++ * 	 0:	More data expected than bufptr contains.
++ * 	-1:	Fatal error deciphering tag.
++ *	>0:	Number of bytes used from bufptr. tag_r will contain the tag.
++ */
++ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r);
++
++/*
++ * This function serializes the tag (T from TLV) in BER format.
++ * It always returns number of bytes necessary to represent the tag,
++ * it is a caller's responsibility to check the return value
++ * against the supplied buffer's size.
++ */
++size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _BER_TLV_TAG_H_ */
+diff --git a/asn1/asn1c/constr_CHOICE.c b/asn1/asn1c/constr_CHOICE.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..b8d6fa9a7f210585e851f8f1ab3cadf1d8fe4923
+--- /dev/null
++++ b/asn1/asn1c/constr_CHOICE.c
+@@ -0,0 +1,1101 @@
++/*
++ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <constr_CHOICE.h>
++
++/*
++ * Number of bytes left for this structure.
++ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
++ * (size) contains the number of bytes in the buffer passed.
++ */
++#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
++
++/*
++ * If the subprocessor function returns with an indication that it wants
++ * more data, it may well be a fatal decoding problem, because the
++ * size is constrained by the <TLV>'s L, even if the buffer size allows
++ * reading more data.
++ * For example, consider the buffer containing the following TLVs:
++ * <T:5><L:1><V> <T:6>...
++ * The TLV length clearly indicates that one byte is expected in V, but
++ * if the V processor returns with "want more data" even if the buffer
++ * contains way more data than the V processor have seen.
++ */
++#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
++
++/*
++ * This macro "eats" the part of the buffer which is definitely "consumed",
++ * i.e. was correctly converted into local representation or rightfully skipped.
++ */
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {		\
++		size_t num = num_bytes;		\
++		ptr = ((const char *)ptr) + num;\
++		size -= num;			\
++		if(ctx->left >= 0)		\
++			ctx->left -= num;	\
++		consumed_myself += num;		\
++	} while(0)
++
++/*
++ * Switch to the next phase of parsing.
++ */
++#undef	NEXT_PHASE
++#define	NEXT_PHASE(ctx)	do {			\
++		ctx->phase++;			\
++		ctx->step = 0;			\
++	} while(0)
++
++/*
++ * Return a standardized complex structure.
++ */
++#undef	RETURN
++#define	RETURN(_code)	do {			\
++		rval.code = _code;		\
++		rval.consumed = consumed_myself;\
++		return rval;			\
++	} while(0)
++
++/*
++ * See the definitions.
++ */
++static int _fetch_present_idx(const void *struct_ptr, int off, int size);
++static void _set_present_idx(void *sptr, int offset, int size, int pres);
++
++/*
++ * Tags are canonically sorted in the tag to member table.
++ */
++static int
++_search4tag(const void *ap, const void *bp) {
++	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
++	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
++
++	int a_class = BER_TAG_CLASS(a->el_tag);
++	int b_class = BER_TAG_CLASS(b->el_tag);
++
++	if(a_class == b_class) {
++		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
++		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
++
++		if(a_value == b_value)
++			return 0;
++		else if(a_value < b_value)
++			return -1;
++		else
++			return 1;
++	} else if(a_class < b_class) {
++		return -1;
++	} else {
++		return 1;
++	}
++}
++
++/*
++ * The decoder of the CHOICE type.
++ */
++asn_dec_rval_t
++CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elements = td->elements;
++
++	/*
++	 * Parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	ber_tlv_tag_t tlv_tag;	/* T from TLV */
++	ssize_t tag_len;	/* Length of TLV's T */
++	asn_dec_rval_t rval;	/* Return code from subparsers */
++
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++
++	ASN_DEBUG("Decoding %s as CHOICE", td->name);
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) {
++			RETURN(RC_FAIL);
++		}
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++	
++	/*
++	 * Start to parse where left previously
++	 */
++	switch(ctx->phase) {
++	case 0:
++		/*
++		 * PHASE 0.
++		 * Check that the set of tags associated with given structure
++		 * perfectly fits our expectations.
++		 */
++
++		if(tag_mode || td->tags_count) {
++			rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
++				tag_mode, -1, &ctx->left, 0);
++			if(rval.code != RC_OK) {
++				ASN_DEBUG("%s tagging check failed: %d",
++					td->name, rval.code);
++				return rval;
++			}
++
++			if(ctx->left >= 0) {
++				/* ?Substracted below! */
++				ctx->left += rval.consumed;
++			}
++			ADVANCE(rval.consumed);
++		} else {
++			ctx->left = -1;
++		}
++
++		NEXT_PHASE(ctx);
++
++		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
++			(long)ctx->left, (long)size);
++
++		/* Fall through */
++	case 1:
++		/*
++		 * Fetch the T from TLV.
++		 */
++		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
++		ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
++		switch(tag_len) {
++		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++			/* Fall through */
++		case -1: RETURN(RC_FAIL);
++		}
++
++		do {
++			asn_TYPE_tag2member_t *t2m;
++			asn_TYPE_tag2member_t key;
++
++			key.el_tag = tlv_tag;
++			t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
++					specs->tag2el, specs->tag2el_count,
++					sizeof(specs->tag2el[0]), _search4tag);
++			if(t2m) {
++				/*
++				 * Found the element corresponding to the tag.
++				 */
++				NEXT_PHASE(ctx);
++				ctx->step = t2m->el_no;
++				break;
++			} else if(specs->ext_start == -1) {
++				ASN_DEBUG("Unexpected tag %s "
++					"in non-extensible CHOICE %s",
++					ber_tlv_tag_string(tlv_tag), td->name);
++				RETURN(RC_FAIL);
++			} else {
++				/* Skip this tag */
++				ssize_t skip;
++
++				ASN_DEBUG("Skipping unknown tag %s",
++					ber_tlv_tag_string(tlv_tag));
++
++				skip = ber_skip_length(opt_codec_ctx,
++					BER_TLV_CONSTRUCTED(ptr),
++					(const char *)ptr + tag_len,
++					LEFT - tag_len);
++
++				switch(skip) {
++				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++					/* Fall through */
++				case -1: RETURN(RC_FAIL);
++				}
++
++				ADVANCE(skip + tag_len);
++				RETURN(RC_OK);
++			}
++		} while(0);
++
++	case 2:
++		/*
++		 * PHASE 2.
++		 * Read in the element.
++		 */
++	    do {
++		asn_TYPE_member_t *elm;/* CHOICE's element */
++		void *memb_ptr;		/* Pointer to the member */
++		void **memb_ptr2;	/* Pointer to that pointer */
++
++		elm = &elements[ctx->step];
++
++		/*
++		 * Compute the position of the member inside a structure,
++		 * and also a type of containment (it may be contained
++		 * as pointer or using inline inclusion).
++		 */
++		if(elm->flags & ATF_POINTER) {
++			/* Member is a pointer to another structure */
++			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
++		} else {
++			/*
++			 * A pointer to a pointer
++			 * holding the start of the structure
++			 */
++			memb_ptr = (char *)st + elm->memb_offset;
++			memb_ptr2 = &memb_ptr;
++		}
++		/* Set presence to be able to free it properly at any time */
++		_set_present_idx(st, specs->pres_offset,
++				specs->pres_size, ctx->step + 1);
++		/*
++		 * Invoke the member fetch routine according to member's type
++		 */
++		rval = elm->type->ber_decoder(opt_codec_ctx, elm->type,
++				memb_ptr2, ptr, LEFT, elm->tag_mode);
++		switch(rval.code) {
++		case RC_OK:
++			break;
++		case RC_WMORE: /* More data expected */
++			if(!SIZE_VIOLATION) {
++				ADVANCE(rval.consumed);
++				RETURN(RC_WMORE);
++			}
++			RETURN(RC_FAIL);
++		case RC_FAIL: /* Fatal error */
++			RETURN(rval.code);
++		} /* switch(rval) */
++		
++		ADVANCE(rval.consumed);
++	  } while(0);
++
++		NEXT_PHASE(ctx);
++
++		/* Fall through */
++	case 3:
++		ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
++			td->name, (long)ctx->left, (long)size,
++			tag_mode, td->tags_count);
++
++		if(ctx->left > 0) {
++			/*
++			 * The type must be fully decoded
++			 * by the CHOICE member-specific decoder.
++			 */
++			RETURN(RC_FAIL);
++		}
++
++		if(ctx->left == -1
++		&& !(tag_mode || td->tags_count)) {
++			/*
++			 * This is an untagged CHOICE.
++			 * It doesn't contain nothing
++			 * except for the member itself, including all its tags.
++			 * The decoding is completed.
++			 */
++			NEXT_PHASE(ctx);
++			break;
++		}
++
++		/*
++		 * Read in the "end of data chunks"'s.
++		 */
++		while(ctx->left < 0) {
++			ssize_t tl;
++
++			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
++			switch(tl) {
++			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++				/* Fall through */
++			case -1: RETURN(RC_FAIL);
++			}
++
++			/*
++			 * Expected <0><0>...
++			 */
++			if(((const uint8_t *)ptr)[0] == 0) {
++				if(LEFT < 2) {
++					if(SIZE_VIOLATION)
++						RETURN(RC_FAIL);
++					else
++						RETURN(RC_WMORE);
++				} else if(((const uint8_t *)ptr)[1] == 0) {
++					/*
++					 * Correctly finished with <0><0>.
++					 */
++					ADVANCE(2);
++					ctx->left++;
++					continue;
++				}
++			} else {
++				ASN_DEBUG("Unexpected continuation in %s",
++					td->name);
++				RETURN(RC_FAIL);
++			}
++
++			/* UNREACHABLE */
++		}
++
++		NEXT_PHASE(ctx);
++	case 4:
++		/* No meaningful work here */
++		break;
++	}
++	
++	RETURN(RC_OK);
++}
++
++asn_enc_rval_t
++CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
++		int tag_mode, ber_tlv_tag_t tag,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm;	/* CHOICE element */
++	asn_enc_rval_t erval;
++	void *memb_ptr;
++	size_t computed_size = 0;
++	int present;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++
++	ASN_DEBUG("%s %s as CHOICE",
++		cb?"Encoding":"Estimating", td->name);
++
++	present = _fetch_present_idx(sptr,
++		specs->pres_offset, specs->pres_size);
++
++	/*
++	 * If the structure was not initialized, it cannot be encoded:
++	 * can't deduce what to encode in the choice type.
++	 */
++	if(present <= 0 || present > td->elements_count) {
++		if(present == 0 && td->elements_count == 0) {
++			/* The CHOICE is empty?! */
++			erval.encoded = 0;
++			_ASN_ENCODED_OK(erval);
++		}
++		_ASN_ENCODE_FAILED;
++	}
++
++	/*
++	 * Seek over the present member of the structure.
++	 */
++	elm = &td->elements[present-1];
++	if(elm->flags & ATF_POINTER) {
++		memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++		if(memb_ptr == 0) {
++			if(elm->optional) {
++				erval.encoded = 0;
++				_ASN_ENCODED_OK(erval);
++			}
++			/* Mandatory element absent */
++			_ASN_ENCODE_FAILED;
++		}
++	} else {
++		memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++	}
++
++	/*
++	 * If the CHOICE itself is tagged EXPLICIT:
++	 * T ::= [2] EXPLICIT CHOICE { ... }
++	 * Then emit the appropriate tags.
++	 */
++	if(tag_mode == 1 || td->tags_count) {
++		/*
++		 * For this, we need to pre-compute the member.
++		 */
++		ssize_t ret;
++
++		/* Encode member with its tag */
++		erval = elm->type->der_encoder(elm->type, memb_ptr,
++			elm->tag_mode, elm->tag, 0, 0);
++		if(erval.encoded == -1)
++			return erval;
++
++		/* Encode CHOICE with parent or my own tag */
++		ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
++			cb, app_key);
++		if(ret == -1)
++			_ASN_ENCODE_FAILED;
++		computed_size += ret;
++	}
++
++	/*
++	 * Encode the single underlying member.
++	 */
++	erval = elm->type->der_encoder(elm->type, memb_ptr,
++		elm->tag_mode, elm->tag, cb, app_key);
++	if(erval.encoded == -1)
++		return erval;
++
++	ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
++		(long)erval.encoded, (long)computed_size);
++
++	erval.encoded += computed_size;
++
++	return erval;
++}
++
++ber_tlv_tag_t
++CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	int present;
++
++	assert(tag_mode == 0); (void)tag_mode;
++	assert(tag == 0); (void)tag;
++
++	/*
++	 * Figure out which CHOICE element is encoded.
++	 */
++	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
++
++	if(present > 0 || present <= td->elements_count) {
++		asn_TYPE_member_t *elm = &td->elements[present-1];
++		const void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(const void * const *)
++					((const char *)ptr + elm->memb_offset);
++		} else {
++			memb_ptr = (const void *)
++					((const char *)ptr + elm->memb_offset);
++		}
++
++		return asn_TYPE_outmost_tag(elm->type, memb_ptr,
++			elm->tag_mode, elm->tag);
++	} else {
++		return (ber_tlv_tag_t)-1;
++	}
++}
++
++int
++CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
++		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	int present;
++
++	if(!sptr) {
++		_ASN_CTFAIL(app_key, td,
++			"%s: value not given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++
++	/*
++	 * Figure out which CHOICE element is encoded.
++	 */
++	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
++	if(present > 0 && present <= td->elements_count) {
++		asn_TYPE_member_t *elm = &td->elements[present-1];
++		const void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
++			if(!memb_ptr) {
++				if(elm->optional)
++					return 0;
++				_ASN_CTFAIL(app_key, td,
++					"%s: mandatory CHOICE element %s absent (%s:%d)",
++					td->name, elm->name, __FILE__, __LINE__);
++				return -1;
++			}
++		} else {
++			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
++		}
++
++		if(elm->memb_constraints) {
++			return elm->memb_constraints(elm->type, memb_ptr,
++				ctfailcb, app_key);
++		} else {
++			int ret = elm->type->check_constraints(elm->type,
++					memb_ptr, ctfailcb, app_key);
++			/*
++			 * Cannot inherit it eralier:
++			 * need to make sure we get the updated version.
++			 */
++			elm->memb_constraints = elm->type->check_constraints;
++			return ret;
++		}
++	} else {
++		_ASN_CTFAIL(app_key, td,
++			"%s: no CHOICE element given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++}
++
++#undef	XER_ADVANCE
++#define	XER_ADVANCE(num_bytes)	do {			\
++		size_t num = num_bytes;			\
++		buf_ptr = ((const char *)buf_ptr) + num;\
++		size -= num;				\
++		consumed_myself += num;			\
++	} while(0)
++
++/*
++ * Decode the XER (XML) data.
++ */
++asn_dec_rval_t
++CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const char *opt_mname,
++		const void *buf_ptr, size_t size) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
++
++	/*
++	 * Parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	asn_dec_rval_t rval;		/* Return value of a decoder */
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++	int edx;			/* Element index */
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) RETURN(RC_FAIL);
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++	if(ctx->phase == 0 && !*xml_tag)
++		ctx->phase = 1;	/* Skip the outer tag checking phase */
++
++	/*
++	 * Phases of XER/XML processing:
++	 * Phase 0: Check that the opening tag matches our expectations.
++	 * Phase 1: Processing body and reacting on closing tag.
++	 * Phase 2: Processing inner type.
++	 * Phase 3: Only waiting for closing tag.
++	 * Phase 4: Skipping unknown extensions.
++	 * Phase 5: PHASED OUT
++	 */
++	for(edx = ctx->step; ctx->phase <= 4;) {
++		pxer_chunk_type_e ch_type;	/* XER chunk type */
++		ssize_t ch_size;		/* Chunk size */
++		xer_check_tag_e tcv;		/* Tag check value */
++		asn_TYPE_member_t *elm;
++
++		/*
++		 * Go inside the member.
++		 */
++		if(ctx->phase == 2) {
++			asn_dec_rval_t tmprval;
++			void *memb_ptr;		/* Pointer to the member */
++			void **memb_ptr2;	/* Pointer to that pointer */
++
++			elm = &td->elements[edx];
++
++			if(elm->flags & ATF_POINTER) {
++				/* Member is a pointer to another structure */
++				memb_ptr2 = (void **)((char *)st
++					+ elm->memb_offset);
++			} else {
++				memb_ptr = (char *)st + elm->memb_offset;
++				memb_ptr2 = &memb_ptr;
++			}
++
++			/* Start/Continue decoding the inner member */
++			tmprval = elm->type->xer_decoder(opt_codec_ctx,
++					elm->type, memb_ptr2, elm->name,
++					buf_ptr, size);
++			XER_ADVANCE(tmprval.consumed);
++			ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
++				elm->type->name, tmprval.code);
++			if(tmprval.code != RC_OK)
++				RETURN(tmprval.code);
++			assert(_fetch_present_idx(st,
++				specs->pres_offset, specs->pres_size) == 0);
++			/* Record what we've got */
++			_set_present_idx(st,
++				specs->pres_offset, specs->pres_size, edx + 1);
++			ctx->phase = 3;
++			/* Fall through */
++		}
++
++		/* No need to wait for closing tag; special mode. */
++		if(ctx->phase == 3 && !*xml_tag) {
++			ctx->phase = 5;	/* Phase out */
++			RETURN(RC_OK);
++		}
++
++		/*
++		 * Get the next part of the XML stream.
++		 */
++		ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
++		switch(ch_size) {
++		case -1: RETURN(RC_FAIL);
++		case 0:  RETURN(RC_WMORE);
++		default:
++			switch(ch_type) {
++			case PXER_COMMENT:	/* Got XML comment */
++			case PXER_TEXT:		/* Ignore free-standing text */
++				XER_ADVANCE(ch_size);	/* Skip silently */
++				continue;
++			case PXER_TAG:
++				break;	/* Check the rest down there */
++			}
++		}
++
++		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
++		ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
++			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
++			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
++			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
++			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
++		xml_tag, tcv);
++
++		/* Skip the extensions section */
++		if(ctx->phase == 4) {
++			ASN_DEBUG("skip_unknown(%d, %ld)",
++				tcv, (long)ctx->left);
++			switch(xer_skip_unknown(tcv, &ctx->left)) {
++			case -1:
++				ctx->phase = 5;
++				RETURN(RC_FAIL);
++				continue;
++			case 1:
++				ctx->phase = 3;
++				/* Fall through */
++			case 0:
++				XER_ADVANCE(ch_size);
++				continue;
++			case 2:
++				ctx->phase = 3;
++				break;
++			}
++		}
++
++		switch(tcv) {
++		case XCT_BOTH:
++			break;	/* No CHOICE? */
++		case XCT_CLOSING:
++			if(ctx->phase != 3)
++				break;
++			XER_ADVANCE(ch_size);
++			ctx->phase = 5;	/* Phase out */
++			RETURN(RC_OK);
++		case XCT_OPENING:
++			if(ctx->phase == 0) {
++				XER_ADVANCE(ch_size);
++				ctx->phase = 1;	/* Processing body phase */
++				continue;
++			}
++			/* Fall through */
++		case XCT_UNKNOWN_OP:
++		case XCT_UNKNOWN_BO:
++
++			if(ctx->phase != 1)
++				break;	/* Really unexpected */
++
++			/*
++			 * Search which inner member corresponds to this tag.
++			 */
++			for(edx = 0; edx < td->elements_count; edx++) {
++				elm = &td->elements[edx];
++				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
++				switch(tcv) {
++				case XCT_BOTH:
++				case XCT_OPENING:
++					/*
++					 * Process this member.
++					 */
++					ctx->step = edx;
++					ctx->phase = 2;
++					break;
++				case XCT_UNKNOWN_OP:
++				case XCT_UNKNOWN_BO:
++					continue;
++				default:
++					edx = td->elements_count;
++					break;	/* Phase out */
++				}
++				break;
++			}
++			if(edx != td->elements_count)
++				continue;
++
++			/* It is expected extension */
++			if(specs->ext_start != -1) {
++				ASN_DEBUG("Got anticipated extension");
++				/*
++				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
++				 * By using a mask. Only record a pure
++				 * <opening> tags.
++				 */
++				if(tcv & XCT_CLOSING) {
++					/* Found </extension> without body */
++					ctx->phase = 3; /* Terminating */
++				} else {
++					ctx->left = 1;
++					ctx->phase = 4; /* Skip ...'s */
++				}
++				XER_ADVANCE(ch_size);
++				continue;
++			}
++
++			/* Fall through */
++		default:
++			break;
++		}
++
++		ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
++			" (ph=%d, tag=%s)",
++			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
++			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
++			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
++			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
++			td->name, ctx->phase, xml_tag);
++		break;
++	}
++
++	ctx->phase = 5;	/* Phase out, just in case */
++	RETURN(RC_FAIL);
++}
++
++
++asn_enc_rval_t
++CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
++	asn_enc_rval_t er;
++	int present;
++
++	if(!sptr)
++		_ASN_ENCODE_FAILED;
++
++	/*
++	 * Figure out which CHOICE element is encoded.
++	 */
++	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
++
++	if(present <= 0 || present > td->elements_count) {
++		_ASN_ENCODE_FAILED;
++	}  else {
++		asn_enc_rval_t tmper;
++		asn_TYPE_member_t *elm = &td->elements[present-1];
++		void *memb_ptr;
++		const char *mname = elm->name;
++		unsigned int mlen = strlen(mname);
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++			if(!memb_ptr) _ASN_ENCODE_FAILED;
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++		}
++
++		er.encoded = 0;
++
++                if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel);
++		_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
++
++		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
++				ilevel + 1, flags, cb, app_key);
++		if(tmper.encoded == -1) return tmper;
++
++		_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
++
++		er.encoded += 5 + (2 * mlen) + tmper.encoded;
++	}
++
++	if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel - 1);
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++asn_dec_rval_t
++CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	asn_dec_rval_t rv;
++	asn_per_constraint_t *ct;
++	asn_TYPE_member_t *elm;	/* CHOICE's element */
++	void *memb_ptr;
++	void **memb_ptr2;
++	void *st = *sptr;
++	int value;
++
++	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
++		_ASN_DECODE_FAILED;
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(!st) {
++		st = *sptr = CALLOC(1, specs->struct_size);
++		if(!st) _ASN_DECODE_FAILED;
++	}
++
++	if(constraints) ct = &constraints->value;
++	else if(td->per_constraints) ct = &td->per_constraints->value;
++	else ct = 0;
++
++	if(ct && ct->flags & APC_EXTENSIBLE) {
++		value = per_get_few_bits(pd, 1);
++		if(value < 0) _ASN_DECODE_STARVED;
++		if(value) ct = 0;	/* Not restricted */
++	}
++
++	if(ct && ct->range_bits >= 0) {
++		value = per_get_few_bits(pd, ct->range_bits);
++		if(value < 0) _ASN_DECODE_STARVED;
++		ASN_DEBUG("CHOICE %s got index %d in range %d",
++			td->name, value, ct->range_bits);
++		if(value > ct->upper_bound)
++			_ASN_DECODE_FAILED;
++	} else {
++		if(specs->ext_start == -1)
++			_ASN_DECODE_FAILED;
++		value = uper_get_nsnnwn(pd);
++		if(value < 0) _ASN_DECODE_STARVED;
++		value += specs->ext_start;
++		if(value >= td->elements_count)
++			_ASN_DECODE_FAILED;
++		ASN_DEBUG("NOT IMPLEMENTED YET");
++		_ASN_DECODE_FAILED;
++	}
++
++	/* Adjust if canonical order is different from natural order */
++	if(specs->canonical_order)
++		value = specs->canonical_order[value];
++
++	/* Set presence to be able to free it later */
++	_set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
++
++	elm = &td->elements[value];
++	if(elm->flags & ATF_POINTER) {
++		/* Member is a pointer to another structure */
++		memb_ptr2 = (void **)((char *)st + elm->memb_offset);
++	} else {
++		memb_ptr = (char *)st + elm->memb_offset;
++		memb_ptr2 = &memb_ptr;
++	}
++	ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
++
++	rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
++			elm->per_constraints, memb_ptr2, pd);
++	if(rv.code != RC_OK)
++		ASN_DEBUG("Failed to decode %s in %s (CHOICE)",
++			elm->name, td->name);
++	return rv;
++}
++   
++asn_enc_rval_t
++CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm;	/* CHOICE's element */
++	asn_per_constraint_t *ct;
++	void *memb_ptr;
++	int present;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++
++	ASN_DEBUG("Encoding %s as CHOICE", td->name);
++
++	if(constraints) ct = &constraints->value;
++	else if(td->per_constraints) ct = &td->per_constraints->value;
++	else ct = 0;
++
++	present = _fetch_present_idx(sptr,
++		specs->pres_offset, specs->pres_size);
++
++	/*
++	 * If the structure was not initialized properly, it cannot be encoded:
++	 * can't deduce what to encode in the choice type.
++	 */
++	if(present <= 0 || present > td->elements_count)
++		_ASN_ENCODE_FAILED;
++	else
++		present--;
++
++	/* Adjust if canonical order is different from natural order */
++	if(specs->canonical_order)
++		present = specs->canonical_order[present];
++
++	ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
++
++	if(ct && ct->range_bits >= 0) {
++		if(present < ct->lower_bound
++		|| present > ct->upper_bound) {
++			if(ct->flags & APC_EXTENSIBLE) {
++				if(per_put_few_bits(po, 1, 1))
++					_ASN_ENCODE_FAILED;
++			} else {
++				_ASN_ENCODE_FAILED;
++			}
++			ct = 0;
++		}
++	}
++	if(ct && ct->flags & APC_EXTENSIBLE)
++		if(per_put_few_bits(po, 0, 1))
++			_ASN_ENCODE_FAILED;
++
++	if(ct && ct->range_bits >= 0) {
++		if(per_put_few_bits(po, present, ct->range_bits))
++			_ASN_ENCODE_FAILED;
++	} else {
++		if(specs->ext_start == -1)
++			_ASN_ENCODE_FAILED;
++		if(uper_put_nsnnwn(po, present - specs->ext_start))
++			_ASN_ENCODE_FAILED;
++		ASN_DEBUG("NOT IMPLEMENTED YET");
++		_ASN_ENCODE_FAILED;
++	}
++
++	elm = &td->elements[present];
++	if(elm->flags & ATF_POINTER) {
++		/* Member is a pointer to another structure */
++		memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++		if(!memb_ptr) _ASN_ENCODE_FAILED;
++	} else {
++		memb_ptr = (char *)sptr + elm->memb_offset;
++	}
++
++	return elm->type->uper_encoder(elm->type, elm->per_constraints,
++			memb_ptr, po);
++}
++   
++
++int
++CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	int present;
++
++	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++
++	/*
++	 * Figure out which CHOICE element is encoded.
++	 */
++	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
++
++	/*
++	 * Print that element.
++	 */
++	if(present > 0 && present <= td->elements_count) {
++		asn_TYPE_member_t *elm = &td->elements[present-1];
++		const void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
++			if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++		} else {
++			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
++		}
++
++		/* Print member's name and stuff */
++		if(0) {
++			if(cb(elm->name, strlen(elm->name), app_key) < 0
++			|| cb(": ", 2, app_key) < 0)
++				return -1;
++		}
++
++		return elm->type->print_struct(elm->type, memb_ptr, ilevel,
++			cb, app_key);
++	} else {
++		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++	}
++}
++
++void
++CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
++	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
++	int present;
++
++	if(!td || !ptr)
++		return;
++
++	ASN_DEBUG("Freeing %s as CHOICE", td->name);
++
++	/*
++	 * Figure out which CHOICE element is encoded.
++	 */
++	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
++
++	/*
++	 * Free that element.
++	 */
++	if(present > 0 && present <= td->elements_count) {
++		asn_TYPE_member_t *elm = &td->elements[present-1];
++		void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
++			if(memb_ptr)
++				ASN_STRUCT_FREE(*elm->type, memb_ptr);
++		} else {
++			memb_ptr = (void *)((char *)ptr + elm->memb_offset);
++			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
++		}
++	}
++
++	if(!contents_only) {
++		FREEMEM(ptr);
++	}
++}
++
++
++/*
++ * The following functions functions offer protection against -fshort-enums,
++ * compatible with little- and big-endian machines.
++ * If assertion is triggered, either disable -fshort-enums, or add an entry
++ * here with the ->pres_size of your target stracture.
++ * Unless the target structure is packed, the ".present" member
++ * is guaranteed to be aligned properly. ASN.1 compiler itself does not
++ * produce packed code.
++ */
++static int
++_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
++	const void *present_ptr;
++	int present;
++
++	present_ptr = ((const char *)struct_ptr) + pres_offset;
++
++	switch(pres_size) {
++	case sizeof(int):	present =   *(const int *)present_ptr; break;
++	case sizeof(short):	present = *(const short *)present_ptr; break;
++	case sizeof(char):	present =  *(const char *)present_ptr; break;
++	default:
++		/* ANSI C mandates enum to be equivalent to integer */
++		assert(pres_size != sizeof(int));
++		return 0;	/* If not aborted, pass back safe value */
++	}
++
++	return present;
++}
++
++static void
++_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) {
++	void *present_ptr;
++	present_ptr = ((char *)struct_ptr) + pres_offset;
++
++	switch(pres_size) {
++	case sizeof(int):	*(int *)present_ptr   = present; break;
++	case sizeof(short):	*(short *)present_ptr = present; break;
++	case sizeof(char):	*(char *)present_ptr  = present; break;
++	default:
++		/* ANSI C mandates enum to be equivalent to integer */
++		assert(pres_size != sizeof(int));
++	}
++}
+diff --git a/asn1/asn1c/constr_CHOICE.h b/asn1/asn1c/constr_CHOICE.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..83404e6d43573c9903888fb5c49853e852a7848e
+--- /dev/null
++++ b/asn1/asn1c/constr_CHOICE.h
+@@ -0,0 +1,57 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_CONSTR_CHOICE_H_
++#define	_CONSTR_CHOICE_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct asn_CHOICE_specifics_s {
++	/*
++	 * Target structure description.
++	 */
++	int struct_size;	/* Size of the target structure. */
++	int ctx_offset;		/* Offset of the asn_codec_ctx_t member */
++	int pres_offset;	/* Identifier of the present member */
++	int pres_size;		/* Size of the identifier (enum) */
++
++	/*
++	 * Tags to members mapping table.
++	 */
++	asn_TYPE_tag2member_t *tag2el;
++	int tag2el_count;
++
++	/* Canonical ordering of CHOICE elements, for PER */
++	int *canonical_order;
++
++	/*
++	 * Extensions-related stuff.
++	 */
++	int ext_start;		/* First member of extensions, or -1 */
++} asn_CHOICE_specifics_t;
++
++/*
++ * A set specialized functions dealing with the CHOICE type.
++ */
++asn_struct_free_f CHOICE_free;
++asn_struct_print_f CHOICE_print;
++asn_constr_check_f CHOICE_constraint;
++ber_type_decoder_f CHOICE_decode_ber;
++der_type_encoder_f CHOICE_encode_der;
++xer_type_decoder_f CHOICE_decode_xer;
++xer_type_encoder_f CHOICE_encode_xer;
++per_type_decoder_f CHOICE_decode_uper;
++per_type_encoder_f CHOICE_encode_uper;
++asn_outmost_tag_f CHOICE_outmost_tag;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _CONSTR_CHOICE_H_ */
+diff --git a/asn1/asn1c/constr_SEQUENCE.c b/asn1/asn1c/constr_SEQUENCE.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..b769434345763a454777a89458155f5debea73c8
+--- /dev/null
++++ b/asn1/asn1c/constr_SEQUENCE.c
+@@ -0,0 +1,1251 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <constr_SEQUENCE.h>
++
++/*
++ * Number of bytes left for this structure.
++ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
++ * (size) contains the number of bytes in the buffer passed.
++ */
++#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
++
++/*
++ * If the subprocessor function returns with an indication that it wants
++ * more data, it may well be a fatal decoding problem, because the
++ * size is constrained by the <TLV>'s L, even if the buffer size allows
++ * reading more data.
++ * For example, consider the buffer containing the following TLVs:
++ * <T:5><L:1><V> <T:6>...
++ * The TLV length clearly indicates that one byte is expected in V, but
++ * if the V processor returns with "want more data" even if the buffer
++ * contains way more data than the V processor have seen.
++ */
++#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
++
++/*
++ * This macro "eats" the part of the buffer which is definitely "consumed",
++ * i.e. was correctly converted into local representation or rightfully skipped.
++ */
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {		\
++		size_t num = num_bytes;		\
++		ptr = ((const char *)ptr) + num;\
++		size -= num;			\
++		if(ctx->left >= 0)		\
++			ctx->left -= num;	\
++		consumed_myself += num;		\
++	} while(0)
++
++/*
++ * Switch to the next phase of parsing.
++ */
++#undef	NEXT_PHASE
++#undef	PHASE_OUT
++#define	NEXT_PHASE(ctx)	do {			\
++		ctx->phase++;			\
++		ctx->step = 0;			\
++	} while(0)
++#define	PHASE_OUT(ctx)	do { ctx->phase = 10; } while(0)
++
++/*
++ * Return a standardized complex structure.
++ */
++#undef	RETURN
++#define	RETURN(_code)	do {			\
++		rval.code = _code;		\
++		rval.consumed = consumed_myself;\
++		return rval;			\
++	} while(0)
++
++/*
++ * Check whether we are inside the extensions group.
++ */
++#define	IN_EXTENSION_GROUP(specs, memb_idx)	\
++	( ((memb_idx) > (specs)->ext_after)	\
++	&&((memb_idx) < (specs)->ext_before))
++
++
++/*
++ * Tags are canonically sorted in the tag2element map.
++ */
++static int
++_t2e_cmp(const void *ap, const void *bp) {
++	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
++	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
++
++	int a_class = BER_TAG_CLASS(a->el_tag);
++	int b_class = BER_TAG_CLASS(b->el_tag);
++
++	if(a_class == b_class) {
++		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
++		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
++
++		if(a_value == b_value) {
++			if(a->el_no > b->el_no)
++				return 1;
++			/*
++			 * Important: we do not check
++			 * for a->el_no <= b->el_no!
++			 */
++			return 0;
++		} else if(a_value < b_value)
++			return -1;
++		else
++			return 1;
++	} else if(a_class < b_class) {
++		return -1;
++	} else {
++		return 1;
++	}
++}
++
++
++/*
++ * The decoder of the SEQUENCE type.
++ */
++asn_dec_rval_t
++SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elements = td->elements;
++
++	/*
++	 * Parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	ber_tlv_tag_t tlv_tag;	/* T from TLV */
++	asn_dec_rval_t rval;	/* Return code from subparsers */
++
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++	int edx;			/* SEQUENCE element's index */
++
++	ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
++	
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) {
++			RETURN(RC_FAIL);
++		}
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++	
++	/*
++	 * Start to parse where left previously
++	 */
++	switch(ctx->phase) {
++	case 0:
++		/*
++		 * PHASE 0.
++		 * Check that the set of tags associated with given structure
++		 * perfectly fits our expectations.
++		 */
++
++		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
++			tag_mode, 1, &ctx->left, 0);
++		if(rval.code != RC_OK) {
++			ASN_DEBUG("%s tagging check failed: %d",
++				td->name, rval.code);
++			return rval;
++		}
++
++		if(ctx->left >= 0)
++			ctx->left += rval.consumed; /* ?Substracted below! */
++		ADVANCE(rval.consumed);
++
++		NEXT_PHASE(ctx);
++
++		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
++			(long)ctx->left, (long)size);
++
++		/* Fall through */
++	case 1:
++		/*
++		 * PHASE 1.
++		 * From the place where we've left it previously,
++		 * try to decode the next member from the list of
++		 * this structure's elements.
++		 * (ctx->step) stores the member being processed
++		 * between invocations and the microphase {0,1} of parsing
++		 * that member:
++		 * 	step = (<member_number> * 2 + <microphase>).
++		 */
++	  for(edx = (ctx->step >> 1); edx < td->elements_count;
++			edx++, ctx->step = (ctx->step & ~1) + 2) {
++		void *memb_ptr;		/* Pointer to the member */
++		void **memb_ptr2;	/* Pointer to that pointer */
++		ssize_t tag_len;	/* Length of TLV's T */
++		int opt_edx_end;	/* Next non-optional element */
++		int use_bsearch;
++		int n;
++
++		if(ctx->step & 1)
++			goto microphase2;
++
++		/*
++		 * MICROPHASE 1: Synchronize decoding.
++		 */
++		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
++				" opt=%d ec=%d",
++			td->name, (int)ctx->left, edx,
++			elements[edx].flags, elements[edx].optional,
++			td->elements_count);
++
++		if(ctx->left == 0	/* No more stuff is expected */
++		&& (
++			/* Explicit OPTIONAL specification reaches the end */
++			(edx + elements[edx].optional
++					== td->elements_count)
++			||
++			/* All extensions are optional */
++			(IN_EXTENSION_GROUP(specs, edx)
++				&& specs->ext_before > td->elements_count)
++		   )
++		) {
++			ASN_DEBUG("End of SEQUENCE %s", td->name);
++			/*
++			 * Found the legitimate end of the structure.
++			 */
++			PHASE_OUT(ctx);
++			RETURN(RC_OK);
++		}
++
++		/*
++		 * Fetch the T from TLV.
++		 */
++		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
++		ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
++			"(%s) is %s encoded in %d bytes, of frame %ld",
++			td->name, edx, elements[edx].name,
++			ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
++		switch(tag_len) {
++		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++			/* Fall through */
++		case -1: RETURN(RC_FAIL);
++		}
++
++		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
++			if(LEFT < 2) {
++				if(SIZE_VIOLATION)
++					RETURN(RC_FAIL);
++				else
++					RETURN(RC_WMORE);
++			} else if(((const uint8_t *)ptr)[1] == 0) {
++			ASN_DEBUG("edx = %d, opt = %d, ec=%d",
++				edx, elements[edx].optional,
++				td->elements_count);
++				if((edx + elements[edx].optional
++					== td->elements_count)
++				|| (IN_EXTENSION_GROUP(specs, edx)
++					&& specs->ext_before
++						> td->elements_count)) {
++					/*
++					 * Yeah, baby! Found the terminator
++					 * of the indefinite length structure.
++					 */
++					/*
++					 * Proceed to the canonical
++					 * finalization function.
++					 * No advancing is necessary.
++					 */
++					goto phase3;
++				}
++			}
++		}
++
++		/*
++		 * Find the next available type with this tag.
++		 */
++		use_bsearch = 0;
++		opt_edx_end = edx + elements[edx].optional + 1;
++		if(opt_edx_end > td->elements_count)
++			opt_edx_end = td->elements_count;	/* Cap */
++		else if(opt_edx_end - edx > 8) {
++			/* Limit the scope of linear search... */
++			opt_edx_end = edx + 8;
++			use_bsearch = 1;
++			/* ... and resort to bsearch() */
++		}
++		for(n = edx; n < opt_edx_end; n++) {
++			if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
++				/*
++				 * Found element corresponding to the tag
++				 * being looked at.
++				 * Reposition over the right element.
++				 */
++				edx = n;
++				ctx->step = 1 + 2 * edx;	/* Remember! */
++				goto microphase2;
++			} else if(elements[n].flags & ATF_OPEN_TYPE) {
++				/*
++				 * This is the ANY type, which may bear
++				 * any flag whatsoever.
++				 */
++				edx = n;
++				ctx->step = 1 + 2 * edx;	/* Remember! */
++				goto microphase2;
++			} else if(elements[n].tag == (ber_tlv_tag_t)-1) {
++				use_bsearch = 1;
++				break;
++			}
++		}
++		if(use_bsearch) {
++			/*
++			 * Resort to a binary search over
++			 * sorted array of tags.
++			 */
++			asn_TYPE_tag2member_t *t2m;
++			asn_TYPE_tag2member_t key;
++			key.el_tag = tlv_tag;
++			key.el_no = edx;
++			t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
++				specs->tag2el, specs->tag2el_count,
++				sizeof(specs->tag2el[0]), _t2e_cmp);
++			if(t2m) {
++				asn_TYPE_tag2member_t *best = 0;
++				asn_TYPE_tag2member_t *t2m_f, *t2m_l;
++				int edx_max = edx + elements[edx].optional;
++				/*
++				 * Rewind to the first element with that tag,
++				 * `cause bsearch() does not guarantee order.
++				 */
++				t2m_f = t2m + t2m->toff_first;
++				t2m_l = t2m + t2m->toff_last;
++				for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
++					if(t2m->el_no > edx_max) break;
++					if(t2m->el_no < edx) continue;
++					best = t2m;
++				}
++				if(best) {
++					edx = best->el_no;
++					ctx->step = 1 + 2 * edx;
++					goto microphase2;
++				}
++			}
++			n = opt_edx_end;
++		}
++		if(n == opt_edx_end) {
++			/*
++			 * If tag is unknown, it may be either
++			 * an unknown (thus, incorrect) tag,
++			 * or an extension (...),
++			 * or an end of the indefinite-length structure.
++			 */
++			if(!IN_EXTENSION_GROUP(specs, edx)) {
++				ASN_DEBUG("Unexpected tag %s (at %d)",
++					ber_tlv_tag_string(tlv_tag), edx);
++				ASN_DEBUG("Expected tag %s (%s)%s",
++					ber_tlv_tag_string(elements[edx].tag),
++					elements[edx].name,
++					elements[edx].optional
++						?" or alternatives":"");
++				RETURN(RC_FAIL);
++			} else {
++				/* Skip this tag */
++				ssize_t skip;
++
++				skip = ber_skip_length(opt_codec_ctx,
++					BER_TLV_CONSTRUCTED(ptr),
++					(const char *)ptr + tag_len,
++					LEFT - tag_len);
++				ASN_DEBUG("Skip length %d in %s",
++					(int)skip, td->name);
++				switch(skip) {
++				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++					/* Fall through */
++				case -1: RETURN(RC_FAIL);
++				}
++
++				ADVANCE(skip + tag_len);
++				ctx->step -= 2;
++				edx--;
++				continue;  /* Try again with the next tag */
++			}
++		}
++
++		/*
++		 * MICROPHASE 2: Invoke the member-specific decoder.
++		 */
++		ctx->step |= 1;		/* Confirm entering next microphase */
++	microphase2:
++		ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
++		
++		/*
++		 * Compute the position of the member inside a structure,
++		 * and also a type of containment (it may be contained
++		 * as pointer or using inline inclusion).
++		 */
++		if(elements[edx].flags & ATF_POINTER) {
++			/* Member is a pointer to another structure */
++			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
++		} else {
++			/*
++			 * A pointer to a pointer
++			 * holding the start of the structure
++			 */
++			memb_ptr = (char *)st + elements[edx].memb_offset;
++			memb_ptr2 = &memb_ptr;
++		}
++		/*
++		 * Invoke the member fetch routine according to member's type
++		 */
++		rval = elements[edx].type->ber_decoder(opt_codec_ctx,
++				elements[edx].type,
++				memb_ptr2, ptr, LEFT,
++				elements[edx].tag_mode);
++		ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
++			"in %d bytes rval.code %d, size=%d",
++			td->name, edx, elements[edx].type->name,
++			(int)LEFT, (int)rval.consumed, rval.code, (int)size);
++		switch(rval.code) {
++		case RC_OK:
++			break;
++		case RC_WMORE: /* More data expected */
++			if(!SIZE_VIOLATION) {
++				ADVANCE(rval.consumed);
++				RETURN(RC_WMORE);
++			}
++			ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
++				(long)ctx->left, (long)size);
++			/* Fall through */
++		case RC_FAIL: /* Fatal error */
++			RETURN(RC_FAIL);
++		} /* switch(rval) */
++		
++		ADVANCE(rval.consumed);
++	  }	/* for(all structure members) */
++
++	phase3:
++		ctx->phase = 3;
++	case 3:	/* 00 and other tags expected */
++	case 4:	/* only 00's expected */
++
++		ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
++			td->name, (long)ctx->left, (long)size);
++
++		/*
++		 * Skip everything until the end of the SEQUENCE.
++		 */
++		while(ctx->left) {
++			ssize_t tl, ll;
++
++			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
++			switch(tl) {
++			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++				/* Fall through */
++			case -1: RETURN(RC_FAIL);
++			}
++
++			/*
++			 * If expected <0><0>...
++			 */
++			if(ctx->left < 0
++				&& ((const uint8_t *)ptr)[0] == 0) {
++				if(LEFT < 2) {
++					if(SIZE_VIOLATION)
++						RETURN(RC_FAIL);
++					else
++						RETURN(RC_WMORE);
++				} else if(((const uint8_t *)ptr)[1] == 0) {
++					/*
++					 * Correctly finished with <0><0>.
++					 */
++					ADVANCE(2);
++					ctx->left++;
++					ctx->phase = 4;
++					continue;
++				}
++			}
++
++			if(!IN_EXTENSION_GROUP(specs, td->elements_count)
++			|| ctx->phase == 4) {
++				ASN_DEBUG("Unexpected continuation "
++					"of a non-extensible type "
++					"%s (SEQUENCE): %s",
++					td->name,
++					ber_tlv_tag_string(tlv_tag));
++				RETURN(RC_FAIL);
++			}
++
++			ll = ber_skip_length(opt_codec_ctx,
++				BER_TLV_CONSTRUCTED(ptr),
++				(const char *)ptr + tl, LEFT - tl);
++			switch(ll) {
++			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++				/* Fall through */
++			case -1: RETURN(RC_FAIL);
++			}
++
++			ADVANCE(tl + ll);
++		}
++
++		PHASE_OUT(ctx);
++	}
++	
++	RETURN(RC_OK);
++}
++
++
++/*
++ * The DER encoder of the SEQUENCE type.
++ */
++asn_enc_rval_t
++SEQUENCE_encode_der(asn_TYPE_descriptor_t *td,
++	void *sptr, int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	size_t computed_size = 0;
++	asn_enc_rval_t erval;
++	ssize_t ret;
++	int edx;
++
++	ASN_DEBUG("%s %s as SEQUENCE",
++		cb?"Encoding":"Estimating", td->name);
++
++	/*
++	 * Gather the length of the underlying members sequence.
++	 */
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		void *memb_ptr;
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++			if(!memb_ptr) {
++				if(elm->optional) continue;
++				/* Mandatory element is missing */
++				_ASN_ENCODE_FAILED;
++			}
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++		}
++		erval = elm->type->der_encoder(elm->type, memb_ptr,
++			elm->tag_mode, elm->tag,
++			0, 0);
++		if(erval.encoded == -1)
++			return erval;
++		computed_size += erval.encoded;
++		ASN_DEBUG("Member %d %s estimated %ld bytes",
++			edx, elm->name, (long)erval.encoded);
++	}
++
++	/*
++	 * Encode the TLV for the sequence itself.
++	 */
++	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
++	ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
++	if(ret == -1)
++		_ASN_ENCODE_FAILED;
++	erval.encoded = computed_size + ret;
++
++	if(!cb) _ASN_ENCODED_OK(erval);
++
++	/*
++	 * Encode all members.
++	 */
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		asn_enc_rval_t tmperval;
++		void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++			if(!memb_ptr) continue;
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++		}
++		tmperval = elm->type->der_encoder(elm->type, memb_ptr,
++			elm->tag_mode, elm->tag,
++			cb, app_key);
++		if(tmperval.encoded == -1)
++			return tmperval;
++		computed_size -= tmperval.encoded;
++		ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes",
++			edx, elm->name, td->name, (long)tmperval.encoded);
++	}
++
++	if(computed_size != 0)
++		/*
++		 * Encoded size is not equal to the computed size.
++		 */
++		_ASN_ENCODE_FAILED;
++
++	_ASN_ENCODED_OK(erval);
++}
++
++
++#undef	XER_ADVANCE
++#define	XER_ADVANCE(num_bytes)	do {			\
++		size_t num = num_bytes;			\
++		buf_ptr = ((const char *)buf_ptr) + num;\
++		size -= num;				\
++		consumed_myself += num;			\
++	} while(0)
++
++/*
++ * Decode the XER (XML) data.
++ */
++asn_dec_rval_t
++SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const char *opt_mname,
++		const void *buf_ptr, size_t size) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_SEQUENCE_specifics_t *specs
++		= (asn_SEQUENCE_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elements = td->elements;
++	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
++
++	/*
++	 * ... and parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	asn_dec_rval_t rval;		/* Return value from a decoder */
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++	int edx;			/* Element index */
++	int edx_end;
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) RETURN(RC_FAIL);
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++
++
++	/*
++	 * Phases of XER/XML processing:
++	 * Phase 0: Check that the opening tag matches our expectations.
++	 * Phase 1: Processing body and reacting on closing tag.
++	 * Phase 2: Processing inner type.
++	 * Phase 3: Skipping unknown extensions.
++	 * Phase 4: PHASED OUT
++	 */
++	for(edx = ctx->step; ctx->phase <= 3;) {
++		pxer_chunk_type_e ch_type;	/* XER chunk type */
++		ssize_t ch_size;		/* Chunk size */
++		xer_check_tag_e tcv;		/* Tag check value */
++		asn_TYPE_member_t *elm;
++		int n;
++
++		/*
++		 * Go inside the inner member of a sequence.
++		 */
++		if(ctx->phase == 2) {
++			asn_dec_rval_t tmprval;
++			void *memb_ptr;		/* Pointer to the member */
++			void **memb_ptr2;	/* Pointer to that pointer */
++
++			elm = &td->elements[edx];
++
++			if(elm->flags & ATF_POINTER) {
++				/* Member is a pointer to another structure */
++				memb_ptr2 = (void **)((char *)st
++					+ elm->memb_offset);
++			} else {
++				memb_ptr = (char *)st + elm->memb_offset;
++				memb_ptr2 = &memb_ptr;
++			}
++
++			/* Invoke the inner type decoder, m.b. multiple times */
++			tmprval = elm->type->xer_decoder(opt_codec_ctx,
++					elm->type, memb_ptr2, elm->name,
++					buf_ptr, size);
++			XER_ADVANCE(tmprval.consumed);
++			if(tmprval.code != RC_OK)
++				RETURN(tmprval.code);
++			ctx->phase = 1;	/* Back to body processing */
++			ctx->step = ++edx;
++			ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
++				ctx->phase, ctx->step);
++			/* Fall through */
++		}
++
++		/*
++		 * Get the next part of the XML stream.
++		 */
++		ch_size = xer_next_token(&ctx->context, buf_ptr, size,
++			&ch_type);
++		switch(ch_size) {
++		case -1: RETURN(RC_FAIL);
++		case 0:  RETURN(RC_WMORE);
++		default:
++			switch(ch_type) {
++			case PXER_COMMENT:	/* Got XML comment */
++			case PXER_TEXT:		/* Ignore free-standing text */
++				XER_ADVANCE(ch_size);	/* Skip silently */
++				continue;
++			case PXER_TAG:
++				break;	/* Check the rest down there */
++			}
++		}
++
++		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
++		ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
++			tcv, ctx->phase, xml_tag);
++
++		/* Skip the extensions section */
++		if(ctx->phase == 3) {
++			switch(xer_skip_unknown(tcv, &ctx->left)) {
++			case -1:
++				ctx->phase = 4;
++				RETURN(RC_FAIL);
++			case 0:
++				XER_ADVANCE(ch_size);
++				continue;
++			case 1:
++				XER_ADVANCE(ch_size);
++				ctx->phase = 1;
++				continue;
++			case 2:
++				ctx->phase = 1;
++				break;
++			}
++		}
++
++		switch(tcv) {
++		case XCT_CLOSING:
++			if(ctx->phase == 0) break;
++			ctx->phase = 0;
++			/* Fall through */
++		case XCT_BOTH:
++			if(ctx->phase == 0) {
++				if(edx >= td->elements_count
++				   ||
++				   /* Explicit OPTIONAL specs reaches the end */
++				    (edx + elements[edx].optional
++					== td->elements_count)
++				   ||
++				   /* All extensions are optional */
++				   (IN_EXTENSION_GROUP(specs, edx)
++					&& specs->ext_before
++						> td->elements_count)
++				) {
++					XER_ADVANCE(ch_size);
++					ctx->phase = 4;	/* Phase out */
++					RETURN(RC_OK);
++				} else {
++					ASN_DEBUG("Premature end of XER SEQUENCE");
++					RETURN(RC_FAIL);
++				}
++			}
++			/* Fall through */
++		case XCT_OPENING:
++			if(ctx->phase == 0) {
++				XER_ADVANCE(ch_size);
++				ctx->phase = 1;	/* Processing body phase */
++				continue;
++			}
++			/* Fall through */
++		case XCT_UNKNOWN_OP:
++		case XCT_UNKNOWN_BO:
++
++			ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d",
++				tcv, ctx->phase, edx);
++			if(ctx->phase != 1) {
++				break;	/* Really unexpected */
++			}
++
++			if(edx < td->elements_count) {
++				/*
++				 * Search which member corresponds to this tag.
++				 */
++				edx_end = edx + elements[edx].optional + 1;
++				if(edx_end > td->elements_count)
++					edx_end = td->elements_count;
++				for(n = edx; n < edx_end; n++) {
++					elm = &td->elements[n];
++					tcv = xer_check_tag(buf_ptr,
++						ch_size, elm->name);
++					switch(tcv) {
++					case XCT_BOTH:
++					case XCT_OPENING:
++						/*
++						 * Process this member.
++						 */
++						ctx->step = edx = n;
++						ctx->phase = 2;
++						break;
++					case XCT_UNKNOWN_OP:
++					case XCT_UNKNOWN_BO:
++						continue;
++					default:
++						n = edx_end;
++						break;	/* Phase out */
++					}
++					break;
++				}
++				if(n != edx_end)
++					continue;
++			} else {
++				ASN_DEBUG("Out of defined members: %d/%d",
++					edx, td->elements_count);
++			}
++
++			/* It is expected extension */
++			if(IN_EXTENSION_GROUP(specs,
++				edx + (edx < td->elements_count
++					? elements[edx].optional : 0))) {
++				ASN_DEBUG("Got anticipated extension at %d",
++					edx);
++				/*
++				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
++				 * By using a mask. Only record a pure
++				 * <opening> tags.
++				 */
++				if(tcv & XCT_CLOSING) {
++					/* Found </extension> without body */
++				} else {
++					ctx->left = 1;
++					ctx->phase = 3;	/* Skip ...'s */
++				}
++				XER_ADVANCE(ch_size);
++				continue;
++			}
++
++			/* Fall through */
++		default:
++			break;
++		}
++
++		ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
++			size>0?((const char *)buf_ptr)[0]:'.',
++			size>1?((const char *)buf_ptr)[1]:'.',
++			size>2?((const char *)buf_ptr)[2]:'.',
++			size>3?((const char *)buf_ptr)[3]:'.',
++			size>4?((const char *)buf_ptr)[4]:'.',
++			size>5?((const char *)buf_ptr)[5]:'.');
++		break;
++	}
++
++	ctx->phase = 4;	/* "Phase out" on hard failure */
++	RETURN(RC_FAIL);
++}
++
++asn_enc_rval_t
++SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er;
++	int xcan = (flags & XER_F_CANONICAL);
++	int edx;
++
++	if(!sptr)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = 0;
++
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_enc_rval_t tmper;
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		void *memb_ptr;
++		const char *mname = elm->name;
++		unsigned int mlen = strlen(mname);
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++			if(!memb_ptr) {
++				if(elm->optional)
++					continue;
++				/* Mandatory element is missing */
++				_ASN_ENCODE_FAILED;
++			}
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++		}
++
++		if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
++		_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
++
++		/* Print the member itself */
++		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
++			ilevel + 1, flags, cb, app_key);
++		if(tmper.encoded == -1) return tmper;
++
++		_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
++		er.encoded += 5 + (2 * mlen) + tmper.encoded;
++	}
++
++	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++int
++SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	int edx;
++	int ret;
++
++	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++
++	/* Dump preamble */
++	if(cb(td->name, strlen(td->name), app_key) < 0
++	|| cb(" ::= {", 6, app_key) < 0)
++		return -1;
++
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		const void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
++			if(!memb_ptr) {
++				if(elm->optional) continue;
++				/* Print <absent> line */
++				/* Fall through */
++			}
++		} else {
++			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
++		}
++
++		/* Indentation */
++		_i_INDENT(1);
++
++		/* Print the member's name and stuff */
++		if(cb(elm->name, strlen(elm->name), app_key) < 0
++		|| cb(": ", 2, app_key) < 0)
++			return -1;
++
++		/* Print the member itself */
++		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
++			cb, app_key);
++		if(ret) return ret;
++	}
++
++	ilevel--;
++	_i_INDENT(1);
++
++	return (cb("}", 1, app_key) < 0) ? -1 : 0;
++}
++
++void
++SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
++	int edx;
++
++	if(!td || !sptr)
++		return;
++
++	ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
++
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		void *memb_ptr;
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
++			if(memb_ptr)
++				ASN_STRUCT_FREE(*elm->type, memb_ptr);
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
++		}
++	}
++
++	if(!contents_only) {
++		FREEMEM(sptr);
++	}
++}
++
++int
++SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
++		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
++	int edx;
++
++	if(!sptr) {
++		_ASN_CTFAIL(app_key, td,
++			"%s: value not given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++
++	/*
++	 * Iterate over structure members and check their validity.
++	 */
++	for(edx = 0; edx < td->elements_count; edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		const void *memb_ptr;
++
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
++			if(!memb_ptr) {
++				if(elm->optional)
++					continue;
++				_ASN_CTFAIL(app_key, td,
++				"%s: mandatory element %s absent (%s:%d)",
++				td->name, elm->name, __FILE__, __LINE__);
++				return -1;
++			}
++		} else {
++			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
++		}
++
++		if(elm->memb_constraints) {
++			int ret = elm->memb_constraints(elm->type, memb_ptr,
++				ctfailcb, app_key);
++			if(ret) return ret;
++		} else {
++			int ret = elm->type->check_constraints(elm->type,
++				memb_ptr, ctfailcb, app_key);
++			if(ret) return ret;
++			/*
++			 * Cannot inherit it earlier:
++			 * need to make sure we get the updated version.
++			 */
++			elm->memb_constraints = elm->type->check_constraints;
++		}
++	}
++
++	return 0;
++}
++
++asn_dec_rval_t
++SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
++	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
++	void *st = *sptr;	/* Target structure. */
++	int extpresent = 0;	/* Extension additions are present */
++	uint8_t *opres;		/* Presence of optional root members */
++	asn_per_data_t opmd;
++	asn_dec_rval_t rv;
++	int edx;
++
++	(void)constraints;
++
++	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
++		_ASN_DECODE_FAILED;
++
++	if(!st) {
++		st = *sptr = CALLOC(1, specs->struct_size);
++		if(!st) _ASN_DECODE_FAILED;
++	}
++
++	ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
++
++	/* Handle extensions */
++	if(specs->ext_before >= 0) {
++		extpresent = per_get_few_bits(pd, 1);
++		if(extpresent < 0) _ASN_DECODE_STARVED;
++	}
++
++	/* Prepare a place and read-in the presence bitmap */
++	if(specs->roms_count) {
++		opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
++		if(!opres) _ASN_DECODE_FAILED;
++		/* Get the presence map */
++		if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
++			FREEMEM(opres);
++			_ASN_DECODE_STARVED;
++		}
++		opmd.buffer = opres;
++		opmd.nboff = 0;
++		opmd.nbits = specs->roms_count;
++		ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
++			td->name, specs->roms_count, *opres);
++	} else {
++		opres = 0;
++		memset(&opmd, 0, sizeof opmd);
++	}
++
++	/*
++	 * Get the sequence ROOT elements.
++	 */
++	for(edx = 0; edx < ((specs->ext_before < 0)
++			? td->elements_count : specs->ext_before + 1); edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		void *memb_ptr;		/* Pointer to the member */
++		void **memb_ptr2;	/* Pointer to that pointer */
++
++		/* Fetch the pointer to this member */
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
++		} else {
++			memb_ptr = (char *)st + elm->memb_offset;
++			memb_ptr2 = &memb_ptr;
++		}
++
++		/* Deal with optionality */
++		if(elm->optional) {
++			int present = per_get_few_bits(&opmd, 1);
++			ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
++				td->name, elm->name, present,
++				(int)opmd.nboff, (int)opmd.nbits);
++			if(present == 0) {
++				/* This element is not present */
++				if(elm->default_value) {
++					/* Fill-in DEFAULT */
++					if(elm->default_value(1, memb_ptr2)) {
++						FREEMEM(opres);
++						_ASN_DECODE_FAILED;
++					}
++				}
++				/* The member is just not present */
++				continue;
++			}
++			/* Fall through */
++		}
++
++		/* Fetch the member from the stream */
++		ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
++		rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
++			elm->per_constraints, memb_ptr2, pd);
++		if(rv.code != RC_OK) {
++			ASN_DEBUG("Failed decode %s in %s",
++				elm->name, td->name);
++			FREEMEM(opres);
++			return rv;
++		}
++	}
++
++	/*
++	 * Deal with extensions.
++	 */
++	if(extpresent) {
++		ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name);
++		_ASN_DECODE_FAILED;
++	} else {
++		for(edx = specs->roms_count; edx < specs->roms_count
++				+ specs->aoms_count; edx++) {
++			asn_TYPE_member_t *elm = &td->elements[edx];
++			void *memb_ptr;		/* Pointer to the member */
++			void **memb_ptr2;	/* Pointer to that pointer */
++
++			if(!elm->default_value) continue;
++
++			/* Fetch the pointer to this member */
++			if(elm->flags & ATF_POINTER) {
++				memb_ptr2 = (void **)((char *)st
++						+ elm->memb_offset);
++			} else {
++				memb_ptr = (char *)st + elm->memb_offset;
++				memb_ptr2 = &memb_ptr;
++			}
++
++			/* Set default value */
++			if(elm->default_value(1, memb_ptr2)) {
++				FREEMEM(opres);
++				_ASN_DECODE_FAILED;
++			}
++		}
++	}
++
++	rv.consumed = 0;
++	rv.code = RC_OK;
++	FREEMEM(opres);
++	return rv;
++}
++
++asn_enc_rval_t
++SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_SEQUENCE_specifics_t *specs
++		= (asn_SEQUENCE_specifics_t *)td->specifics;
++	asn_enc_rval_t er;
++	int edx;
++	int i;
++
++	(void)constraints;
++
++	if(!sptr)
++		_ASN_ENCODE_FAILED;
++
++	er.encoded = 0;
++
++	ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
++	if(specs->ext_before >= 0)
++		_ASN_ENCODE_FAILED;	/* We don't encode extensions yet */
++
++	/* Encode a presence bitmap */
++	for(i = 0; i < specs->roms_count; i++) {
++		asn_TYPE_member_t *elm;
++		void *memb_ptr;		/* Pointer to the member */
++		void **memb_ptr2;	/* Pointer to that pointer */
++		int present;
++
++		edx = specs->oms[i];
++		elm = &td->elements[edx];
++
++		/* Fetch the pointer to this member */
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
++			present = (*memb_ptr2 != 0);
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++			memb_ptr2 = &memb_ptr;
++			present = 1;
++		}
++
++		/* Eliminate default values */
++		if(present && elm->default_value
++		&& elm->default_value(0, memb_ptr2) == 1)
++			present = 0;
++
++		ASN_DEBUG("Element %s %s %s->%s is %s",
++			elm->flags & ATF_POINTER ? "ptr" : "inline",
++			elm->default_value ? "def" : "wtv",
++			td->name, elm->name, present ? "present" : "absent");
++		if(per_put_few_bits(po, present, 1))
++			_ASN_ENCODE_FAILED;
++	}
++
++	/*
++	 * Get the sequence ROOT elements.
++	 */
++	for(edx = 0; edx < ((specs->ext_before < 0)
++			? td->elements_count : specs->ext_before + 1); edx++) {
++		asn_TYPE_member_t *elm = &td->elements[edx];
++		void *memb_ptr;		/* Pointer to the member */
++		void **memb_ptr2;	/* Pointer to that pointer */
++
++		/* Fetch the pointer to this member */
++		if(elm->flags & ATF_POINTER) {
++			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
++			if(!*memb_ptr2) {
++				ASN_DEBUG("Element %s %d not present",
++					elm->name, edx);
++				if(elm->optional)
++					continue;
++				/* Mandatory element is missing */
++				_ASN_ENCODE_FAILED;
++			}
++		} else {
++			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
++			memb_ptr2 = &memb_ptr;
++		}
++
++		/* Eliminate default values */
++		if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
++			continue;
++
++		er = elm->type->uper_encoder(elm->type, elm->per_constraints,
++			*memb_ptr2, po);
++		if(er.encoded == -1)
++			return er;
++	}
++
++	_ASN_ENCODED_OK(er);
++}
++
+diff --git a/asn1/asn1c/constr_SEQUENCE.h b/asn1/asn1c/constr_SEQUENCE.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..5f589d5c1c0d1ae1d6e970742fc6467153bea79c
+--- /dev/null
++++ b/asn1/asn1c/constr_SEQUENCE.h
+@@ -0,0 +1,60 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_CONSTR_SEQUENCE_H_
++#define	_CONSTR_SEQUENCE_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct asn_SEQUENCE_specifics_s {
++	/*
++	 * Target structure description.
++	 */
++	int struct_size;	/* Size of the target structure. */
++	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
++
++	/*
++	 * Tags to members mapping table (sorted).
++	 */
++	asn_TYPE_tag2member_t *tag2el;
++	int tag2el_count;
++
++	/*
++	 * Optional members of the extensions root (roms) or additions (aoms).
++	 * Meaningful for PER.
++	 */
++	int *oms;		/* Optional MemberS */
++	int  roms_count;	/* Root optional members count */
++	int  aoms_count;	/* Additions optional members count */
++
++	/*
++	 * Description of an extensions group.
++	 */
++	int ext_after;		/* Extensions start after this member */
++	int ext_before;		/* Extensions stop before this member */
++} asn_SEQUENCE_specifics_t;
++
++
++/*
++ * A set specialized functions dealing with the SEQUENCE type.
++ */
++asn_struct_free_f SEQUENCE_free;
++asn_struct_print_f SEQUENCE_print;
++asn_constr_check_f SEQUENCE_constraint;
++ber_type_decoder_f SEQUENCE_decode_ber;
++der_type_encoder_f SEQUENCE_encode_der;
++xer_type_decoder_f SEQUENCE_decode_xer;
++xer_type_encoder_f SEQUENCE_encode_xer;
++per_type_decoder_f SEQUENCE_decode_uper;
++per_type_encoder_f SEQUENCE_encode_uper;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _CONSTR_SEQUENCE_H_ */
+diff --git a/asn1/asn1c/constr_SEQUENCE_OF.c b/asn1/asn1c/constr_SEQUENCE_OF.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..aa101176d649ee2b26e3616e88197d9488991bb2
+--- /dev/null
++++ b/asn1/asn1c/constr_SEQUENCE_OF.c
+@@ -0,0 +1,208 @@
++/*-
++ * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <constr_SEQUENCE_OF.h>
++#include <asn_SEQUENCE_OF.h>
++
++/*
++ * The DER encoder of the SEQUENCE OF type.
++ */
++asn_enc_rval_t
++SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_TYPE_member_t *elm = td->elements;
++	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr);
++	size_t computed_size = 0;
++	ssize_t encoding_size = 0;
++	asn_enc_rval_t erval;
++	int edx;
++
++	ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);
++
++	/*
++	 * Gather the length of the underlying members sequence.
++	 */
++	for(edx = 0; edx < list->count; edx++) {
++		void *memb_ptr = list->array[edx];
++		if(!memb_ptr) continue;
++		erval = elm->type->der_encoder(elm->type, memb_ptr,
++			0, elm->tag,
++			0, 0);
++		if(erval.encoded == -1)
++			return erval;
++		computed_size += erval.encoded;
++	}
++
++	/*
++	 * Encode the TLV for the sequence itself.
++	 */
++	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
++		cb, app_key);
++	if(encoding_size == -1) {
++		erval.encoded = -1;
++		erval.failed_type = td;
++		erval.structure_ptr = ptr;
++		return erval;
++	}
++
++	computed_size += encoding_size;
++	if(!cb) {
++		erval.encoded = computed_size;
++		_ASN_ENCODED_OK(erval);
++	}
++
++	ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);
++
++	/*
++	 * Encode all members.
++	 */
++	for(edx = 0; edx < list->count; edx++) {
++		void *memb_ptr = list->array[edx];
++		if(!memb_ptr) continue;
++		erval = elm->type->der_encoder(elm->type, memb_ptr,
++			0, elm->tag,
++			cb, app_key);
++		if(erval.encoded == -1)
++			return erval;
++		encoding_size += erval.encoded;
++	}
++
++	if(computed_size != (size_t)encoding_size) {
++		/*
++		 * Encoded size is not equal to the computed size.
++		 */
++		erval.encoded = -1;
++		erval.failed_type = td;
++		erval.structure_ptr = ptr;
++	} else {
++		erval.encoded = computed_size;
++		erval.structure_ptr = 0;
++		erval.failed_type = 0;
++	}
++
++	return erval;
++}
++
++asn_enc_rval_t
++SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er;
++        asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm = td->elements;
++	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr);
++	const char *mname = specs->as_XMLValueList
++		? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
++	unsigned int mlen = mname ? strlen(mname) : 0;
++	int xcan = (flags & XER_F_CANONICAL);
++	int i;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++
++	er.encoded = 0;
++
++	for(i = 0; i < list->count; i++) {
++		asn_enc_rval_t tmper;
++		void *memb_ptr = list->array[i];
++		if(!memb_ptr) continue;
++
++		if(mname) {
++			if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
++			_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
++		}
++
++		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
++				ilevel + 1, flags, cb, app_key);
++		if(tmper.encoded == -1) return tmper;
++                if(tmper.encoded == 0 && specs->as_XMLValueList) {
++                        const char *name = elm->type->xml_tag;
++			size_t len = strlen(name);
++			if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel + 1);
++			_ASN_CALLBACK3("<", 1, name, len, "/>", 2);
++                }
++
++		if(mname) {
++			_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
++			er.encoded += 5;
++		}
++
++		er.encoded += (2 * mlen) + tmper.encoded;
++	}
++
++	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++asn_enc_rval_t
++SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
++	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
++	asn_anonymous_sequence_ *list;
++	asn_per_constraint_t *ct;
++	asn_enc_rval_t er;
++	asn_TYPE_member_t *elm = td->elements;
++	int seq;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++	list = _A_SEQUENCE_FROM_VOID(sptr);
++
++	er.encoded = 0;
++
++	ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
++
++	if(constraints) ct = &constraints->size;
++	else if(td->per_constraints) ct = &td->per_constraints->size;
++	else ct = 0;
++
++	/* If extensible constraint, check if size is in root */
++	if(ct) {
++		int not_in_root = (list->count < ct->lower_bound
++				|| list->count > ct->upper_bound);
++		ASN_DEBUG("lb %ld ub %ld %s",
++			ct->lower_bound, ct->upper_bound,
++			ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
++		if(ct->flags & APC_EXTENSIBLE) {
++			/* Declare whether size is in extension root */
++			if(per_put_few_bits(po, not_in_root, 1))
++				_ASN_ENCODE_FAILED;
++			if(not_in_root) ct = 0;
++		} else if(not_in_root && ct->effective_bits >= 0)
++			_ASN_ENCODE_FAILED;
++	}
++
++	if(ct && ct->effective_bits >= 0) {
++		/* X.691, #19.5: No length determinant */
++		if(per_put_few_bits(po, list->count - ct->lower_bound,
++				ct->effective_bits))
++			_ASN_ENCODE_FAILED;
++	}
++
++	for(seq = -1; seq < list->count;) {
++		ssize_t mayEncode;
++		if(seq < 0) seq = 0;
++		if(ct && ct->effective_bits >= 0) {
++			mayEncode = list->count;
++		} else {
++			mayEncode = uper_put_length(po, list->count - seq);
++			if(mayEncode < 0) _ASN_ENCODE_FAILED;
++		}
++
++		while(mayEncode--) {
++			void *memb_ptr = list->array[seq++];
++			if(!memb_ptr) _ASN_ENCODE_FAILED;
++			er = elm->type->uper_encoder(elm->type,
++				elm->per_constraints, memb_ptr, po);
++			if(er.encoded == -1)
++				_ASN_ENCODE_FAILED;
++		}
++	}
++
++	_ASN_ENCODED_OK(er);
++}
++
+diff --git a/asn1/asn1c/constr_SEQUENCE_OF.h b/asn1/asn1c/constr_SEQUENCE_OF.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..e2272f326ba1b961f3f0539c160481f9348b49da
+--- /dev/null
++++ b/asn1/asn1c/constr_SEQUENCE_OF.h
+@@ -0,0 +1,33 @@
++/*-
++ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_CONSTR_SEQUENCE_OF_H_
++#define	_CONSTR_SEQUENCE_OF_H_
++
++#include <asn_application.h>
++#include <constr_SET_OF.h>		/* Implemented using SET OF */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * A set specialized functions dealing with the SEQUENCE OF type.
++ * Generally implemented using SET OF.
++ */
++#define	SEQUENCE_OF_free	SET_OF_free
++#define	SEQUENCE_OF_print	SET_OF_print
++#define	SEQUENCE_OF_constraint	SET_OF_constraint
++#define	SEQUENCE_OF_decode_ber	SET_OF_decode_ber
++#define	SEQUENCE_OF_decode_xer	SET_OF_decode_xer
++#define	SEQUENCE_OF_decode_uper	SET_OF_decode_uper
++der_type_encoder_f SEQUENCE_OF_encode_der;
++xer_type_encoder_f SEQUENCE_OF_encode_xer;
++per_type_encoder_f SEQUENCE_OF_encode_uper;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _CONSTR_SET_OF_H_ */
+diff --git a/asn1/asn1c/constr_SET_OF.c b/asn1/asn1c/constr_SET_OF.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..09f27db53dada6869accd8dbb3aba0f56b49e00b
+--- /dev/null
++++ b/asn1/asn1c/constr_SET_OF.c
+@@ -0,0 +1,942 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <constr_SET_OF.h>
++#include <asn_SET_OF.h>
++
++/*
++ * Number of bytes left for this structure.
++ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
++ * (size) contains the number of bytes in the buffer passed.
++ */
++#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
++
++/*
++ * If the subprocessor function returns with an indication that it wants
++ * more data, it may well be a fatal decoding problem, because the
++ * size is constrained by the <TLV>'s L, even if the buffer size allows
++ * reading more data.
++ * For example, consider the buffer containing the following TLVs:
++ * <T:5><L:1><V> <T:6>...
++ * The TLV length clearly indicates that one byte is expected in V, but
++ * if the V processor returns with "want more data" even if the buffer
++ * contains way more data than the V processor have seen.
++ */
++#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
++
++/*
++ * This macro "eats" the part of the buffer which is definitely "consumed",
++ * i.e. was correctly converted into local representation or rightfully skipped.
++ */
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {		\
++		size_t num = num_bytes;		\
++		ptr = ((const char *)ptr) + num;\
++		size -= num;			\
++		if(ctx->left >= 0)		\
++			ctx->left -= num;	\
++		consumed_myself += num;		\
++	} while(0)
++
++/*
++ * Switch to the next phase of parsing.
++ */
++#undef	NEXT_PHASE
++#undef	PHASE_OUT
++#define	NEXT_PHASE(ctx)	do {			\
++		ctx->phase++;			\
++		ctx->step = 0;			\
++	} while(0)
++#define	PHASE_OUT(ctx)	do { ctx->phase = 10; } while(0)
++
++/*
++ * Return a standardized complex structure.
++ */
++#undef	RETURN
++#define	RETURN(_code)	do {			\
++		rval.code = _code;		\
++		rval.consumed = consumed_myself;\
++		return rval;			\
++	} while(0)
++
++/*
++ * The decoder of the SET OF type.
++ */
++asn_dec_rval_t
++SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm = td->elements;	/* Single one */
++
++	/*
++	 * Parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	ber_tlv_tag_t tlv_tag;	/* T from TLV */
++	asn_dec_rval_t rval;	/* Return code from subparsers */
++
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++
++	ASN_DEBUG("Decoding %s as SET OF", td->name);
++	
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) {
++			RETURN(RC_FAIL);
++		}
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++	
++	/*
++	 * Start to parse where left previously
++	 */
++	switch(ctx->phase) {
++	case 0:
++		/*
++		 * PHASE 0.
++		 * Check that the set of tags associated with given structure
++		 * perfectly fits our expectations.
++		 */
++
++		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
++			tag_mode, 1, &ctx->left, 0);
++		if(rval.code != RC_OK) {
++			ASN_DEBUG("%s tagging check failed: %d",
++				td->name, rval.code);
++			return rval;
++		}
++
++		if(ctx->left >= 0)
++			ctx->left += rval.consumed; /* ?Substracted below! */
++		ADVANCE(rval.consumed);
++
++		ASN_DEBUG("Structure consumes %ld bytes, "
++			"buffer %ld", (long)ctx->left, (long)size);
++
++		NEXT_PHASE(ctx);
++		/* Fall through */
++	case 1:
++		/*
++		 * PHASE 1.
++		 * From the place where we've left it previously,
++		 * try to decode the next item.
++		 */
++	  for(;; ctx->step = 0) {
++		ssize_t tag_len;	/* Length of TLV's T */
++
++		if(ctx->step & 1)
++			goto microphase2;
++
++		/*
++		 * MICROPHASE 1: Synchronize decoding.
++		 */
++
++		if(ctx->left == 0) {
++			ASN_DEBUG("End of SET OF %s", td->name);
++			/*
++			 * No more things to decode.
++			 * Exit out of here.
++			 */
++			PHASE_OUT(ctx);
++			RETURN(RC_OK);
++		}
++
++		/*
++		 * Fetch the T from TLV.
++		 */
++		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
++		switch(tag_len) {
++		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
++			/* Fall through */
++		case -1: RETURN(RC_FAIL);
++		}
++
++		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
++			if(LEFT < 2) {
++				if(SIZE_VIOLATION)
++					RETURN(RC_FAIL);
++				else
++					RETURN(RC_WMORE);
++			} else if(((const uint8_t *)ptr)[1] == 0) {
++				/*
++				 * Found the terminator of the
++				 * indefinite length structure.
++				 */
++				break;
++			}
++		}
++
++		/* Outmost tag may be unknown and cannot be fetched/compared */
++		if(elm->tag != (ber_tlv_tag_t)-1) {
++		    if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
++			/*
++			 * The new list member of expected type has arrived.
++			 */
++		    } else {
++			ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
++				ber_tlv_tag_string(tlv_tag), td->name);
++			ASN_DEBUG("%s SET OF has tag %s",
++				td->name, ber_tlv_tag_string(elm->tag));
++			RETURN(RC_FAIL);
++		    }
++		}
++
++		/*
++		 * MICROPHASE 2: Invoke the member-specific decoder.
++		 */
++		ctx->step |= 1;		/* Confirm entering next microphase */
++	microphase2:
++		
++		/*
++		 * Invoke the member fetch routine according to member's type
++		 */
++		rval = elm->type->ber_decoder(opt_codec_ctx,
++				elm->type, &ctx->ptr, ptr, LEFT, 0);
++		ASN_DEBUG("In %s SET OF %s code %d consumed %d",
++			td->name, elm->type->name,
++			rval.code, (int)rval.consumed);
++		switch(rval.code) {
++		case RC_OK:
++			{
++				asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
++				if(ASN_SET_ADD(list, ctx->ptr) != 0)
++					RETURN(RC_FAIL);
++				else
++					ctx->ptr = 0;
++			}
++			break;
++		case RC_WMORE: /* More data expected */
++			if(!SIZE_VIOLATION) {
++				ADVANCE(rval.consumed);
++				RETURN(RC_WMORE);
++			}
++			/* Fall through */
++		case RC_FAIL: /* Fatal error */
++			RETURN(RC_FAIL);
++		} /* switch(rval) */
++		
++		ADVANCE(rval.consumed);
++	  }	/* for(all list members) */
++
++		NEXT_PHASE(ctx);
++	case 2:
++		/*
++		 * Read in all "end of content" TLVs.
++		 */
++		while(ctx->left < 0) {
++			if(LEFT < 2) {
++				if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
++					/* Unexpected tag */
++					RETURN(RC_FAIL);
++				} else {
++					RETURN(RC_WMORE);
++				}
++			}
++			if(((const char *)ptr)[0] == 0
++			&& ((const char *)ptr)[1] == 0) {
++				ADVANCE(2);
++				ctx->left++;
++			} else {
++				RETURN(RC_FAIL);
++			}
++		}
++
++		PHASE_OUT(ctx);
++	}
++	
++	RETURN(RC_OK);
++}
++
++/*
++ * Internally visible buffer holding a single encoded element.
++ */
++struct _el_buffer {
++	uint8_t *buf;
++	size_t length;
++	size_t size;
++};
++/* Append bytes to the above structure */
++static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
++	struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
++
++	if(el_buf->length + size > el_buf->size)
++		return -1;
++
++	memcpy(el_buf->buf + el_buf->length, buffer, size);
++
++	el_buf->length += size;
++	return 0;
++}
++static int _el_buf_cmp(const void *ap, const void *bp) {
++	const struct _el_buffer *a = (const struct _el_buffer *)ap;
++	const struct _el_buffer *b = (const struct _el_buffer *)bp;
++	int ret;
++	size_t common_len;
++
++	if(a->length < b->length)
++		common_len = a->length;
++	else
++		common_len = b->length;
++
++	ret = memcmp(a->buf, b->buf, common_len);
++	if(ret == 0) {
++		if(a->length < b->length)
++			ret = -1;
++		else if(a->length > b->length)
++			ret = 1;
++	}
++
++	return ret;
++}
++
++/*
++ * The DER encoder of the SET OF type.
++ */
++asn_enc_rval_t
++SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
++	int tag_mode, ber_tlv_tag_t tag,
++	asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_TYPE_member_t *elm = td->elements;
++	asn_TYPE_descriptor_t *elm_type = elm->type;
++	der_type_encoder_f *der_encoder = elm_type->der_encoder;
++	asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
++	size_t computed_size = 0;
++	ssize_t encoding_size = 0;
++	struct _el_buffer *encoded_els;
++	ssize_t eels_count = 0;
++	size_t max_encoded_len = 1;
++	asn_enc_rval_t erval;
++	int ret;
++	int edx;
++
++	ASN_DEBUG("Estimating size for SET OF %s", td->name);
++
++	/*
++	 * Gather the length of the underlying members sequence.
++	 */
++	for(edx = 0; edx < list->count; edx++) {
++		void *memb_ptr = list->array[edx];
++		if(!memb_ptr) continue;
++		erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0);
++		if(erval.encoded == -1)
++			return erval;
++		computed_size += erval.encoded;
++
++		/* Compute maximum encoding's size */
++		if(max_encoded_len < (size_t)erval.encoded)
++			max_encoded_len = erval.encoded;
++	}
++
++	/*
++	 * Encode the TLV for the sequence itself.
++	 */
++	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
++		cb, app_key);
++	if(encoding_size == -1) {
++		erval.encoded = -1;
++		erval.failed_type = td;
++		erval.structure_ptr = ptr;
++		return erval;
++	}
++	computed_size += encoding_size;
++
++	if(!cb || list->count == 0) {
++		erval.encoded = computed_size;
++		_ASN_ENCODED_OK(erval);
++	}
++
++	/*
++	 * DER mandates dynamic sorting of the SET OF elements
++	 * according to their encodings. Build an array of the
++	 * encoded elements.
++	 */
++	encoded_els = (struct _el_buffer *)MALLOC(
++				list->count * sizeof(encoded_els[0]));
++	if(encoded_els == NULL) {
++		erval.encoded = -1;
++		erval.failed_type = td;
++		erval.structure_ptr = ptr;
++		return erval;
++	}
++
++	ASN_DEBUG("Encoding members of %s SET OF", td->name);
++
++	/*
++	 * Encode all members.
++	 */
++	for(edx = 0; edx < list->count; edx++) {
++		void *memb_ptr = list->array[edx];
++		struct _el_buffer *encoded_el = &encoded_els[eels_count];
++
++		if(!memb_ptr) continue;
++
++		/*
++		 * Prepare space for encoding.
++		 */
++		encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len);
++		if(encoded_el->buf) {
++			encoded_el->length = 0;
++			encoded_el->size = max_encoded_len;
++		} else {
++			for(edx--; edx >= 0; edx--)
++				FREEMEM(encoded_els[edx].buf);
++			FREEMEM(encoded_els);
++			erval.encoded = -1;
++			erval.failed_type = td;
++			erval.structure_ptr = ptr;
++			return erval;
++		}
++
++		/*
++		 * Encode the member into the prepared space.
++		 */
++		erval = der_encoder(elm_type, memb_ptr, 0, elm->tag,
++			_el_addbytes, encoded_el);
++		if(erval.encoded == -1) {
++			for(; edx >= 0; edx--)
++				FREEMEM(encoded_els[edx].buf);
++			FREEMEM(encoded_els);
++			return erval;
++		}
++		encoding_size += erval.encoded;
++		eels_count++;
++	}
++
++	/*
++	 * Sort the encoded elements according to their encoding.
++	 */
++	qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp);
++
++	/*
++	 * Report encoded elements to the application.
++	 * Dispose of temporary sorted members table.
++	 */
++	ret = 0;
++	for(edx = 0; edx < eels_count; edx++) {
++		struct _el_buffer *encoded_el = &encoded_els[edx];
++		/* Report encoded chunks to the application */
++		if(ret == 0
++		&& cb(encoded_el->buf, encoded_el->length, app_key) < 0)
++			ret = -1;
++		FREEMEM(encoded_el->buf);
++	}
++	FREEMEM(encoded_els);
++
++	if(ret || computed_size != (size_t)encoding_size) {
++		/*
++		 * Standard callback failed, or
++		 * encoded size is not equal to the computed size.
++		 */
++		erval.encoded = -1;
++		erval.failed_type = td;
++		erval.structure_ptr = ptr;
++	} else {
++		erval.encoded = computed_size;
++	}
++
++	_ASN_ENCODED_OK(erval);
++}
++
++#undef	XER_ADVANCE
++#define	XER_ADVANCE(num_bytes)	do {			\
++		size_t num = num_bytes;			\
++		buf_ptr = ((const char *)buf_ptr) + num;\
++		size -= num;				\
++		consumed_myself += num;			\
++	} while(0)
++
++/*
++ * Decode the XER (XML) data.
++ */
++asn_dec_rval_t
++SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++	void **struct_ptr, const char *opt_mname,
++		const void *buf_ptr, size_t size) {
++	/*
++	 * Bring closer parts of structure description.
++	 */
++	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
++	asn_TYPE_member_t *element = td->elements;
++	const char *elm_tag;
++	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
++
++	/*
++	 * ... and parts of the structure being constructed.
++	 */
++	void *st = *struct_ptr;	/* Target structure. */
++	asn_struct_ctx_t *ctx;	/* Decoder context */
++
++	asn_dec_rval_t rval;		/* Return value from a decoder */
++	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(st == 0) {
++		st = *struct_ptr = CALLOC(1, specs->struct_size);
++		if(st == 0) RETURN(RC_FAIL);
++	}
++
++	/* Which tag is expected for the downstream */
++	if(specs->as_XMLValueList) {
++		elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
++	} else {
++		elm_tag = (*element->name)
++				? element->name : element->type->xml_tag;
++	}
++
++	/*
++	 * Restore parsing context.
++	 */
++	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
++
++	/*
++	 * Phases of XER/XML processing:
++	 * Phase 0: Check that the opening tag matches our expectations.
++	 * Phase 1: Processing body and reacting on closing tag.
++	 * Phase 2: Processing inner type.
++	 */
++	for(; ctx->phase <= 2;) {
++		pxer_chunk_type_e ch_type;	/* XER chunk type */
++		ssize_t ch_size;		/* Chunk size */
++		xer_check_tag_e tcv;		/* Tag check value */
++
++		/*
++		 * Go inside the inner member of a set.
++		 */
++		if(ctx->phase == 2) {
++			asn_dec_rval_t tmprval;
++
++			/* Invoke the inner type decoder, m.b. multiple times */
++			ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
++			tmprval = element->type->xer_decoder(opt_codec_ctx,
++					element->type, &ctx->ptr, elm_tag,
++					buf_ptr, size);
++			if(tmprval.code == RC_OK) {
++				asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
++				if(ASN_SET_ADD(list, ctx->ptr) != 0)
++					RETURN(RC_FAIL);
++				ctx->ptr = 0;
++				XER_ADVANCE(tmprval.consumed);
++			} else {
++				XER_ADVANCE(tmprval.consumed);
++				RETURN(tmprval.code);
++			}
++			ctx->phase = 1;	/* Back to body processing */
++			ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
++			/* Fall through */
++		}
++
++		/*
++		 * Get the next part of the XML stream.
++		 */
++		ch_size = xer_next_token(&ctx->context,
++			buf_ptr, size, &ch_type);
++		switch(ch_size) {
++		case -1: RETURN(RC_FAIL);
++		case 0:  RETURN(RC_WMORE);
++		default:
++			switch(ch_type) {
++			case PXER_COMMENT:	/* Got XML comment */
++			case PXER_TEXT:		/* Ignore free-standing text */
++				XER_ADVANCE(ch_size);	/* Skip silently */
++				continue;
++			case PXER_TAG:
++				break;	/* Check the rest down there */
++			}
++		}
++
++		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
++		ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
++			tcv, ctx->phase, xml_tag);
++		switch(tcv) {
++		case XCT_CLOSING:
++			if(ctx->phase == 0) break;
++			ctx->phase = 0;
++			/* Fall through */
++		case XCT_BOTH:
++			if(ctx->phase == 0) {
++				/* No more things to decode */
++				XER_ADVANCE(ch_size);
++				ctx->phase = 3;	/* Phase out */
++				RETURN(RC_OK);
++			}
++			/* Fall through */
++		case XCT_OPENING:
++			if(ctx->phase == 0) {
++				XER_ADVANCE(ch_size);
++				ctx->phase = 1;	/* Processing body phase */
++				continue;
++			}
++			/* Fall through */
++		case XCT_UNKNOWN_OP:
++		case XCT_UNKNOWN_BO:
++
++			ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
++			if(ctx->phase == 1) {
++				/*
++				 * Process a single possible member.
++				 */
++				ctx->phase = 2;
++				continue;
++			}
++			/* Fall through */
++		default:
++			break;
++		}
++
++		ASN_DEBUG("Unexpected XML tag in SET OF");
++		break;
++	}
++
++	ctx->phase = 3;	/* "Phase out" on hard failure */
++	RETURN(RC_FAIL);
++}
++
++
++
++typedef struct xer_tmp_enc_s {
++	void *buffer;
++	size_t offset;
++	size_t size;
++} xer_tmp_enc_t;
++static int
++SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) {
++	xer_tmp_enc_t *t = (xer_tmp_enc_t *)key;
++	if(t->offset + size >= t->size) {
++		size_t newsize = (t->size << 2) + size;
++		void *p = REALLOC(t->buffer, newsize);
++		if(!p) return -1;
++		t->buffer = p;
++		t->size = newsize;
++	}
++	memcpy((char *)t->buffer + t->offset, buffer, size);
++	t->offset += size;
++	return 0;
++}
++static int
++SET_OF_xer_order(const void *aptr, const void *bptr) {
++	const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr;
++	const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr;
++	size_t minlen = a->offset;
++	int ret;
++	if(b->offset < minlen) minlen = b->offset;
++	/* Well-formed UTF-8 has this nice lexicographical property... */
++	ret = memcmp(a->buffer, b->buffer, minlen);
++	if(ret != 0) return ret;
++	if(a->offset == b->offset)
++		return 0;
++	if(a->offset == minlen)
++		return -1;
++	return 1;
++}
++
++
++asn_enc_rval_t
++SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
++	int ilevel, enum xer_encoder_flags_e flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er;
++	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm = td->elements;
++	asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr);
++	const char *mname = specs->as_XMLValueList
++		? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
++	size_t mlen = mname ? strlen(mname) : 0;
++	int xcan = (flags & XER_F_CANONICAL);
++	xer_tmp_enc_t *encs = 0;
++	size_t encs_count = 0;
++	void *original_app_key = app_key;
++	asn_app_consume_bytes_f *original_cb = cb;
++	int i;
++
++	if(!sptr) _ASN_ENCODE_FAILED;
++
++	if(xcan) {
++		encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
++		if(!encs) _ASN_ENCODE_FAILED;
++		cb = SET_OF_encode_xer_callback;
++	}
++
++	er.encoded = 0;
++
++	for(i = 0; i < list->count; i++) {
++		asn_enc_rval_t tmper;
++
++		void *memb_ptr = list->array[i];
++		if(!memb_ptr) continue;
++
++		if(encs) {
++			memset(&encs[encs_count], 0, sizeof(encs[0]));
++			app_key = &encs[encs_count];
++			encs_count++;
++		}
++
++		if(mname) {
++			if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
++			_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
++		}
++
++		if(!xcan && specs->as_XMLValueList == 1)
++			_i_ASN_TEXT_INDENT(1, ilevel + 1);
++		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
++				ilevel + (specs->as_XMLValueList != 2),
++				flags, cb, app_key);
++		if(tmper.encoded == -1) {
++			td = tmper.failed_type;
++			sptr = tmper.structure_ptr;
++			goto cb_failed;
++		}
++		if(tmper.encoded == 0 && specs->as_XMLValueList) {
++			const char *name = elm->type->xml_tag;
++			size_t len = strlen(name);
++			_ASN_CALLBACK3("<", 1, name, len, "/>", 2);
++		}
++
++		if(mname) {
++			_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
++			er.encoded += 5;
++		}
++
++		er.encoded += (2 * mlen) + tmper.encoded;
++	}
++
++	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
++
++	if(encs) {
++		xer_tmp_enc_t *enc = encs;
++		xer_tmp_enc_t *end = encs + encs_count;
++		ssize_t control_size = 0;
++
++		cb = original_cb;
++		app_key = original_app_key;
++		qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order);
++
++		for(; enc < end; enc++) {
++			_ASN_CALLBACK(enc->buffer, enc->offset);
++			FREEMEM(enc->buffer);
++			enc->buffer = 0;
++			control_size += enc->offset;
++		}
++		assert(control_size == er.encoded);
++	}
++
++	goto cleanup;
++cb_failed:
++	er.encoded = -1;
++	er.failed_type = td;
++	er.structure_ptr = sptr;
++cleanup:
++	if(encs) {
++		while(encs_count-- > 0) {
++			if(encs[encs_count].buffer)
++				FREEMEM(encs[encs_count].buffer);
++		}
++		FREEMEM(encs);
++	}
++	_ASN_ENCODED_OK(er);
++}
++
++int
++SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_TYPE_member_t *elm = td->elements;
++	const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
++	int ret;
++	int i;
++
++	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++
++	/* Dump preamble */
++	if(cb(td->name, strlen(td->name), app_key) < 0
++	|| cb(" ::= {", 6, app_key) < 0)
++		return -1;
++
++	for(i = 0; i < list->count; i++) {
++		const void *memb_ptr = list->array[i];
++		if(!memb_ptr) continue;
++
++		_i_INDENT(1);
++
++		ret = elm->type->print_struct(elm->type, memb_ptr,
++			ilevel + 1, cb, app_key);
++		if(ret) return ret;
++	}
++
++	ilevel--;
++	_i_INDENT(1);
++
++	return (cb("}", 1, app_key) < 0) ? -1 : 0;
++}
++
++void
++SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
++	if(td && ptr) {
++		asn_TYPE_member_t *elm = td->elements;
++		asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
++		int i;
++
++		/*
++		 * Could not use set_of_empty() because of (*free)
++		 * incompatibility.
++		 */
++		for(i = 0; i < list->count; i++) {
++			void *memb_ptr = list->array[i];
++			if(memb_ptr)
++			ASN_STRUCT_FREE(*elm->type, memb_ptr);
++		}
++		list->count = 0;	/* No meaningful elements left */
++
++		asn_set_empty(list);	/* Remove (list->array) */
++
++		if(!contents_only) {
++			FREEMEM(ptr);
++		}
++	}
++}
++
++int
++SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
++		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
++	asn_TYPE_member_t *elm = td->elements;
++	asn_constr_check_f *constr;
++	const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
++	int i;
++
++	if(!sptr) {
++		_ASN_CTFAIL(app_key, td,
++			"%s: value not given (%s:%d)",
++			td->name, __FILE__, __LINE__);
++		return -1;
++	}
++
++	constr = elm->memb_constraints;
++	if(!constr) constr = elm->type->check_constraints;
++
++	/*
++	 * Iterate over the members of an array.
++	 * Validate each in turn, until one fails.
++	 */
++	for(i = 0; i < list->count; i++) {
++		const void *memb_ptr = list->array[i];
++		int ret;
++
++		if(!memb_ptr) continue;
++
++		ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
++		if(ret) return ret;
++	}
++
++	/*
++	 * Cannot inherit it eralier:
++	 * need to make sure we get the updated version.
++	 */
++	if(!elm->memb_constraints)
++		elm->memb_constraints = elm->type->check_constraints;
++
++	return 0;
++}
++
++asn_dec_rval_t
++SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++        asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
++	asn_dec_rval_t rv;
++        asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
++	asn_TYPE_member_t *elm = td->elements;	/* Single one */
++	void *st = *sptr;
++	asn_anonymous_set_ *list;
++	asn_per_constraint_t *ct;
++	int repeat = 0;
++	ssize_t nelems;
++
++	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
++		_ASN_DECODE_FAILED;
++
++	/*
++	 * Create the target structure if it is not present already.
++	 */
++	if(!st) {
++		st = *sptr = CALLOC(1, specs->struct_size);
++		if(!st) _ASN_DECODE_FAILED;
++	}                                                                       
++	list = _A_SET_FROM_VOID(st);
++
++	/* Figure out which constraints to use */
++	if(constraints) ct = &constraints->size;
++	else if(td->per_constraints) ct = &td->per_constraints->size;
++	else ct = 0;
++
++	if(ct && ct->flags & APC_EXTENSIBLE) {
++		int value = per_get_few_bits(pd, 1);
++		if(value < 0) _ASN_DECODE_STARVED;
++		if(value) ct = 0;	/* Not restricted! */
++	}
++
++	if(ct && ct->effective_bits >= 0) {
++		/* X.691, #19.5: No length determinant */
++		nelems = per_get_few_bits(pd, ct->effective_bits);
++		ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
++			(long)nelems, ct->lower_bound, td->name);
++		if(nelems < 0)  _ASN_DECODE_STARVED;
++		nelems += ct->lower_bound;
++	} else {
++		nelems = -1;
++	}
++
++	do {
++		int i;
++		if(nelems < 0) {
++			nelems = uper_get_length(pd,
++				ct ? ct->effective_bits : -1, &repeat);
++			ASN_DEBUG("Got to decode %d elements (eff %d)",
++				(int)nelems, (int)ct ? ct->effective_bits : -1);
++			if(nelems < 0) _ASN_DECODE_STARVED;
++		}
++
++		for(i = 0; i < nelems; i++) {
++			void *ptr = 0;
++			ASN_DEBUG("SET OF %s decoding", elm->type->name);
++			rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
++				elm->per_constraints, &ptr, pd);
++			ASN_DEBUG("%s SET OF %s decoded %d, %p",
++				td->name, elm->type->name, rv.code, ptr);
++			if(rv.code == RC_OK) {
++				if(ASN_SET_ADD(list, ptr) == 0)
++					continue;
++				ASN_DEBUG("Failed to add element into %s",
++					td->name);
++				/* Fall through */
++				rv.code == RC_FAIL;
++			} else {
++				ASN_DEBUG("Failed decoding %s of %s (SET OF)",
++					elm->type->name, td->name);
++			}
++			if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
++			return rv;
++		}
++
++		nelems = -1;	/* Allow uper_get_length() */
++	} while(repeat);
++
++	ASN_DEBUG("Decoded %s as SET OF", td->name);
++
++	rv.code = RC_OK;
++	rv.consumed = 0;
++	return rv;
++}
++
+diff --git a/asn1/asn1c/constr_SET_OF.h b/asn1/asn1c/constr_SET_OF.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..bcd09662906b69e5ac5cfec82c8a47b47ab3f351
+--- /dev/null
++++ b/asn1/asn1c/constr_SET_OF.h
+@@ -0,0 +1,42 @@
++/*-
++ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_CONSTR_SET_OF_H_
++#define	_CONSTR_SET_OF_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct asn_SET_OF_specifics_s {
++	/*
++	 * Target structure description.
++	 */
++	int struct_size;	/* Size of the target structure. */
++	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
++
++	/* XER-specific stuff */
++	int as_XMLValueList;	/* The member type must be encoded like this */
++} asn_SET_OF_specifics_t;
++
++/*
++ * A set specialized functions dealing with the SET OF type.
++ */
++asn_struct_free_f SET_OF_free;
++asn_struct_print_f SET_OF_print;
++asn_constr_check_f SET_OF_constraint;
++ber_type_decoder_f SET_OF_decode_ber;
++der_type_encoder_f SET_OF_encode_der;
++xer_type_decoder_f SET_OF_decode_xer;
++xer_type_encoder_f SET_OF_encode_xer;
++per_type_decoder_f SET_OF_decode_uper;
++per_type_encoder_f SET_OF_encode_uper;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _CONSTR_SET_OF_H_ */
+diff --git a/asn1/asn1c/constr_TYPE.c b/asn1/asn1c/constr_TYPE.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..4bc88d44f3c54131da0696b60050bd26376ce5b4
+--- /dev/null
++++ b/asn1/asn1c/constr_TYPE.c
+@@ -0,0 +1,77 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <constr_TYPE.h>
++#include <errno.h>
++
++/*
++ * Version of the ASN.1 infrastructure shipped with compiler.
++ */
++int get_asn1c_environment_version() { return ASN1C_ENVIRONMENT_VERSION; }
++
++static asn_app_consume_bytes_f _print2fp;
++
++/*
++ * Return the outmost tag of the type.
++ */
++ber_tlv_tag_t
++asn_TYPE_outmost_tag(asn_TYPE_descriptor_t *type_descriptor,
++		const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) {
++
++	if(tag_mode)
++		return tag;
++
++	if(type_descriptor->tags_count)
++		return type_descriptor->tags[0];
++
++	return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0);
++}
++
++/*
++ * Print the target language's structure in human readable form.
++ */
++int
++asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) {
++	if(!stream) stream = stdout;
++	if(!td || !struct_ptr) {
++		errno = EINVAL;
++		return -1;
++	}
++
++	/* Invoke type-specific printer */
++	if(td->print_struct(td, struct_ptr, 1, _print2fp, stream))
++		return -1;
++
++	/* Terminate the output */
++	if(_print2fp("\n", 1, stream))
++		return -1;
++
++	return fflush(stream);
++}
++
++/* Dump the data into the specified stdio stream */
++static int
++_print2fp(const void *buffer, size_t size, void *app_key) {
++	FILE *stream = (FILE *)app_key;
++
++	if(fwrite(buffer, 1, size, stream) != size)
++		return -1;
++
++	return 0;
++}
++
++
++/*
++ * Some compilers do not support variable args macros.
++ * This function is a replacement of ASN_DEBUG() macro.
++ */
++void ASN_DEBUG_f(const char *fmt, ...);
++void ASN_DEBUG_f(const char *fmt, ...) {
++	va_list ap;
++	va_start(ap, fmt);
++	vfprintf(stderr, fmt, ap);
++	fprintf(stderr, "\n");
++	va_end(ap);
++}
+diff --git a/asn1/asn1c/constr_TYPE.h b/asn1/asn1c/constr_TYPE.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..95507c8097b840457eafb95e1bae4abcff6a3e22
+--- /dev/null
++++ b/asn1/asn1c/constr_TYPE.h
+@@ -0,0 +1,180 @@
++/*-
++ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
++ * All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++/*
++ * This file contains the declaration structure called "ASN.1 Type Definition",
++ * which holds all information necessary for encoding and decoding routines.
++ * This structure even contains pointer to these encoding and decoding routines
++ * for each defined ASN.1 type.
++ */
++#ifndef	_CONSTR_TYPE_H_
++#define	_CONSTR_TYPE_H_
++
++#include <ber_tlv_length.h>
++#include <ber_tlv_tag.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++struct asn_TYPE_member_s;	/* Forward declaration */
++
++/*
++ * This type provides the context information for various ASN.1 routines,
++ * primarily ones doing decoding. A member _asn_ctx of this type must be
++ * included into certain target language's structures, such as compound types.
++ */
++typedef struct asn_struct_ctx_s {
++	short phase;		/* Decoding phase */
++	short step;		/* Elementary step of a phase */
++	int context;		/* Other context information */
++	void *ptr;		/* Decoder-specific stuff (stack elements) */
++	ber_tlv_len_t left;	/* Number of bytes left, -1 for indefinite */
++} asn_struct_ctx_t;
++
++#include <ber_decoder.h>	/* Basic Encoding Rules decoder */
++#include <der_encoder.h>	/* Distinguished Encoding Rules encoder */
++#include <xer_decoder.h>	/* Decoder of XER (XML, text) */
++#include <xer_encoder.h>	/* Encoder into XER (XML, text) */
++#include <per_decoder.h>	/* Packet Encoding Rules decoder */
++#include <per_encoder.h>	/* Packet Encoding Rules encoder */
++#include <constraints.h>	/* Subtype constraints support */
++
++/*
++ * Free the structure according to its specification.
++ * If (free_contents_only) is set, the wrapper structure itself (struct_ptr)
++ * will not be freed. (It may be useful in case the structure is allocated
++ * statically or arranged on the stack, yet its elements are allocated
++ * dynamically.)
++ */
++typedef void (asn_struct_free_f)(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr, int free_contents_only);
++#define	ASN_STRUCT_FREE(asn_DEF, ptr)	(asn_DEF).free_struct(&(asn_DEF),ptr,0)
++#define	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr)	\
++					(asn_DEF).free_struct(&(asn_DEF),ptr,1)
++
++/*
++ * Print the structure according to its specification.
++ */
++typedef int (asn_struct_print_f)(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		const void *struct_ptr,
++		int level,	/* Indentation level */
++		asn_app_consume_bytes_f *callback, void *app_key);
++
++/*
++ * Return the outmost tag of the type.
++ * If the type is untagged CHOICE, the dynamic operation is performed.
++ * NOTE: This function pointer type is only useful internally.
++ * Do not use it in your application.
++ */
++typedef ber_tlv_tag_t (asn_outmost_tag_f)(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag);
++/* The instance of the above function type; used internally. */
++asn_outmost_tag_f asn_TYPE_outmost_tag;
++
++
++/*
++ * The definitive description of the destination language's structure.
++ */
++typedef struct asn_TYPE_descriptor_s {
++	char *name;	/* A name of the ASN.1 type. "" in some cases. */
++	char *xml_tag;	/* Name used in XML tag */
++
++	/*
++	 * Generalized functions for dealing with the specific type.
++	 * May be directly invoked by applications.
++	 */
++	asn_struct_free_f  *free_struct;	/* Free the structure */
++	asn_struct_print_f *print_struct;	/* Human readable output */
++	asn_constr_check_f *check_constraints;	/* Constraints validator */
++	ber_type_decoder_f *ber_decoder;	/* Generic BER decoder */
++	der_type_encoder_f *der_encoder;	/* Canonical DER encoder */
++	xer_type_decoder_f *xer_decoder;	/* Generic XER decoder */
++	xer_type_encoder_f *xer_encoder;	/* [Canonical] XER encoder */
++	per_type_decoder_f *uper_decoder;	/* Unaligned PER decoder */
++	per_type_encoder_f *uper_encoder;	/* Unaligned PER encoder */
++
++	/***********************************************************************
++	 * Internally useful members. Not to be used by applications directly. *
++	 **********************************************************************/
++
++	/*
++	 * Tags that are expected to occur.
++	 */
++	asn_outmost_tag_f  *outmost_tag;	/* <optional, internal> */
++	ber_tlv_tag_t *tags;	/* Effective tags sequence for this type */
++	int tags_count;		/* Number of tags which are expected */
++	ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */
++	int all_tags_count;	/* Number of tags */
++
++	asn_per_constraints_t *per_constraints;	/* PER compiled constraints */
++
++	/*
++	 * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
++	 */
++	struct asn_TYPE_member_s *elements;
++	int elements_count;
++
++	/*
++	 * Additional information describing the type, used by appropriate
++	 * functions above.
++	 */
++	void *specifics;
++} asn_TYPE_descriptor_t;
++
++/*
++ * This type describes an element of the constructed type,
++ * i.e. SEQUENCE, SET, CHOICE, etc.
++ */
++  enum asn_TYPE_flags_e {
++	ATF_NOFLAGS,
++	ATF_POINTER	= 0x01,	/* Represented by the pointer */
++	ATF_OPEN_TYPE	= 0x02	/* ANY type, without meaningful tag */
++  };
++typedef struct asn_TYPE_member_s {
++	enum asn_TYPE_flags_e flags;	/* Element's presentation flags */
++	int optional;	/* Following optional members, including current */
++	int memb_offset;		/* Offset of the element */
++	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
++	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
++	asn_TYPE_descriptor_t *type;	/* Member type descriptor */
++	asn_constr_check_f *memb_constraints;	/* Constraints validator */
++	asn_per_constraints_t *per_constraints;	/* PER compiled constraints */
++	int (*default_value)(int setval, void **sptr);	/* DEFAULT <value> */
++	char *name;			/* ASN.1 identifier of the element */
++} asn_TYPE_member_t;
++
++/*
++ * BER tag to element number mapping.
++ */
++typedef struct asn_TYPE_tag2member_s {
++	ber_tlv_tag_t el_tag;	/* Outmost tag of the member */
++	int el_no;		/* Index of the associated member, base 0 */
++	int toff_first;		/* First occurence of the el_tag, relative */
++	int toff_last;		/* Last occurence of the el_tag, relatvie */
++} asn_TYPE_tag2member_t;
++
++/*
++ * This function is a wrapper around (td)->print_struct, which prints out
++ * the contents of the target language's structure (struct_ptr) into the
++ * file pointer (stream) in human readable form.
++ * RETURN VALUES:
++ * 	 0: The structure is printed.
++ * 	-1: Problem dumping the structure.
++ * (See also xer_fprint() in xer_encoder.h)
++ */
++int asn_fprint(FILE *stream,		/* Destination stream descriptor */
++	asn_TYPE_descriptor_t *td,	/* ASN.1 type descriptor */
++	const void *struct_ptr);	/* Structure to be printed */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _CONSTR_TYPE_H_ */
+diff --git a/asn1/asn1c/constraints.c b/asn1/asn1c/constraints.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..1bdda73e5d68cba8311e3fda444fd86d20865d2d
+--- /dev/null
++++ b/asn1/asn1c/constraints.c
+@@ -0,0 +1,93 @@
++#include "asn_internal.h"
++#include "constraints.h"
++
++int
++asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor,
++	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
++
++	(void)type_descriptor;	/* Unused argument */
++	(void)struct_ptr;	/* Unused argument */
++	(void)cb;	/* Unused argument */
++	(void)key;	/* Unused argument */
++
++	/* Nothing to check */
++	return 0;
++}
++
++int
++asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor,
++	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
++
++	(void)type_descriptor;	/* Unused argument */
++	(void)struct_ptr;	/* Unused argument */
++	(void)cb;	/* Unused argument */
++	(void)key;	/* Unused argument */
++
++	/* Unknown how to check */
++	return 0;
++}
++
++struct errbufDesc {
++	asn_TYPE_descriptor_t *failed_type;
++	const void *failed_struct_ptr;
++	char *errbuf;
++	size_t errlen;
++};
++
++static void
++_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) {
++	struct errbufDesc *arg = key;
++	va_list ap;
++	ssize_t vlen;
++	ssize_t maxlen;
++
++	arg->failed_type = td;
++	arg->failed_struct_ptr = sptr;
++
++	maxlen = arg->errlen;
++	if(maxlen <= 0)
++		return;
++
++	va_start(ap, fmt);
++	vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap);
++	va_end(ap);
++	if(vlen >= maxlen) {
++		arg->errbuf[maxlen-1] = '\0';	/* Ensuring libc correctness */
++		arg->errlen = maxlen - 1;	/* Not counting termination */
++		return;
++	} else if(vlen >= 0) {
++		arg->errbuf[vlen] = '\0';	/* Ensuring libc correctness */
++		arg->errlen = vlen;		/* Not counting termination */
++	} else {
++		/*
++		 * The libc on this system is broken.
++		 */
++		vlen = sizeof("<broken vsnprintf>") - 1;
++		maxlen--;
++		arg->errlen = vlen < maxlen ? vlen : maxlen;
++		memcpy(arg->errbuf, "<broken vsnprintf>", arg->errlen);
++		arg->errbuf[arg->errlen] = 0;
++	}
++
++	return;
++}
++
++int
++asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor,
++		const void *struct_ptr, char *errbuf, size_t *errlen) {
++	struct errbufDesc arg;
++	int ret;
++
++	arg.failed_type = 0;
++	arg.failed_struct_ptr = 0;
++	arg.errbuf = errbuf;
++	arg.errlen = errlen ? *errlen : 0;
++
++	ret = type_descriptor->check_constraints(type_descriptor,
++		struct_ptr, _asn_i_ctfailcb, &arg);
++	if(ret == -1 && errlen)
++		*errlen = arg.errlen;
++
++	return ret;
++}
++
+diff --git a/asn1/asn1c/constraints.h b/asn1/asn1c/constraints.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..5032345ee475564eeea0240bf73d76ae41139f6f
+--- /dev/null
++++ b/asn1/asn1c/constraints.h
+@@ -0,0 +1,63 @@
++/*-
++ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_ASN1_CONSTRAINTS_VALIDATOR_H_
++#define	_ASN1_CONSTRAINTS_VALIDATOR_H_
++
++#include <asn_system.h>		/* Platform-dependent types */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;		/* Forward declaration */
++
++/*
++ * Validate the structure according to the ASN.1 constraints.
++ * If errbuf and errlen are given, they shall be pointing to the appropriate
++ * buffer space and its length before calling this function. Alternatively,
++ * they could be passed as NULL's. If constraints validation fails,
++ * errlen will contain the actual number of bytes taken from the errbuf
++ * to encode an error message (properly 0-terminated).
++ * 
++ * RETURN VALUES:
++ * This function returns 0 in case all ASN.1 constraints are met
++ * and -1 if one or more constraints were failed.
++ */
++int
++asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor,
++	const void *struct_ptr,	/* Target language's structure */
++	char *errbuf,		/* Returned error description */
++	size_t *errlen		/* Length of the error description */
++	);
++
++
++/*
++ * Generic type for constraint checking callback,
++ * associated with every type descriptor.
++ */
++typedef int (asn_constr_check_f)(
++	struct asn_TYPE_descriptor_s *type_descriptor,
++	const void *struct_ptr,
++	asn_app_constraint_failed_f *optional_callback,	/* Log the error */
++	void *optional_app_key		/* Opaque key passed to a callback */
++	);
++
++/*******************************
++ * INTERNALLY USEFUL FUNCTIONS *
++ *******************************/
++
++asn_constr_check_f asn_generic_no_constraint;	/* No constraint whatsoever */
++asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */
++
++/*
++ * Invoke the callback with a complete error message.
++ */
++#define	_ASN_CTFAIL	if(ctfailcb) ctfailcb
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _ASN1_CONSTRAINTS_VALIDATOR_H_ */
+diff --git a/asn1/asn1c/der_encoder.c b/asn1/asn1c/der_encoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..6c859e1b08bba9600c97970df2fceede5716ddc0
+--- /dev/null
++++ b/asn1/asn1c/der_encoder.c
+@@ -0,0 +1,199 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <errno.h>
++
++static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
++	asn_app_consume_bytes_f *cb, void *app_key, int constructed);
++
++/*
++ * The DER encoder of any type.
++ */
++asn_enc_rval_t
++der_encode(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
++	asn_app_consume_bytes_f *consume_bytes, void *app_key) {
++
++	ASN_DEBUG("DER encoder invoked for %s",
++		type_descriptor->name);
++
++	/*
++	 * Invoke type-specific encoder.
++	 */
++	return type_descriptor->der_encoder(type_descriptor,
++		struct_ptr,	/* Pointer to the destination structure */
++		0, 0,
++		consume_bytes, app_key);
++}
++
++/*
++ * Argument type and callback necessary for der_encode_to_buffer().
++ */
++typedef struct enc_to_buf_arg {
++	void *buffer;
++	size_t left;
++} enc_to_buf_arg;
++static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
++	enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
++
++	if(arg->left < size)
++		return -1;	/* Data exceeds the available buffer size */
++
++	memcpy(arg->buffer, buffer, size);
++	arg->buffer = ((char *)arg->buffer) + size;
++	arg->left -= size;
++
++	return 0;
++}
++
++/*
++ * A variant of the der_encode() which encodes the data into the provided buffer
++ */
++asn_enc_rval_t
++der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
++	void *buffer, size_t buffer_size) {
++	enc_to_buf_arg arg;
++	asn_enc_rval_t ec;
++
++	arg.buffer = buffer;
++	arg.left = buffer_size;
++
++	ec = type_descriptor->der_encoder(type_descriptor,
++		struct_ptr,	/* Pointer to the destination structure */
++		0, 0, encode_to_buffer_cb, &arg);
++	if(ec.encoded != -1) {
++		assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
++		/* Return the encoded contents size */
++	}
++	return ec;
++}
++
++
++/*
++ * Write out leading TL[v] sequence according to the type definition.
++ */
++ssize_t
++der_write_tags(asn_TYPE_descriptor_t *sd,
++		size_t struct_length,
++		int tag_mode, int last_tag_form,
++		ber_tlv_tag_t tag,	/* EXPLICIT or IMPLICIT tag */
++		asn_app_consume_bytes_f *cb,
++		void *app_key) {
++	ber_tlv_tag_t *tags;	/* Copy of tags stream */
++	int tags_count;		/* Number of tags */
++	size_t overall_length;
++	ssize_t *lens;
++	int i;
++
++	ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",
++		sd->name, tag_mode, sd->tags_count,
++		ber_tlv_tag_string(tag),
++		tag_mode
++			?(sd->tags_count+1
++				-((tag_mode == -1) && sd->tags_count))
++			:sd->tags_count
++	);
++
++	if(tag_mode) {
++		/*
++		 * Instead of doing shaman dance like we do in ber_check_tags(),
++		 * allocate a small array on the stack
++		 * and initialize it appropriately.
++		 */
++		int stag_offset;
++		tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t));
++		if(!tags) {	/* Can fail on !x86 */
++			errno = ENOMEM;
++			return -1;
++		}
++		tags_count = sd->tags_count
++			+ 1	/* EXPLICIT or IMPLICIT tag is given */
++			- ((tag_mode == -1) && sd->tags_count);
++		/* Copy tags over */
++		tags[0] = tag;
++		stag_offset = -1 + ((tag_mode == -1) && sd->tags_count);
++		for(i = 1; i < tags_count; i++)
++			tags[i] = sd->tags[i + stag_offset];
++	} else {
++		tags = sd->tags;
++		tags_count = sd->tags_count;
++	}
++
++	/* No tags to write */
++	if(tags_count == 0)
++		return 0;
++
++	lens = (ssize_t *)alloca(tags_count * sizeof(lens[0]));
++	if(!lens) {
++		errno = ENOMEM;
++		return -1;
++	}
++
++	/*
++	 * Array of tags is initialized.
++	 * Now, compute the size of the TLV pairs, from right to left.
++	 */
++	overall_length = struct_length;
++	for(i = tags_count - 1; i >= 0; --i) {
++		lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0);
++		if(lens[i] == -1) return -1;
++		overall_length += lens[i];
++		lens[i] = overall_length - lens[i];
++	}
++
++	if(!cb) return overall_length - struct_length;
++
++	ASN_DEBUG("%s %s TL sequence (%d elements)",
++		cb?"Encoding":"Estimating", sd->name, tags_count);
++
++	/*
++	 * Encode the TL sequence for real.
++	 */
++	for(i = 0; i < tags_count; i++) {
++		ssize_t len;
++		int _constr;
++
++		/* Check if this tag happens to be constructed */
++		_constr = (last_tag_form || i < (tags_count - 1));
++
++		len = der_write_TL(tags[i], lens[i], cb, app_key, _constr);
++		if(len == -1) return -1;
++	}
++
++	return overall_length - struct_length;
++}
++
++static ssize_t
++der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
++		asn_app_consume_bytes_f *cb, void *app_key,
++		int constructed) {
++	uint8_t buf[32];
++	size_t size = 0;
++	int buf_size = cb?sizeof(buf):0;
++	ssize_t tmp;
++
++	/* Serialize tag (T from TLV) into possibly zero-length buffer */
++	tmp = ber_tlv_tag_serialize(tag, buf, buf_size);
++	if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1;
++	size += tmp;
++
++	/* Serialize length (L from TLV) into possibly zero-length buffer */
++	tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0);
++	if(tmp == -1) return -1;
++	size += tmp;
++
++	if(size > sizeof(buf))
++		return -1;
++
++	/*
++	 * If callback is specified, invoke it, and check its return value.
++	 */
++	if(cb) {
++		if(constructed) *buf |= 0x20;
++		if(cb(buf, size, app_key) < 0)
++			return -1;
++	}
++
++	return size;
++}
+diff --git a/asn1/asn1c/der_encoder.h b/asn1/asn1c/der_encoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..4e2fb06c28194510c6434f4829e56b2436d8f092
+--- /dev/null
++++ b/asn1/asn1c/der_encoder.h
+@@ -0,0 +1,67 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_DER_ENCODER_H_
++#define	_DER_ENCODER_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/*
++ * The DER encoder of any type. May be invoked by the application.
++ */
++asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr,	/* Structure to be encoded */
++		asn_app_consume_bytes_f *consume_bytes_cb,
++		void *app_key		/* Arbitrary callback argument */
++	);
++
++/* A variant of der_encode() which encodes data into the pre-allocated buffer */
++asn_enc_rval_t der_encode_to_buffer(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr,	/* Structure to be encoded */
++		void *buffer,		/* Pre-allocated buffer */
++		size_t buffer_size	/* Initial buffer size (maximum) */
++	);
++
++/*
++ * Type of the generic DER encoder.
++ */
++typedef asn_enc_rval_t (der_type_encoder_f)(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr,	/* Structure to be encoded */
++		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
++		ber_tlv_tag_t tag,
++		asn_app_consume_bytes_f *consume_bytes_cb,	/* Callback */
++		void *app_key		/* Arbitrary callback argument */
++	);
++
++
++/*******************************
++ * INTERNALLY USEFUL FUNCTIONS *
++ *******************************/
++
++/*
++ * Write out leading TL[v] sequence according to the type definition.
++ */
++ssize_t der_write_tags(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		size_t struct_length,
++		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
++		int last_tag_form,	/* {0,!0}: prim, constructed */
++		ber_tlv_tag_t tag,
++		asn_app_consume_bytes_f *consume_bytes_cb,
++		void *app_key
++	);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _DER_ENCODER_H_ */
+diff --git a/asn1/asn1c/ipa.asn1 b/asn1/asn1c/ipa.asn1
+new file mode 100644
+index 0000000000000000000000000000000000000000..a18488ed371de7270afe7a0a9b345217205a2873
+--- /dev/null
++++ b/asn1/asn1c/ipa.asn1
+@@ -0,0 +1,37 @@
++KeytabModule DEFINITIONS ::= BEGIN
++
++    Int32 ::= INTEGER (-2147483648..2147483647)
++    -- signed values representable in 32 bits (from RFC4120)
++
++    GetKeytabControl ::= CHOICE {
++        newkeys     [0] GKNewKeys,
++        curkeys     [1] GKCurrentKeys,
++        reply       [2] GKReply
++    }
++
++    GKNewKeys ::= SEQUENCE {
++        serviceIdentity [0] OCTET STRING,
++        enctypes        [1] SEQUENCE OF Int32,
++        password        [2] OCTET STRING OPTIONAL
++    }
++
++    GKCurrentKeys ::= SEQUENCE {
++        serviceIdentity [0] OCTET STRING
++    }
++
++    GKReply ::= SEQUENCE {
++        newkvno     Int32,
++        keys        SEQUENCE OF KrbKey
++    }
++
++    KrbKey ::= SEQUENCE {
++        key         [0] TypeValuePair,
++        salt        [1] TypeValuePair OPTIONAL,
++        s2kparams   [2] OCTET STRING OPTIONAL
++    }
++
++    TypeValuePair ::= SEQUENCE {
++        type    [0] Int32,
++        value   [1] OCTET STRING
++    }
++END
+diff --git a/asn1/asn1c/per_decoder.c b/asn1/asn1c/per_decoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..16dee369624bbf28bb8957e222abe77059980d9f
+--- /dev/null
++++ b/asn1/asn1c/per_decoder.c
+@@ -0,0 +1,55 @@
++#include <asn_application.h>
++#include <asn_internal.h>
++#include <per_decoder.h>
++
++asn_dec_rval_t
++uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
++	asn_codec_ctx_t s_codec_ctx;
++	asn_dec_rval_t rval;
++	asn_per_data_t pd;
++
++	if(skip_bits < 0 || skip_bits > 7
++	|| unused_bits < 0 || unused_bits > 7
++	|| (unused_bits > 0 && !size))
++		_ASN_DECODE_FAILED;
++
++	/*
++	 * Stack checker requires that the codec context
++	 * must be allocated on the stack.
++	 */
++	if(opt_codec_ctx) {
++		if(opt_codec_ctx->max_stack_size) {
++			s_codec_ctx = *opt_codec_ctx;
++			opt_codec_ctx = &s_codec_ctx;
++		}
++	} else {
++		/* If context is not given, be security-conscious anyway */
++		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
++		s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
++		opt_codec_ctx = &s_codec_ctx;
++	}
++
++	/* Fill in the position indicator */
++	pd.buffer = (const uint8_t *)buffer;
++	pd.nboff = skip_bits;
++	pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
++	if(pd.nboff > pd.nbits)
++		_ASN_DECODE_FAILED;
++
++	/*
++	 * Invoke type-specific decoder.
++	 */
++	if(!td->uper_decoder)
++		_ASN_DECODE_FAILED;	/* PER is not compiled in */
++	rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
++	if(rval.code == RC_OK) {
++		/* Return the number of consumed bits */
++		rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
++					+ pd.nboff - skip_bits;
++	} else {
++		/* PER codec is not a restartable */
++		rval.consumed = 0;
++	}
++	return rval;
++}
++
+diff --git a/asn1/asn1c/per_decoder.h b/asn1/asn1c/per_decoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..26aaf59400445aff62fb007370fc35c0cfa9b1b2
+--- /dev/null
++++ b/asn1/asn1c/per_decoder.h
+@@ -0,0 +1,44 @@
++/*-
++ * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_PER_DECODER_H_
++#define	_PER_DECODER_H_
++
++#include <asn_application.h>
++#include <per_support.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/*
++ * Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
++ */
++asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
++	struct asn_TYPE_descriptor_s *type_descriptor,	/* Type to decode */
++	void **struct_ptr,	/* Pointer to a target structure's pointer */
++	const void *buffer,	/* Data to be decoded */
++	size_t size,		/* Size of data buffer */
++	int skip_bits,		/* Number of unused leading bits, 0..7 */
++	int unused_bits		/* Number of unused tailing bits, 0..7 */
++	);
++
++
++/*
++ * Type of the type-specific PER decoder function.
++ */
++typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		asn_per_constraints_t *constraints,
++		void **struct_ptr,
++		asn_per_data_t *per_data
++	);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _PER_DECODER_H_ */
+diff --git a/asn1/asn1c/per_encoder.c b/asn1/asn1c/per_encoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..614dd23331d482a05b973f790449359e7f503768
+--- /dev/null
++++ b/asn1/asn1c/per_encoder.c
+@@ -0,0 +1,95 @@
++#include <asn_application.h>
++#include <asn_internal.h>
++#include <per_encoder.h>
++
++/* Flush partially filled buffer */
++static int _uper_encode_flush_outp(asn_per_outp_t *po);
++
++asn_enc_rval_t
++uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_per_outp_t po;
++	asn_enc_rval_t er;
++
++	/*
++	 * Invoke type-specific encoder.
++	 */
++	if(!td || !td->uper_encoder)
++		_ASN_ENCODE_FAILED;	/* PER is not compiled in */
++
++	po.buffer = po.tmpspace;
++	po.nboff = 0;
++	po.nbits = 8 * sizeof(po.tmpspace);
++	po.outper = cb;
++	po.op_key = app_key;
++	po.flushed_bytes = 0;
++
++	er = td->uper_encoder(td, 0, sptr, &po);
++	if(er.encoded != -1) {
++		size_t bits_to_flush;
++
++		bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
++
++		/* Set number of bits encoded to a firm value */
++		er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
++
++		if(_uper_encode_flush_outp(&po))
++			_ASN_ENCODE_FAILED;
++	}
++
++	return er;
++}
++
++/*
++ * Argument type and callback necessary for uper_encode_to_buffer().
++ */
++typedef struct enc_to_buf_arg {
++	void *buffer;
++	size_t left;
++} enc_to_buf_arg;
++static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
++	enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
++
++	if(arg->left < size)
++		return -1;	/* Data exceeds the available buffer size */
++
++	memcpy(arg->buffer, buffer, size);
++	arg->buffer = ((char *)arg->buffer) + size;
++	arg->left -= size;
++
++	return 0;
++}
++
++asn_enc_rval_t
++uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
++	enc_to_buf_arg key;
++
++	/*
++	 * Invoke type-specific encoder.
++	 */
++	if(!td || !td->uper_encoder)
++		_ASN_ENCODE_FAILED;	/* PER is not compiled in */
++
++	key.buffer = buffer;
++	key.left = buffer_size;
++
++	ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
++
++	return uper_encode(td, sptr, encode_to_buffer_cb, &key);
++}
++
++static int
++_uper_encode_flush_outp(asn_per_outp_t *po) {
++	uint8_t *buf;
++
++	if(po->nboff == 0 && po->buffer == po->tmpspace)
++		return 0;
++
++	buf = po->buffer + (po->nboff >> 3);
++	/* Make sure we account for the last, partially filled */
++	if(po->nboff & 0x07) {
++		buf[0] &= 0xff << (8 - (po->nboff & 0x07));
++		buf++;
++	}
++
++	return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
++}
+diff --git a/asn1/asn1c/per_encoder.h b/asn1/asn1c/per_encoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..9ac130b7373cc354effd24058027ea85ca3a9e59
+--- /dev/null
++++ b/asn1/asn1c/per_encoder.h
+@@ -0,0 +1,49 @@
++/*-
++ * Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_PER_ENCODER_H_
++#define	_PER_ENCODER_H_
++
++#include <asn_application.h>
++#include <per_support.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/*
++ * Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
++ */
++asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
++	void *struct_ptr,	/* Structure to be encoded */
++	asn_app_consume_bytes_f *consume_bytes_cb,	/* Data collector */
++	void *app_key		/* Arbitrary callback argument */
++);
++
++/* A variant of uper_encode() which encodes data into the existing buffer */
++asn_enc_rval_t uper_encode_to_buffer(
++	struct asn_TYPE_descriptor_s *type_descriptor,
++	void *struct_ptr,	/* Structure to be encoded */
++	void *buffer,		/* Pre-allocated buffer */
++	size_t buffer_size	/* Initial buffer size (max) */
++);
++
++
++/*
++ * Type of the generic PER encoder function.
++ */
++typedef asn_enc_rval_t (per_type_encoder_f)(
++	struct asn_TYPE_descriptor_s *type_descriptor,
++	asn_per_constraints_t *constraints,
++	void *struct_ptr,
++	asn_per_outp_t *per_output
++);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _PER_ENCODER_H_ */
+diff --git a/asn1/asn1c/per_support.c b/asn1/asn1c/per_support.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..c83441931caf1fcc3a79c0062014833db3d141b5
+--- /dev/null
++++ b/asn1/asn1c/per_support.c
+@@ -0,0 +1,318 @@
++/*
++ * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_system.h>
++#include <asn_internal.h>
++#include <per_support.h>
++
++/*
++ * Extract a small number of bits (<= 31) from the specified PER data pointer.
++ */
++int32_t
++per_get_few_bits(asn_per_data_t *pd, int nbits) {
++	size_t off;	/* Next after last bit offset */
++	uint32_t accum;
++	const uint8_t *buf;
++
++	if(nbits < 0 || pd->nboff + nbits > pd->nbits)
++		return -1;
++
++	ASN_DEBUG("[PER get %d bits from %p+%d bits]",
++		nbits, pd->buffer, pd->nboff);
++
++	/*
++	 * Normalize position indicator.
++	 */
++	if(pd->nboff >= 8) {
++		pd->buffer += (pd->nboff >> 3);
++		pd->nbits  -= (pd->nboff & ~0x07);
++		pd->nboff  &= 0x07;
++	}
++	off = (pd->nboff += nbits);
++	buf = pd->buffer;
++
++	/*
++	 * Extract specified number of bits.
++	 */
++	if(off <= 8)
++		accum = nbits ? (buf[0]) >> (8 - off) : 0;
++	else if(off <= 16)
++		accum = ((buf[0] << 8) + buf[1]) >> (16 - off);
++	else if(off <= 24)
++		accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off);
++	else if(off <= 31)
++		accum = ((buf[0] << 24) + (buf[1] << 16)
++			+ (buf[2] << 8) + (buf[3])) >> (32 - off);
++	else if(nbits <= 31) {
++		asn_per_data_t tpd = *pd;
++		/* Here are we with our 31-bits limit plus 1..7 bits offset. */
++		tpd.nboff -= nbits;
++		accum  = per_get_few_bits(&tpd, nbits - 24) << 24;
++		accum |= per_get_few_bits(&tpd, 24);
++	} else {
++		pd->nboff -= nbits;	/* Oops, revert back */
++		return -1;
++	}
++
++	return (accum & (((uint32_t)1 << nbits) - 1));
++}
++
++/*
++ * Extract a large number of bits from the specified PER data pointer.
++ */
++int
++per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
++	int32_t value;
++
++	if(alright && (nbits & 7)) {
++		/* Perform right alignment of a first few bits */
++		value = per_get_few_bits(pd, nbits & 0x07);
++		if(value < 0) return -1;
++		*dst++ = value;	/* value is already right-aligned */
++		nbits &= ~7;
++	}
++
++	while(nbits) {
++		if(nbits >= 24) {
++			value = per_get_few_bits(pd, 24);
++			if(value < 0) return -1;
++			*(dst++) = value >> 16;
++			*(dst++) = value >> 8;
++			*(dst++) = value;
++			nbits -= 24;
++		} else {
++			value = per_get_few_bits(pd, nbits);
++			if(value < 0) return -1;
++			if(nbits & 7) {	/* implies left alignment */
++				value <<= 8 - (nbits & 7),
++				nbits += 8 - (nbits & 7);
++				if(nbits > 24)
++					*dst++ = value >> 24;
++			}
++			if(nbits > 16)
++				*dst++ = value >> 16;
++			if(nbits > 8)
++				*dst++ = value >> 8;
++			*dst++ = value;
++			break;
++		}
++	}
++
++	return 0;
++}
++
++/*
++ * Get the length "n" from the stream.
++ */
++ssize_t
++uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
++	ssize_t value;
++
++	*repeat = 0;
++
++	if(ebits >= 0) return per_get_few_bits(pd, ebits);
++
++	value = per_get_few_bits(pd, 8);
++	if(value < 0) return -1;
++	if((value & 128) == 0)	/* #10.9.3.6 */
++		return (value & 0x7F);
++	if((value & 64) == 0) {	/* #10.9.3.7 */
++		value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
++		if(value < 0) return -1;
++		return value;
++	}
++	value &= 63;	/* this is "m" from X.691, #10.9.3.8 */
++	if(value < 1 || value > 4)
++		return -1;
++	*repeat = 1;
++	return (16384 * value);
++}
++
++/*
++ * Get the normally small non-negative whole number.
++ * X.691, #10.6
++ */
++ssize_t
++uper_get_nsnnwn(asn_per_data_t *pd) {
++	ssize_t value;
++
++	value = per_get_few_bits(pd, 7);
++	if(value & 64) {	/* implicit (value < 0) */
++		value &= 63;
++		value <<= 2;
++		value |= per_get_few_bits(pd, 2);
++		if(value & 128)	/* implicit (value < 0) */
++			return -1;
++		if(value == 0)
++			return 0;
++		if(value >= 3)
++			return -1;
++		value = per_get_few_bits(pd, 8 * value);
++		return value;
++	}
++
++	return value;
++}
++
++/*
++ * Put the normally small non-negative whole number.
++ * X.691, #10.6
++ */
++int
++uper_put_nsnnwn(asn_per_outp_t *po, int n) {
++	int bytes;
++
++	if(n <= 63) {
++		if(n < 0) return -1;
++		return per_put_few_bits(po, n, 7);
++	}
++	if(n < 256)
++		bytes = 1;
++	else if(n < 65536)
++		bytes = 2;
++	else if(n < 256 * 65536)
++		bytes = 3;
++	else
++		return -1;	/* This is not a "normally small" value */
++	if(per_put_few_bits(po, bytes, 8))
++		return -1;
++
++	return per_put_few_bits(po, n, 8 * bytes);
++}
++
++
++/*
++ * Put a small number of bits (<= 31).
++ */
++int
++per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
++	size_t off;	/* Next after last bit offset */
++	size_t omsk;	/* Existing last byte meaningful bits mask */
++	uint8_t *buf;
++
++	if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
++
++	ASN_DEBUG("[PER put %d bits to %p+%d bits]",
++			obits, po->buffer, po->nboff);
++
++	/*
++	 * Normalize position indicator.
++	 */
++	if(po->nboff >= 8) {
++		po->buffer += (po->nboff >> 3);
++		po->nbits  -= (po->nboff & ~0x07);
++		po->nboff  &= 0x07;
++	}
++
++	/*
++	 * Flush whole-bytes output, if necessary.
++	 */
++	if(po->nboff + obits > po->nbits) {
++		int complete_bytes = (po->buffer - po->tmpspace);
++		if(po->outper(po->buffer, complete_bytes, po->op_key) < 0)
++			return -1;
++		if(po->nboff)
++			po->tmpspace[0] = po->buffer[0];
++		po->buffer = po->tmpspace;
++		po->nbits = 8 * sizeof(po->tmpspace);
++		po->flushed_bytes += complete_bytes;
++	}
++
++	/*
++	 * Now, due to sizeof(tmpspace), we are guaranteed large enough space.
++	 */
++	buf = po->buffer;
++	omsk = ~((1 << (8 - po->nboff)) - 1);
++	off = (po->nboff += obits);
++
++	/* Clear data of debris before meaningful bits */
++	bits &= (((uint32_t)1 << obits) - 1);
++
++	ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits,
++		po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
++
++	if(off <= 8)	/* Completely within 1 byte */
++		bits <<= (8 - off),
++		buf[0] = (buf[0] & omsk) | bits;
++	else if(off <= 16)
++		bits <<= (16 - off),
++		buf[0] = (buf[0] & omsk) | (bits >> 8),
++		buf[1] = bits;
++	else if(off <= 24)
++		bits <<= (24 - off),
++		buf[0] = (buf[0] & omsk) | (bits >> 16),
++		buf[1] = bits >> 8,
++		buf[2] = bits;
++	else if(off <= 31)
++		bits <<= (32 - off),
++		buf[0] = (buf[0] & omsk) | (bits >> 24),
++		buf[1] = bits >> 16,
++		buf[2] = bits >> 8,
++		buf[3] = bits;
++	else {
++		ASN_DEBUG("->[PER out split %d]", obits);
++		per_put_few_bits(po, bits >> 8, 24);
++		per_put_few_bits(po, bits, obits - 24);
++		ASN_DEBUG("<-[PER out split %d]", obits);
++	}
++
++	ASN_DEBUG("[PER out %u/%x => %02x buf+%d]",
++		bits, bits, buf[0], po->buffer - po->tmpspace);
++
++	return 0;
++}
++
++
++/*
++ * Output a large number of bits.
++ */
++int
++per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
++
++	while(nbits) {
++		uint32_t value;
++
++		if(nbits >= 24) {
++			value = (src[0] << 16) | (src[1] << 8) | src[2];
++			src += 3;
++			nbits -= 24;
++			if(per_put_few_bits(po, value, 24))
++				return -1;
++		} else {
++			value = src[0];
++			if(nbits > 8)
++				value = (value << 8) | src[1];
++			if(nbits > 16)
++				value = (value << 8) | src[2];
++			if(nbits & 0x07)
++				value >>= (8 - (nbits & 0x07));
++			if(per_put_few_bits(po, value, nbits))
++				return -1;
++			break;
++		}
++	}
++
++	return 0;
++}
++
++/*
++ * Put the length "n" (or part of it) into the stream.
++ */
++ssize_t
++uper_put_length(asn_per_outp_t *po, size_t length) {
++
++	if(length <= 127)	/* #10.9.3.6 */
++		return per_put_few_bits(po, length, 8)
++			? -1 : (ssize_t)length;
++	else if(length < 16384)	/* #10.9.3.7 */
++		return per_put_few_bits(po, length|0x8000, 16)
++			? -1 : (ssize_t)length;
++
++	length >>= 14;
++	if(length > 4) length = 4;
++
++	return per_put_few_bits(po, 0xC0 | length, 8)
++			? -1 : (ssize_t)(length << 14);
++}
++
+diff --git a/asn1/asn1c/per_support.h b/asn1/asn1c/per_support.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..420bb83c58d081ba3949951b67709e3200e7192a
+--- /dev/null
++++ b/asn1/asn1c/per_support.h
+@@ -0,0 +1,105 @@
++/*
++ * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_PER_SUPPORT_H_
++#define	_PER_SUPPORT_H_
++
++#include <asn_system.h>		/* Platform-specific types */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Pre-computed PER constraints.
++ */
++typedef struct asn_per_constraint_s {
++	enum asn_per_constraint_flags {
++		APC_UNCONSTRAINED	= 0x0,	/* No PER visible constraints */
++		APC_SEMI_CONSTRAINED	= 0x1,	/* Constrained at "lb" */
++		APC_CONSTRAINED		= 0x2,	/* Fully constrained */
++		APC_EXTENSIBLE		= 0x4	/* May have extension */
++	} flags;
++	int  range_bits;		/* Full number of bits in the range */
++	int  effective_bits;		/* Effective bits */
++	long lower_bound;		/* "lb" value */
++	long upper_bound;		/* "ub" value */
++} asn_per_constraint_t;
++typedef struct asn_per_constraints_s {
++	asn_per_constraint_t value;
++	asn_per_constraint_t size;
++} asn_per_constraints_t;
++
++/*
++ * This structure describes a position inside an incoming PER bit stream.
++ */
++typedef struct asn_per_data_s {
++ const uint8_t *buffer;	/* Pointer to the octet stream */
++        size_t  nboff;	/* Bit offset to the meaningful bit */
++        size_t  nbits;	/* Number of bits in the stream */
++} asn_per_data_t;
++
++/*
++ * Extract a small number of bits (<= 31) from the specified PER data pointer.
++ * This function returns -1 if the specified number of bits could not be
++ * extracted due to EOD or other conditions.
++ */
++int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
++
++/*
++ * Extract a large number of bits from the specified PER data pointer.
++ * This function returns -1 if the specified number of bits could not be
++ * extracted due to EOD or other conditions.
++ */
++int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align,
++			int get_nbits);
++
++/*
++ * Get the length "n" from the Unaligned PER stream.
++ */
++ssize_t uper_get_length(asn_per_data_t *pd,
++			int effective_bound_bits,
++			int *repeat);
++
++/*
++ * Get the normally small non-negative whole number.
++ */
++ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
++
++/*
++ * This structure supports forming PER output.
++ */
++typedef struct asn_per_outp_s {
++	uint8_t *buffer;	/* Pointer into the (tmpspace) */
++	size_t nboff;		/* Bit offset to the meaningful bit */
++	size_t nbits;		/* Number of bits left in (tmpspace) */
++	uint8_t tmpspace[32];	/* Preliminary storage to hold data */
++	int (*outper)(const void *data, size_t size, void *op_key);
++	void *op_key;		/* Key for (outper) data callback */
++	size_t flushed_bytes;	/* Bytes already flushed through (outper) */
++} asn_per_outp_t;
++
++/* Output a small number of bits (<= 31) */
++int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
++
++/* Output a large number of bits */
++int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
++
++/*
++ * Put the length "n" to the Unaligned PER stream.
++ * This function returns the number of units which may be flushed
++ * in the next units saving iteration.
++ */
++ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
++
++/*
++ * Put the normally small non-negative whole number.
++ */
++int uper_put_nsnnwn(asn_per_outp_t *po, int n);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _PER_SUPPORT_H_ */
+diff --git a/asn1/asn1c/xer_decoder.c b/asn1/asn1c/xer_decoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..161dc78ce5320368d07c0cd9b01032d07997e0fb
+--- /dev/null
++++ b/asn1/asn1c/xer_decoder.c
+@@ -0,0 +1,363 @@
++/*
++ * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_application.h>
++#include <asn_internal.h>
++#include <xer_support.h>		/* XER/XML parsing support */
++
++
++/*
++ * Decode the XER encoding of a given type.
++ */
++asn_dec_rval_t
++xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
++		void **struct_ptr, const void *buffer, size_t size) {
++	asn_codec_ctx_t s_codec_ctx;
++
++	/*
++	 * Stack checker requires that the codec context
++	 * must be allocated on the stack.
++	 */
++	if(opt_codec_ctx) {
++		if(opt_codec_ctx->max_stack_size) {
++			s_codec_ctx = *opt_codec_ctx;
++			opt_codec_ctx = &s_codec_ctx;
++		}
++	} else {
++		/* If context is not given, be security-conscious anyway */
++		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
++		s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
++		opt_codec_ctx = &s_codec_ctx;
++	}
++
++	/*
++	 * Invoke type-specific decoder.
++	 */
++	return td->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);
++}
++
++
++
++struct xer__cb_arg {
++	pxml_chunk_type_e	chunk_type;
++	size_t			chunk_size;
++	const void		*chunk_buf;
++	int callback_not_invoked;
++};
++
++static int
++xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
++	struct xer__cb_arg *arg = (struct xer__cb_arg *)key;
++	arg->chunk_type = type;
++	arg->chunk_size = _chunk_size;
++	arg->chunk_buf = _chunk_data;
++	arg->callback_not_invoked = 0;
++	return -1;	/* Terminate the XML parsing */
++}
++
++/*
++ * Fetch the next token from the XER/XML stream.
++ */
++ssize_t
++xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
++	struct xer__cb_arg arg;
++	int new_stateContext = *stateContext;
++	ssize_t ret;
++
++	arg.callback_not_invoked = 1;
++	ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
++	if(ret < 0) return -1;
++	if(arg.callback_not_invoked) {
++		assert(ret == 0);	/* No data was consumed */
++		return 0;		/* Try again with more data */
++	} else {
++		assert(arg.chunk_size);
++		assert(arg.chunk_buf == buffer);
++	}
++
++	/*
++	 * Translate the XML chunk types into more convenient ones.
++	 */
++	switch(arg.chunk_type) {
++	case PXML_TEXT:
++		*ch_type = PXER_TEXT;
++		break;
++	case PXML_TAG: return 0;	/* Want more */
++	case PXML_TAG_END:
++		*ch_type = PXER_TAG;
++		break;
++	case PXML_COMMENT:
++	case PXML_COMMENT_END:
++		*ch_type = PXER_COMMENT;
++		break;
++	}
++
++	*stateContext = new_stateContext;
++	return arg.chunk_size;
++}
++
++#define	CSLASH	0x2f	/* '/' */
++#define	LANGLE	0x3c	/* '<' */
++#define	RANGLE	0x3e	/* '>' */
++
++xer_check_tag_e
++xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {
++	const char *buf = (const char *)buf_ptr;
++	const char *end;
++	xer_check_tag_e ct = XCT_OPENING;
++
++	if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
++		if(size >= 2)
++		ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]);
++		return XCT_BROKEN;
++	}
++
++	/*
++	 * Determine the tag class.
++	 */
++	if(buf[1] == CSLASH) {
++		buf += 2;	/* advance past "</" */
++		size -= 3;	/* strip "</" and ">" */
++		ct = XCT_CLOSING;
++		if(size > 0 && buf[size-1] == CSLASH)
++			return XCT_BROKEN;	/* </abc/> */
++	} else {
++		buf++;		/* advance past "<" */
++		size -= 2;	/* strip "<" and ">" */
++		if(size > 0 && buf[size-1] == CSLASH) {
++			ct = XCT_BOTH;
++			size--;	/* One more, for "/" */
++		}
++	}
++
++	/* Sometimes we don't care about the tag */
++	if(!need_tag || !*need_tag)
++		return (xer_check_tag_e)(XCT__UNK__MASK | ct);
++
++	/*
++	 * Determine the tag name.
++	 */
++	for(end = buf + size; buf < end; buf++, need_tag++) {
++		int b = *buf, n = *need_tag;
++		if(b != n) {
++			if(n == 0) {
++				switch(b) {
++				case 0x09: case 0x0a: case 0x0c: case 0x0d:
++				case 0x20:
++					/* "<abc def/>": whitespace is normal */
++					return ct;
++				}
++			}
++			return (xer_check_tag_e)(XCT__UNK__MASK | ct);
++		}
++		if(b == 0)
++			return XCT_BROKEN;	/* Embedded 0 in buf?! */
++	}
++	if(*need_tag)
++		return (xer_check_tag_e)(XCT__UNK__MASK | ct);
++
++	return ct;
++}
++
++
++#undef	ADVANCE
++#define	ADVANCE(num_bytes)	do {				\
++		size_t num = (num_bytes);			\
++		buf_ptr = ((const char *)buf_ptr) + num;	\
++		size -= num;					\
++		consumed_myself += num;				\
++	} while(0)
++
++#undef	RETURN
++#define	RETURN(_code)	do {					\
++		rval.code = _code;				\
++		rval.consumed = consumed_myself;		\
++		if(rval.code != RC_OK)				\
++			ASN_DEBUG("Failed with %d", rval.code);	\
++		return rval;					\
++	} while(0)
++
++#define	XER_GOT_BODY(chunk_buf, chunk_size, size)	do {	\
++		ssize_t converted_size = body_receiver		\
++			(struct_key, chunk_buf, chunk_size,	\
++				(size_t)chunk_size < size);	\
++		if(converted_size == -1) RETURN(RC_FAIL);	\
++		if(converted_size == 0				\
++			&& size == (size_t)chunk_size)		\
++			RETURN(RC_WMORE);			\
++		chunk_size = converted_size;			\
++	} while(0)
++#define	XER_GOT_EMPTY()	do {					\
++	if(body_receiver(struct_key, 0, 0, size > 0) == -1)	\
++			RETURN(RC_FAIL);			\
++	} while(0)
++
++/*
++ * Generalized function for decoding the primitive values.
++ */
++asn_dec_rval_t
++xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
++	asn_struct_ctx_t *ctx,	/* Type decoder context */
++	void *struct_key,
++	const char *xml_tag,	/* Expected XML tag */
++	const void *buf_ptr, size_t size,
++	int (*opt_unexpected_tag_decoder)
++		(void *struct_key, const void *chunk_buf, size_t chunk_size),
++	ssize_t (*body_receiver)
++		(void *struct_key, const void *chunk_buf, size_t chunk_size,
++			int have_more)
++	) {
++
++	asn_dec_rval_t rval;
++	ssize_t consumed_myself = 0;
++
++	(void)opt_codec_ctx;
++
++	/*
++	 * Phases of XER/XML processing:
++	 * Phase 0: Check that the opening tag matches our expectations.
++	 * Phase 1: Processing body and reacting on closing tag.
++	 */
++	if(ctx->phase > 1) RETURN(RC_FAIL);
++	for(;;) {
++		pxer_chunk_type_e ch_type;	/* XER chunk type */
++		ssize_t ch_size;		/* Chunk size */
++		xer_check_tag_e tcv;		/* Tag check value */
++
++		/*
++		 * Get the next part of the XML stream.
++		 */
++		ch_size = xer_next_token(&ctx->context, buf_ptr, size,
++			&ch_type);
++		switch(ch_size) {
++		case -1: RETURN(RC_FAIL);
++		case 0:
++			RETURN(RC_WMORE);
++		default:
++			switch(ch_type) {
++			case PXER_COMMENT:		/* Got XML comment */
++				ADVANCE(ch_size);	/* Skip silently */
++				continue;
++			case PXER_TEXT:
++				if(ctx->phase == 0) {
++					/*
++					 * We have to ignore whitespace here,
++					 * but in order to be forward compatible
++					 * with EXTENDED-XER (EMBED-VALUES, #25)
++					 * any text is just ignored here.
++					 */
++				} else {
++					XER_GOT_BODY(buf_ptr, ch_size, size);
++				}
++				ADVANCE(ch_size);
++				continue;
++			case PXER_TAG:
++				break;	/* Check the rest down there */
++			}
++		}
++
++		assert(ch_type == PXER_TAG && size);
++
++		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
++		/*
++		 * Phase 0:
++		 * 	Expecting the opening tag
++		 * 	for the type being processed.
++		 * Phase 1:
++		 * 	Waiting for the closing XML tag.
++		 */
++		switch(tcv) {
++		case XCT_BOTH:
++			if(ctx->phase) break;
++			/* Finished decoding of an empty element */
++			XER_GOT_EMPTY();
++			ADVANCE(ch_size);
++			ctx->phase = 2;	/* Phase out */
++			RETURN(RC_OK);
++		case XCT_OPENING:
++			if(ctx->phase) break;
++			ADVANCE(ch_size);
++			ctx->phase = 1;	/* Processing body phase */
++			continue;
++		case XCT_CLOSING:
++			if(!ctx->phase) break;
++			ADVANCE(ch_size);
++			ctx->phase = 2;	/* Phase out */
++			RETURN(RC_OK);
++		case XCT_UNKNOWN_BO:
++			/*
++			 * Certain tags in the body may be expected.
++			 */
++			if(opt_unexpected_tag_decoder
++			&& opt_unexpected_tag_decoder(struct_key,
++					buf_ptr, ch_size) >= 0) {
++				/* Tag's processed fine */
++				ADVANCE(ch_size);
++				if(!ctx->phase) {
++					/* We are not expecting
++					 * the closing tag anymore. */
++					ctx->phase = 2;	/* Phase out */
++					RETURN(RC_OK);
++				}
++				continue;
++			}
++			/* Fall through */
++		default:
++			break;		/* Unexpected tag */
++		}
++
++		ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag);
++		break;	/* Dark and mysterious things have just happened */
++	}
++
++	RETURN(RC_FAIL);
++}
++
++
++int
++xer_is_whitespace(const void *chunk_buf, size_t chunk_size) {
++	const char *p = (const char *)chunk_buf;
++	const char *pend = p + chunk_size;
++
++	for(; p < pend; p++) {
++		switch(*p) {
++		/* X.693, #8.1.4
++		 * HORISONTAL TAB (9)
++		 * LINE FEED (10) 
++		 * CARRIAGE RETURN (13) 
++		 * SPACE (32)
++		 */
++		case 0x09: case 0x0a: case 0x0d: case 0x20:
++			break;
++		default:
++			return 0;
++		}
++	}
++	return 1;       /* All whitespace */
++}
++
++/*
++ * This is a vastly simplified, non-validating XML tree skipper.
++ */
++int
++xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
++	assert(*depth > 0);
++	switch(tcv) {
++	case XCT_BOTH:
++	case XCT_UNKNOWN_BO:
++		/* These negate each other. */
++		return 0;
++	case XCT_OPENING:
++	case XCT_UNKNOWN_OP:
++		++(*depth);
++		return 0;
++	case XCT_CLOSING:
++	case XCT_UNKNOWN_CL:
++		if(--(*depth) == 0)
++			return (tcv == XCT_CLOSING) ? 2 : 1;
++		return 0;
++	default:
++		return -1;
++	}
++}
+diff --git a/asn1/asn1c/xer_decoder.h b/asn1/asn1c/xer_decoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..cf0d846fe72d66d0c03548e9f6f4b2c3ecab716d
+--- /dev/null
++++ b/asn1/asn1c/xer_decoder.h
+@@ -0,0 +1,106 @@
++/*-
++ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_XER_DECODER_H_
++#define	_XER_DECODER_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/*
++ * The XER decoder of any ASN.1 type. May be invoked by the application.
++ */
++asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx,
++	struct asn_TYPE_descriptor_s *type_descriptor,
++	void **struct_ptr,	/* Pointer to a target structure's pointer */
++	const void *buffer,	/* Data to be decoded */
++	size_t size		/* Size of data buffer */
++	);
++
++/*
++ * Type of the type-specific XER decoder function.
++ */
++typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void **struct_ptr,
++		const char *opt_mname,	/* Member name */
++		const void *buf_ptr, size_t size
++	);
++
++/*******************************
++ * INTERNALLY USEFUL FUNCTIONS *
++ *******************************/
++
++/*
++ * Generalized function for decoding the primitive values.
++ * Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8
++ * and others. This function should not be used by applications, as its API
++ * is subject to changes.
++ */
++asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
++	asn_struct_ctx_t *ctx,	/* Type decoder context */
++	void *struct_key,	/* Treated as opaque pointer */
++	const char *xml_tag,	/* Expected XML tag name */
++	const void *buf_ptr, size_t size,
++	int (*opt_unexpected_tag_decoder)
++		(void *struct_key, const void *chunk_buf, size_t chunk_size),
++	ssize_t (*body_receiver)
++		(void *struct_key, const void *chunk_buf, size_t chunk_size,
++			int have_more)
++	);
++
++
++/*
++ * Fetch the next XER (XML) token from the stream.
++ * The function returns the number of bytes occupied by the chunk type,
++ * returned in the _ch_type. The _ch_type is only set (and valid) when
++ * the return value is greater than 0.
++ */
++  typedef enum pxer_chunk_type {
++	PXER_TAG,	/* Complete XER tag */
++	PXER_TEXT,	/* Plain text between XER tags */
++	PXER_COMMENT	/* A comment, may be part of */
++  } pxer_chunk_type_e;
++ssize_t xer_next_token(int *stateContext,
++	const void *buffer, size_t size, pxer_chunk_type_e *_ch_type);
++
++/*
++ * This function checks the buffer against the tag name is expected to occur.
++ */
++  typedef enum xer_check_tag {
++	XCT_BROKEN	= 0,	/* The tag is broken */
++	XCT_OPENING	= 1,	/* This is the <opening> tag */
++	XCT_CLOSING	= 2,	/* This is the </closing> tag */
++	XCT_BOTH	= 3,	/* This is the <modified/> tag */
++	XCT__UNK__MASK	= 4,	/* Mask of everything unexpected */
++	XCT_UNKNOWN_OP	= 5,	/* Unexpected <opening> tag */
++	XCT_UNKNOWN_CL	= 6,	/* Unexpected </closing> tag */
++	XCT_UNKNOWN_BO	= 7	/* Unexpected <modified/> tag */
++  } xer_check_tag_e;
++xer_check_tag_e xer_check_tag(const void *buf_ptr, int size,
++		const char *need_tag);
++
++/*
++ * Check whether this buffer consists of entirely XER whitespace characters.
++ * RETURN VALUES:
++ * 1:	Whitespace or empty string
++ * 0:	Non-whitespace
++ */
++int xer_is_whitespace(const void *chunk_buf, size_t chunk_size);
++
++/*
++ * Skip the series of anticipated extensions.
++ */
++int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _XER_DECODER_H_ */
+diff --git a/asn1/asn1c/xer_encoder.c b/asn1/asn1c/xer_encoder.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..aa7cf040ad874dc1f8bfd8e353c3061b71493fdb
+--- /dev/null
++++ b/asn1/asn1c/xer_encoder.c
+@@ -0,0 +1,67 @@
++/*-
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_internal.h>
++#include <stdio.h>
++#include <errno.h>
++
++/*
++ * The XER encoder of any type. May be invoked by the application.
++ */
++asn_enc_rval_t
++xer_encode(asn_TYPE_descriptor_t *td, void *sptr,
++	enum xer_encoder_flags_e xer_flags,
++		asn_app_consume_bytes_f *cb, void *app_key) {
++	asn_enc_rval_t er, tmper;
++	const char *mname;
++	size_t mlen;
++	int xcan = (xer_flags & XER_F_CANONICAL) ? 1 : 2;
++
++	if(!td || !sptr) goto cb_failed;
++
++	mname = td->xml_tag;
++	mlen = strlen(mname);
++
++	_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
++
++	tmper = td->xer_encoder(td, sptr, 1, xer_flags, cb, app_key);
++	if(tmper.encoded == -1) return tmper;
++
++	_ASN_CALLBACK3("</", 2, mname, mlen, ">\n", xcan);
++
++	er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded;
++
++	_ASN_ENCODED_OK(er);
++cb_failed:
++	_ASN_ENCODE_FAILED;
++}
++
++/*
++ * This is a helper function for xer_fprint, which directs all incoming data
++ * into the provided file descriptor.
++ */
++static int
++xer__print2fp(const void *buffer, size_t size, void *app_key) {
++	FILE *stream = (FILE *)app_key;
++
++	if(fwrite(buffer, 1, size, stream) != size)
++		return -1;
++
++	return 0;
++}
++
++int
++xer_fprint(FILE *stream, asn_TYPE_descriptor_t *td, void *sptr) {
++	asn_enc_rval_t er;
++
++	if(!stream) stream = stdout;
++	if(!td || !sptr)
++		return -1;
++
++	er = xer_encode(td, sptr, XER_F_BASIC, xer__print2fp, stream);
++	if(er.encoded == -1)
++		return -1;
++
++	return fflush(stream);
++}
+diff --git a/asn1/asn1c/xer_encoder.h b/asn1/asn1c/xer_encoder.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..055e73c0c8b0dfd330c8d3f80c6d2b02270b3100
+--- /dev/null
++++ b/asn1/asn1c/xer_encoder.h
+@@ -0,0 +1,59 @@
++/*-
++ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_XER_ENCODER_H_
++#define	_XER_ENCODER_H_
++
++#include <asn_application.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct asn_TYPE_descriptor_s;	/* Forward declaration */
++
++/* Flags used by the xer_encode() and (*xer_type_encoder_f), defined below */
++enum xer_encoder_flags_e {
++	/* Mode of encoding */
++	XER_F_BASIC	= 0x01,	/* BASIC-XER (pretty-printing) */
++	XER_F_CANONICAL	= 0x02	/* Canonical XER (strict rules) */
++};
++
++/*
++ * The XER encoder of any type. May be invoked by the application.
++ */
++asn_enc_rval_t xer_encode(struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr,	/* Structure to be encoded */
++		enum xer_encoder_flags_e xer_flags,
++		asn_app_consume_bytes_f *consume_bytes_cb,
++		void *app_key		/* Arbitrary callback argument */
++	);
++
++/*
++ * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
++ * output into the chosen file pointer.
++ * RETURN VALUES:
++ * 	 0: The structure is printed.
++ * 	-1: Problem printing the structure.
++ * WARNING: No sensible errno value is returned.
++ */
++int xer_fprint(FILE *stream, struct asn_TYPE_descriptor_s *td, void *sptr);
++
++/*
++ * Type of the generic XER encoder.
++ */
++typedef asn_enc_rval_t (xer_type_encoder_f)(
++		struct asn_TYPE_descriptor_s *type_descriptor,
++		void *struct_ptr,	/* Structure to be encoded */
++		int ilevel,		/* Level of indentation */
++		enum xer_encoder_flags_e xer_flags,
++		asn_app_consume_bytes_f *consume_bytes_cb,	/* Callback */
++		void *app_key		/* Arbitrary callback argument */
++	);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _XER_ENCODER_H_ */
+diff --git a/asn1/asn1c/xer_support.c b/asn1/asn1c/xer_support.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..9e34e6923467a436e20690633c4091b6db4683cd
+--- /dev/null
++++ b/asn1/asn1c/xer_support.c
+@@ -0,0 +1,233 @@
++/*
++ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
++ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
++ * 	All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#include <asn_system.h>
++#include <xer_support.h>
++
++/* Parser states */
++typedef enum {
++	ST_TEXT,
++	ST_TAG_START,
++	ST_TAG_BODY,
++	ST_TAG_QUOTE_WAIT,
++	ST_TAG_QUOTED_STRING,
++	ST_TAG_UNQUOTED_STRING,
++	ST_COMMENT_WAIT_DASH1,	/* "<!--"[1] */
++	ST_COMMENT_WAIT_DASH2,	/* "<!--"[2] */
++	ST_COMMENT,
++	ST_COMMENT_CLO_DASH2,	/* "-->"[0] */
++	ST_COMMENT_CLO_RT	/* "-->"[1] */
++} pstate_e;
++
++static pxml_chunk_type_e final_chunk_type[] = {
++	PXML_TEXT,
++	PXML_TAG_END,
++	PXML_COMMENT_END,
++	PXML_TAG_END,
++	PXML_COMMENT_END,
++};
++
++
++static int
++_charclass[256] = {
++	0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0,
++	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
++	1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
++	2,2,2,2,2,2,2,2, 2,2,0,0,0,0,0,0,	/* 01234567 89       */
++	0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,	/*  ABCDEFG HIJKLMNO */
++	3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0,	/* PQRSTUVW XYZ      */
++	0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,	/*  abcdefg hijklmno */
++	3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0	/* pqrstuvw xyz      */
++};
++#define WHITESPACE(c)	(_charclass[(unsigned char)(c)] == 1)
++#define ALNUM(c)	(_charclass[(unsigned char)(c)] >= 2)
++#define ALPHA(c)	(_charclass[(unsigned char)(c)] == 3)
++
++/* Aliases for characters, ASCII/UTF-8 */
++#define	EXCLAM	0x21	/* '!' */
++#define	CQUOTE	0x22	/* '"' */
++#define	CDASH	0x2d	/* '-' */
++#define	CSLASH	0x2f	/* '/' */
++#define	LANGLE	0x3c	/* '<' */
++#define	CEQUAL	0x3d	/* '=' */
++#define	RANGLE	0x3e	/* '>' */
++#define	CQUEST	0x3f	/* '?' */
++
++/* Invoke token callback */
++#define	TOKEN_CB_CALL(type, _ns, _current_too, _final) do {	\
++		int _ret;					\
++		pstate_e ns  = _ns;				\
++		ssize_t _sz = (p - chunk_start) + _current_too;	\
++		if (!_sz) {					\
++			/* Shortcut */				\
++			state = _ns;				\
++			break;					\
++		}						\
++		_ret = cb(type, chunk_start, _sz, key);		\
++		if(_ret < _sz) {				\
++			if(_current_too && _ret == -1)		\
++				state = ns;			\
++			goto finish;				\
++		}						\
++		chunk_start = p + _current_too;			\
++		state = ns;					\
++	} while(0)
++
++#define TOKEN_CB(_type, _ns, _current_too)			\
++	TOKEN_CB_CALL(_type, _ns, _current_too, 0)
++
++#define TOKEN_CB_FINAL(_type, _ns, _current_too)		\
++	TOKEN_CB_CALL(final_chunk_type[_type], _ns, _current_too, 1)
++
++/*
++ * Parser itself
++ */
++ssize_t pxml_parse(int *stateContext, const void *xmlbuf, size_t size, pxml_callback_f *cb, void *key) {
++	pstate_e state = (pstate_e)*stateContext;
++	const char *chunk_start = (const char *)xmlbuf;
++	const char *p = chunk_start;
++	const char *end = p + size;
++
++	for(; p < end; p++) {
++	  int C = *(const unsigned char *)p;
++	  switch(state) {
++	  case ST_TEXT:
++		/*
++		 * Initial state: we're in the middle of some text,
++		 * or just have started.
++		 */
++		if (C == LANGLE) 
++			/* We're now in the tag, probably */
++			TOKEN_CB(PXML_TEXT, ST_TAG_START, 0);
++		break;
++	  case ST_TAG_START:
++		if (ALPHA(C) || (C == CSLASH))
++			state = ST_TAG_BODY;
++		else if (C == EXCLAM)
++			state = ST_COMMENT_WAIT_DASH1;
++		else 
++			/*
++			 * Not characters and not whitespace.
++			 * Must be something like "3 < 4".
++			 */
++			TOKEN_CB(PXML_TEXT, ST_TEXT, 1);/* Flush as data */
++		break;
++	  case ST_TAG_BODY:
++		switch(C) {
++		case RANGLE:
++			/* End of the tag */
++			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
++			break;
++		case LANGLE:
++			/*
++			 * The previous tag wasn't completed, but still
++			 * recognized as valid. (Mozilla-compatible)
++			 */
++			TOKEN_CB_FINAL(PXML_TAG, ST_TAG_START, 0);	
++			break;
++		case CEQUAL:
++			state = ST_TAG_QUOTE_WAIT;
++			break;
++		}
++		break;
++	  case ST_TAG_QUOTE_WAIT:
++		/*
++		 * State after the equal sign ("=") in the tag.
++		 */
++		switch(C) {
++		case CQUOTE:
++			state = ST_TAG_QUOTED_STRING;
++			break;
++		case RANGLE:
++			/* End of the tag */
++			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
++			break;
++		default:
++			if(!WHITESPACE(C))
++				/* Unquoted string value */
++				state = ST_TAG_UNQUOTED_STRING;
++		}
++		break;
++	  case ST_TAG_QUOTED_STRING:
++		/*
++		 * Tag attribute's string value in quotes.
++		 */
++		if(C == CQUOTE) {
++			/* Return back to the tag state */
++			state = ST_TAG_BODY;
++		}
++		break;
++	  case ST_TAG_UNQUOTED_STRING:
++		if(C == RANGLE) {
++			/* End of the tag */
++			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
++		} else if(WHITESPACE(C)) {
++			/* Return back to the tag state */
++			state = ST_TAG_BODY;
++		}
++		break;
++	  case ST_COMMENT_WAIT_DASH1:
++		if(C == CDASH) {
++			state = ST_COMMENT_WAIT_DASH2;
++		} else {
++			/* Some ordinary tag. */
++			state = ST_TAG_BODY;
++		}
++		break;
++	  case ST_COMMENT_WAIT_DASH2:
++		if(C == CDASH) {
++			/* Seen "<--" */
++			state = ST_COMMENT;
++		} else {
++			/* Some ordinary tag */
++			state = ST_TAG_BODY;
++		}
++		break;
++	  case ST_COMMENT:
++		if(C == CDASH) {
++			state = ST_COMMENT_CLO_DASH2;
++		}
++		break;
++	  case ST_COMMENT_CLO_DASH2:
++		if(C == CDASH) {
++			state = ST_COMMENT_CLO_RT;
++		} else {
++			/* This is not an end of a comment */
++			state = ST_COMMENT;
++		}
++		break;
++	  case ST_COMMENT_CLO_RT:
++		if(C == RANGLE) {
++			TOKEN_CB_FINAL(PXML_COMMENT, ST_TEXT, 1);
++		} else if(C == CDASH) {
++			/* Maintain current state, still waiting for '>' */
++		} else {
++			state = ST_COMMENT;
++		}
++		break;
++	  } /* switch(*ptr) */
++	} /* for() */
++
++	/*
++	 * Flush the partially processed chunk, state permitting.
++	 */
++	if(p - chunk_start) {
++		switch (state) {
++		case ST_COMMENT:
++			TOKEN_CB(PXML_COMMENT, state, 0);
++			break;
++		case ST_TEXT:
++			TOKEN_CB(PXML_TEXT, state, 0);
++			break;
++		default: break;	/* a no-op */
++		}
++	}
++
++finish:
++	*stateContext = (int)state;
++	return chunk_start - (const char *)xmlbuf;
++}
++
+diff --git a/asn1/asn1c/xer_support.h b/asn1/asn1c/xer_support.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..8b01944ab584c4bca90139c4b322fa5103030f49
+--- /dev/null
++++ b/asn1/asn1c/xer_support.h
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
++ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
++ * Redistribution and modifications are permitted subject to BSD license.
++ */
++#ifndef	_XER_SUPPORT_H_
++#define	_XER_SUPPORT_H_
++
++#include <asn_system.h>		/* Platform-specific types */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Types of data transferred to the application.
++ */
++typedef enum {
++	PXML_TEXT,	/* Plain text between XML tags. */
++	PXML_TAG,	/* A tag, starting with '<'. */
++	PXML_COMMENT,	/* An XML comment, including "<!--" and "-->". */
++	/* 
++	 * The following chunk types are reported if the chunk
++	 * terminates the specified XML element.
++	 */
++	PXML_TAG_END,		/* Tag ended */
++	PXML_COMMENT_END	/* Comment ended */
++} pxml_chunk_type_e;
++
++/*
++ * Callback function that is called by the parser when parsed data is
++ * available. The _opaque is the pointer to a field containing opaque user 
++ * data specified in pxml_create() call. The chunk type is _type and the text 
++ * data is the piece of buffer identified by _bufid (as supplied to
++ * pxml_feed() call) starting at offset _offset and of _size bytes size. 
++ * The chunk is NOT '\0'-terminated.
++ */
++typedef int (pxml_callback_f)(pxml_chunk_type_e _type,
++	const void *_chunk_data, size_t _chunk_size, void *_key);
++
++/*
++ * Parse the given buffer as it were a chunk of XML data.
++ * Invoke the specified callback each time the meaninful data is found.
++ * This function returns number of bytes consumed from the bufer.
++ * It will always be lesser than or equal to the specified _size.
++ * The next invocation of this function must account the difference.
++ */
++ssize_t pxml_parse(int *_stateContext, const void *_buf, size_t _size,
++	pxml_callback_f *cb, void *_key);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* _XER_SUPPORT_H_ */
+diff --git a/asn1/configure.ac b/asn1/configure.ac
+new file mode 100644
+index 0000000000000000000000000000000000000000..c3e398ea20d4112ed8308ba5eb822ab22d256436
+--- /dev/null
++++ b/asn1/configure.ac
+@@ -0,0 +1,24 @@
++AC_PREREQ(2.59)
++m4_include(../version.m4)
++AC_INIT([ipa-server],
++        IPA_VERSION,
++        [https://hosted.fedoraproject.org/projects/freeipa/newticket])
++
++AC_CONFIG_HEADERS([config.h])
++AC_PROG_CC_C99
++AC_PROG_LIBTOOL
++
++AM_INIT_AUTOMAKE([foreign])
++
++AM_MAINTAINER_MODE
++
++AC_SUBST(VERSION)
++
++# Files
++
++AC_CONFIG_FILES([
++    Makefile
++    asn1c/Makefile
++])
++
++AC_OUTPUT
+diff --git a/asn1/ipa_asn1.c b/asn1/ipa_asn1.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..50851a804f59bdb3fcb9ba832b093860d914452d
+--- /dev/null
++++ b/asn1/ipa_asn1.c
+@@ -0,0 +1,229 @@
++#include <stdbool.h>
++#include <sys/types.h>
++#include "ipa_asn1.h"
++#include "GetKeytabControl.h"
++
++static bool encode_GetKeytabControl(GetKeytabControl_t *gkctrl,
++                                    void **buf, size_t *len)
++{
++    asn_enc_rval_t rval;
++    char *buffer = NULL;
++    size_t buflen;
++    bool ret = false;
++
++    /* dry run to compute the size */
++    rval = der_encode(&asn_DEF_GetKeytabControl, gkctrl, NULL, NULL);
++    if (rval.encoded == -1) goto done;
++
++    buflen = rval.encoded;
++    buffer = malloc(buflen);
++    if (!buffer) goto done;
++
++    /* now for real */
++    rval = der_encode_to_buffer(&asn_DEF_GetKeytabControl,
++                                gkctrl, buffer, buflen);
++    if (rval.encoded == -1) goto done;
++
++    *buf = buffer;
++    *len = buflen;
++    ret = true;
++
++done:
++    if (!ret) {
++        free(buffer);
++    }
++    return ret;
++}
++
++bool ipaasn1_enc_getkt(bool newkt, const char *princ, const char *pwd,
++                       long *etypes, int numtypes, void **buf, size_t *len)
++{
++    GetKeytabControl_t gkctrl = { 0 };
++    bool ret = false;
++
++    if (newkt) {
++        gkctrl.present = GetKeytabControl_PR_newkeys;
++        if (OCTET_STRING_fromString(&gkctrl.choice.newkeys.serviceIdentity,
++                                    princ) != 0) goto done;
++
++        for (int i = 0; i < numtypes; i++) {
++            long *tmp;
++            tmp = malloc(sizeof(long));
++            if (!tmp) goto done;
++            *tmp = etypes[i];
++            ASN_SEQUENCE_ADD(&gkctrl.choice.newkeys.enctypes.list, tmp);
++        }
++
++        if (pwd) {
++            gkctrl.choice.newkeys.password =
++                OCTET_STRING_new_fromBuf(&asn_DEF_OCTET_STRING, pwd, -1);
++            if (!gkctrl.choice.newkeys.password) goto done;
++        }
++    } else {
++        gkctrl.present = GetKeytabControl_PR_curkeys;
++        if (OCTET_STRING_fromString(&gkctrl.choice.curkeys.serviceIdentity,
++                                    princ) != 0) goto done;
++    }
++
++    ret = encode_GetKeytabControl(&gkctrl, buf, len);
++
++done:
++    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetKeytabControl, &gkctrl);
++    return ret;
++}
++
++bool ipaasn1_enc_getktreply(int kvno, struct keys_container *keys,
++                            void **buf, size_t *len)
++{
++    GetKeytabControl_t gkctrl = { 0 };
++    bool ret = false;
++
++    gkctrl.present = GetKeytabControl_PR_reply;
++    gkctrl.choice.reply.newkvno = kvno;
++
++    for (int i = 0; i < keys->nkeys; i++) {
++        KrbKey_t *KK;
++        KK = calloc(1, sizeof(KrbKey_t));
++        if (!KK) goto done;
++        KK->key.type = keys->ksdata[i].key.enctype;
++        KK->key.value.buf = malloc(keys->ksdata[i].key.length);
++        if (!KK->key.value.buf) goto done;
++        memcpy(KK->key.value.buf,
++               keys->ksdata[i].key.contents, keys->ksdata[i].key.length);
++        KK->key.value.size = keys->ksdata[i].key.length;
++
++        if (keys->ksdata[i].salt.data != NULL) {
++            KK->salt = calloc(1, sizeof(TypeValuePair_t));
++            if (!KK->salt) goto done;
++            KK->salt->type = keys->ksdata[i].salttype;
++            KK->salt->value.buf = malloc(keys->ksdata[i].salt.length);
++            if (!KK->salt->value.buf) goto done;
++            memcpy(KK->salt->value.buf,
++                   keys->ksdata[i].salt.data, keys->ksdata[i].salt.length);
++            KK->salt->value.size = keys->ksdata[i].salt.length;
++        }
++
++        /* KK->key.s2kparams not used for now */
++
++        ASN_SEQUENCE_ADD(&gkctrl.choice.reply.keys.list, KK);
++    }
++
++    ret = encode_GetKeytabControl(&gkctrl, buf, len);
++
++done:
++    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetKeytabControl, &gkctrl);
++    return ret;
++}
++
++static GetKeytabControl_t *decode_GetKeytabControl(void *buf, size_t len)
++{
++    GetKeytabControl_t *gkctrl = NULL;
++    asn_dec_rval_t rval;
++
++    rval = ber_decode(NULL, &asn_DEF_GetKeytabControl,
++                      (void **)&gkctrl, buf, len);
++    if (rval.code == RC_OK) {
++        return gkctrl;
++    }
++    return NULL;
++}
++
++bool ipaasn1_dec_getkt(void *buf, size_t len, bool *newkt,
++                       char **princ, char **pwd, long **etypes, int *numtypes)
++{
++    GetKeytabControl_t *gkctrl;
++    bool ret = false;
++    int num;
++
++    gkctrl = decode_GetKeytabControl(buf, len);
++    if (!gkctrl) return false;
++
++    switch (gkctrl->present) {
++    case GetKeytabControl_PR_newkeys:
++        *newkt = true;
++        *princ = strndup((char *)gkctrl->choice.newkeys.serviceIdentity.buf,
++                         gkctrl->choice.newkeys.serviceIdentity.size);
++        if (!*princ) goto done;
++
++        num = gkctrl->choice.newkeys.enctypes.list.count;
++        *etypes = malloc(num * sizeof(long));
++        *numtypes = 0;
++        if (!*etypes) goto done;
++        for (int i = 0; i < num; i++) {
++            (*etypes)[i] = *gkctrl->choice.newkeys.enctypes.list.array[i];
++            (*numtypes)++;
++        }
++
++        if (gkctrl->choice.newkeys.password) {
++            *pwd = strndup((char *)gkctrl->choice.newkeys.password->buf,
++                           gkctrl->choice.newkeys.password->size);
++            if (!*pwd) goto done;
++        }
++        break;
++    case GetKeytabControl_PR_curkeys:
++        *newkt = false;
++        *princ = strndup((char *)gkctrl->choice.curkeys.serviceIdentity.buf,
++                         gkctrl->choice.curkeys.serviceIdentity.size);
++        if (!*princ) goto done;
++        break;
++    default:
++        goto done;
++    }
++
++    ret = true;
++
++done:
++    ASN_STRUCT_FREE(asn_DEF_GetKeytabControl, gkctrl);
++    return ret;
++}
++
++bool ipaasn1_dec_getktreply(void *buf, size_t len,
++                            int *kvno, struct keys_container *keys)
++{
++    GetKeytabControl_t *gkctrl;
++    struct KrbKey *KK;
++    bool ret = false;
++    int nkeys;
++
++    gkctrl = decode_GetKeytabControl(buf, len);
++    if (!gkctrl) return false;
++
++    if (gkctrl->present != GetKeytabControl_PR_reply) goto done;
++
++    *kvno = gkctrl->choice.reply.newkvno;
++
++    nkeys = gkctrl->choice.reply.keys.list.count;
++
++    keys->nkeys = 0;
++    keys->ksdata = calloc(nkeys, sizeof(struct krb_key_salt));
++    if (!keys->ksdata) goto done;
++
++    for (int i = 0; i < nkeys; i++) {
++        KK = gkctrl->choice.reply.keys.list.array[i];
++        keys->ksdata[i].enctype = KK->key.type;
++        keys->ksdata[i].key.enctype = KK->key.type;
++        keys->ksdata[i].key.contents = malloc(KK->key.value.size);
++        if (!keys->ksdata[i].key.contents) goto done;
++        memcpy(keys->ksdata[i].key.contents,
++               KK->key.value.buf, KK->key.value.size);
++        keys->ksdata[i].key.length = KK->key.value.size;
++
++        if (KK->salt) {
++            keys->ksdata[i].salttype = KK->salt->type;
++            keys->ksdata[i].salt.data = malloc(KK->salt->value.size);
++            if (!keys->ksdata[i].salt.data) goto done;
++            memcpy(keys->ksdata[i].salt.data,
++                   KK->salt->value.buf, KK->salt->value.size);
++            keys->ksdata[i].salt.length = KK->salt->value.size;
++        }
++
++        /* KK->s2kparams is ignored for now */
++        keys->nkeys++;
++    }
++
++    ret = true;
++
++done:
++    ASN_STRUCT_FREE(asn_DEF_GetKeytabControl, gkctrl);
++    return ret;
++}
+diff --git a/asn1/ipa_asn1.h b/asn1/ipa_asn1.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..6ffcc5cc81992966654c21e923a1f8883b32833b
+--- /dev/null
++++ b/asn1/ipa_asn1.h
+@@ -0,0 +1,76 @@
++#ifndef __IPA_ASN1_H_
++#define __IPA_ASN1_H_
++
++#include "ipa_krb5.h"
++
++/**
++ * @brief Encodes a Get Keytab Request Control
++ *
++ * @param newkt     Whether this is a New Key request or a Current Key one
++ * @param princ     The principal the keys belong to (this is required)
++ * @param pwd       Optional, only for New Key reqs, the password to use to
++ *                  create the new keys
++ * @param etypes    Optional, only for New Key reqs, list of desired
++ *                  enctypes
++ * @param numtypes  Optional, Number of desired enctypes in etypes
++ * @param buf       A void pointer wil lcontain pointer to an allocated
++ *                  buffer with the serialized control, must be freed
++ * @param len       Length of the returned buffer
++ *
++ * @return          True on success or False on failure
++ */
++bool ipaasn1_enc_getkt(bool newkt, const char *princ, const char *pwd,
++                       long *etypes, int numtypes, void **buf, size_t *len);
++
++/**
++ * @brief Encodes a Get Keytab Reply Control
++ *
++ * @param kvno      The new key version number
++ * @param keys      A set of keys to return to the caller
++ * @param buf       A void pointer wil lcontain pointer to an allocated
++ *                  buffer with the serialized control, must be freed
++ * @param len       Length of the returned buffer
++ *
++ * @return          True on success or False on failure
++ */
++bool ipaasn1_enc_getktreply(int kvno, struct keys_container *keys,
++                            void **buf, size_t *len);
++
++/**
++ * @brief Decodes a Get Keytab Requst Control
++ *
++ * @param buf       A pointer to the serialized buffer
++ * @param len       The lenght of the buffer
++ * @param newkt     Returns whether this is a New Key or Current Key request
++ * @param princ     Returns the principal the keys belong to.
++ * @param pwd       Optional: The password to use to create keys
++ * @param etypes    Optional: The desired enctypes
++ * @param numtypes  Optional: Number of desired enctypes in etypes
++ *
++ * @return          True on success or False on failure
++ *
++ * NOTE: princ, pwd, etypes and numtypes should be zeroed before being
++ *       passed in input, and the caller may need to free them even in
++ *       case of failure.
++ */
++bool ipaasn1_dec_getkt(void *buf, size_t len, bool *newkt,
++                       char **princ, char **pwd,
++                       long **etypes, int *numtypes);
++
++/**
++ * @brief Decodes a Get Keytab Reply Control
++ *
++ * @param buf       A pointer to the serialized buffer
++ * @param len       The lenght of the buffer
++ * @param kvno      The new key version number
++ * @param keys      A set of keys generated by the server
++ *
++ * @return          True on success or False on failure
++ *
++ * NOTE: keys should be a zeroed structure and the caller may need to free
++ *       it even in case of failure.
++ */
++bool ipaasn1_dec_getktreply(void *buf, size_t len,
++                            int *kvno, struct keys_container *keys);
++
++#endif /* __IPA_ASN1_H_ */
+diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
+index 1e036e4f8eb8f9a92af6fb6190f507e02ae38934..7b877aa665dd6cb4e0c1cf9d8153319cc8f61a20 100644
+--- a/util/ipa_krb5.h
++++ b/util/ipa_krb5.h
+@@ -1,6 +1,7 @@
+ #ifndef __IPA_KRB5_H_
+ #define __IPA_KRB5_H_
+ 
++#include <lber.h>
+ #include <krb5/krb5.h>
+ #include <kdb.h>
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0044-Remove-sourcehostcategory-from-the-default-HBAC-rule.patch b/SOURCES/0044-Remove-sourcehostcategory-from-the-default-HBAC-rule.patch
deleted file mode 100644
index b2822e3..0000000
--- a/SOURCES/0044-Remove-sourcehostcategory-from-the-default-HBAC-rule.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From b3d761fb187f08d910df0bee420e9ed3b23d035f Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Thu, 6 Feb 2014 12:33:43 +0100
-Subject: [PATCH 44/46] Remove sourcehostcategory from the default HBAC rule.
-
-https://fedorahosted.org/freeipa/ticket/4158
-
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- install/share/default-hbac.ldif | 1 -
- ipalib/plugins/hbacrule.py      | 2 +-
- 2 files changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/install/share/default-hbac.ldif b/install/share/default-hbac.ldif
-index b7b6ba28453b867fa142d038b1e35e162dac800f..52fd30ec9ac4e01f68d9cc6a94fb4cc15177e10b 100644
---- a/install/share/default-hbac.ldif
-+++ b/install/share/default-hbac.ldif
-@@ -7,7 +7,6 @@ dn:
- accessruletype: allow
- usercategory: all
- hostcategory: all
--sourcehostcategory: all
- servicecategory: all
- ipaenabledflag: TRUE
- description: Allow all users to access any host from any host
-diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py
-index 5cc8bc1a34de38ce5c5f6faf8ea24ee6873bf0b7..daf165346ba67c6525f7ab2034519c7a03fd3394 100644
---- a/ipalib/plugins/hbacrule.py
-+++ b/ipalib/plugins/hbacrule.py
-@@ -118,7 +118,7 @@ class hbacrule(LDAPObject):
-     default_attributes = [
-         'cn', 'ipaenabledflag',
-         'description', 'usercategory', 'hostcategory',
--        'sourcehostcategory', 'servicecategory', 'ipaenabledflag',
-+        'servicecategory', 'ipaenabledflag',
-         'memberuser', 'sourcehost', 'memberhost', 'memberservice',
-         'memberhostgroup', 'externalhost',
-     ]
--- 
-1.8.5.3
-
diff --git a/SOURCES/0045-DNS-classless-support-for-reverse-domains.patch b/SOURCES/0045-DNS-classless-support-for-reverse-domains.patch
deleted file mode 100644
index 3611dcc..0000000
--- a/SOURCES/0045-DNS-classless-support-for-reverse-domains.patch
+++ /dev/null
@@ -1,229 +0,0 @@
-From c884a56c2d9996fc54c054c78d56eae50f696997 Mon Sep 17 00:00:00 2001
-From: Martin Basti <mbasti@redhat.com>
-Date: Fri, 31 Jan 2014 15:42:31 +0100
-Subject: [PATCH 45/46] DNS classless support for reverse domains
-
-Now users can add reverse zones in classless form:
-0/25.1.168.192.in-addr.arpa.
-0-25.1.168.192.in-addr.arpa.
-
-128/25 NS ns.example.com.
-10 CNAME 10.128/25.1.168.192.in-addr.arpa.
-
-Ticket: https://fedorahosted.org/freeipa/ticket/4143
-Reviewed-By: Jan Cholasta <jcholast@redhat.com>
----
- ipalib/plugins/dns.py | 45 +++++++++++++++++++++++++++----------
- ipalib/util.py        | 61 ++++++++++++++++++++++++++++++---------------------
- 2 files changed, 70 insertions(+), 36 deletions(-)
-
-diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
-index 94ae92ba5d1ae42e31ebb6100c743a2334f29e70..a78dc9e90a04a00a731541f8a04db5c0f0dd12bb 100644
---- a/ipalib/plugins/dns.py
-+++ b/ipalib/plugins/dns.py
-@@ -368,25 +368,31 @@ def _normalize_bind_aci(bind_acis):
-     acis += u';'
-     return acis
- 
--def _bind_hostname_validator(ugettext, value):
-+def _bind_hostname_validator(ugettext, value, allow_slash=False):
-     if value == _dns_zone_record:
-         return
-     try:
-         # Allow domain name which is not fully qualified. These are supported
-         # in bind and then translated as <non-fqdn-name>.<domain>.
--        validate_hostname(value, check_fqdn=False, allow_underscore=True)
-+        validate_hostname(value, check_fqdn=False, allow_underscore=True, allow_slash=allow_slash)
-     except ValueError, e:
-         return _('invalid domain-name: %s') \
-             % unicode(e)
- 
-     return None
- 
-+def _bind_cname_hostname_validator(ugettext, value):
-+    """
-+    Validator for CNAME allows classless domain names (25/0.0.10.in-addr.arpa.)
-+    """
-+    return _bind_hostname_validator(ugettext, value, allow_slash=True)
-+
- def _dns_record_name_validator(ugettext, value):
-     if value == _dns_zone_record:
-         return
- 
-     try:
--        map(lambda label:validate_dns_label(label, allow_underscore=True), \
-+        map(lambda label:validate_dns_label(label, allow_underscore=True, allow_slash=True), \
-             value.split(u'.'))
-     except ValueError, e:
-         return unicode(e)
-@@ -411,7 +417,10 @@ def _validate_bind_forwarder(ugettext, forwarder):
- 
- def _domain_name_validator(ugettext, value):
-     try:
--        validate_domain_name(value)
-+        #classless reverse zones can contain slash '/'
-+        normalized_zone = normalize_zone(value)
-+        validate_domain_name(value, allow_slash=zone_is_reverse(normalized_zone))
-+
-     except ValueError, e:
-         return unicode(e)
- 
-@@ -939,7 +948,7 @@ class CNAMERecord(DNSRecord):
-     rfc = 1035
-     parts = (
-         Str('hostname',
--            _bind_hostname_validator,
-+            _bind_cname_hostname_validator,
-             label=_('Hostname'),
-             doc=_('A hostname which this alias hostname points to'),
-         ),
-@@ -960,7 +969,7 @@ class DNAMERecord(DNSRecord):
-     rfc = 2672
-     parts = (
-         Str('target',
--            _bind_hostname_validator,
-+            _bind_cname_hostname_validator,
-             label=_('Target'),
-         ),
-     )
-@@ -2119,6 +2128,14 @@ class dnsrecord(LDAPObject):
-                            doc=_('Parse all raw DNS records and return them in a structured way'),
-                            )
- 
-+    def _idnsname_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
-+        if not self.is_pkey_zone_record(*keys):
-+            zone, addr = normalize_zone(keys[-2]), keys[-1]
-+            try:
-+                validate_domain_name(addr, allow_underscore=True, allow_slash=zone_is_reverse(zone))
-+            except ValueError, e:
-+                raise errors.ValidationError(name='idnsname', error=unicode(e))
-+
-     def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
-         assert isinstance(dn, DN)
-         nsrecords = entry_attrs.get('nsrecord')
-@@ -2132,6 +2149,7 @@ def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
-         ptrrecords = entry_attrs.get('ptrrecord')
-         if ptrrecords is None:
-             return
-+
-         zone = keys[-2]
-         if self.is_pkey_zone_record(*keys):
-             addr = u''
-@@ -2150,11 +2168,16 @@ def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
-                     error=unicode(_('Reverse zone for PTR record should be a sub-zone of one the following fully qualified domains: %s') % allowed_zones))
- 
-         addr_len = len(addr.split('.')) if addr else 0
--        ip_addr_comp_count = addr_len + len(zone.split('.'))
--        if ip_addr_comp_count != zone_len:
--            raise errors.ValidationError(name='ptrrecord',
--                error=unicode(_('Reverse zone %(name)s requires exactly %(count)d IP address components, %(user_count)d given')
--                % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count)))
-+
-+        #Classless zones (0/25.0.0.10.in-addr.arpa.) -> skip check
-+        #zone has to be checked without reverse domain suffix (in-addr.arpa.)
-+        if ('/' not in addr and '/' not in zone and
-+            '-' not in addr and '-' not in zone):
-+            ip_addr_comp_count = addr_len + len(zone.split('.'))
-+            if ip_addr_comp_count != zone_len:
-+                raise errors.ValidationError(name='ptrrecord',
-+                      error=unicode(_('Reverse zone %(name)s requires exactly %(count)d IP address components, %(user_count)d given')
-+                      % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count)))
- 
-     def run_precallback_validators(self, dn, entry_attrs, *keys, **options):
-         assert isinstance(dn, DN)
-diff --git a/ipalib/util.py b/ipalib/util.py
-index 3c52e4fd9a3e08d160dd4ae7076590be8b869d2c..17851294a78507aba7035390c3695184b7d641b1 100644
---- a/ipalib/util.py
-+++ b/ipalib/util.py
-@@ -215,34 +215,45 @@ def normalize_zone(zone):
-     else:
-         return zone
- 
--def validate_dns_label(dns_label, allow_underscore=False):
--    label_chars = r'a-z0-9'
--    underscore_err_msg = ''
--    if allow_underscore:
--        label_chars += "_"
--        underscore_err_msg = u' _,'
--    label_regex = r'^[%(chars)s]([%(chars)s-]?[%(chars)s])*$' % dict(chars=label_chars)
--    regex = re.compile(label_regex, re.IGNORECASE)
--
--    if not dns_label:
--        raise ValueError(_('empty DNS label'))
--
--    if len(dns_label) > 63:
--        raise ValueError(_('DNS label cannot be longer that 63 characters'))
--
--    if not regex.match(dns_label):
--        raise ValueError(_('only letters, numbers,%(underscore)s and - are allowed. ' \
--                           'DNS label may not start or end with -') \
--                           % dict(underscore=underscore_err_msg))
--
--def validate_domain_name(domain_name, allow_underscore=False):
-+
-+def validate_dns_label(dns_label, allow_underscore=False, allow_slash=False):
-+     base_chars = 'a-z0-9'
-+     extra_chars = ''
-+     middle_chars = ''
-+
-+     if allow_underscore:
-+         extra_chars += '_'
-+     if allow_slash:
-+         middle_chars += '/'
-+
-+     middle_chars = middle_chars + '-' #has to be always the last in the regex [....-]
-+
-+     label_regex = r'^[%(base)s%(extra)s]([%(base)s%(extra)s%(middle)s]?[%(base)s%(extra)s])*$' \
-+         % dict(base=base_chars, extra=extra_chars, middle=middle_chars)
-+     regex = re.compile(label_regex, re.IGNORECASE)
-+
-+     if not dns_label:
-+         raise ValueError(_('empty DNS label'))
-+
-+     if len(dns_label) > 63:
-+         raise ValueError(_('DNS label cannot be longer that 63 characters'))
-+
-+     if not regex.match(dns_label):
-+         chars = ', '.join("'%s'" % c for c in extra_chars + middle_chars)
-+         chars2 = ', '.join("'%s'" % c for c in middle_chars)
-+         raise ValueError(_("only letters, numbers, %(chars)s are allowed. " \
-+                            "DNS label may not start or end with %(chars2)s") \
-+                            % dict(chars=chars, chars2=chars2))
-+
-+
-+def validate_domain_name(domain_name, allow_underscore=False, allow_slash=False):
-     if domain_name.endswith('.'):
-         domain_name = domain_name[:-1]
- 
-     domain_name = domain_name.split(".")
- 
-     # apply DNS name validator to every name part
--    map(lambda label:validate_dns_label(label,allow_underscore), domain_name)
-+    map(lambda label:validate_dns_label(label, allow_underscore, allow_slash), domain_name)
- 
- 
- def validate_zonemgr(zonemgr):
-@@ -287,7 +298,7 @@ def validate_zonemgr(zonemgr):
-                local_part.split(local_part_sep)):
-         raise ValueError(local_part_errmsg)
- 
--def validate_hostname(hostname, check_fqdn=True, allow_underscore=False):
-+def validate_hostname(hostname, check_fqdn=True, allow_underscore=False, allow_slash=False):
-     """ See RFC 952, 1123
- 
-     :param hostname Checked value
-@@ -305,9 +316,9 @@ def validate_hostname(hostname, check_fqdn=True, allow_underscore=False):
-     if '.' not in hostname:
-         if check_fqdn:
-             raise ValueError(_('not fully qualified'))
--        validate_dns_label(hostname,allow_underscore)
-+        validate_dns_label(hostname, allow_underscore, allow_slash)
-     else:
--        validate_domain_name(hostname,allow_underscore)
-+        validate_domain_name(hostname, allow_underscore, allow_slash)
- 
- def normalize_sshpubkey(value):
-     return SSHPublicKey(value).openssh()
--- 
-1.8.5.3
-
diff --git a/SOURCES/0045-Use-asn1c-helpers-to-encode-decode-the-getkeytab-con.patch b/SOURCES/0045-Use-asn1c-helpers-to-encode-decode-the-getkeytab-con.patch
new file mode 100644
index 0000000..e8c728e
--- /dev/null
+++ b/SOURCES/0045-Use-asn1c-helpers-to-encode-decode-the-getkeytab-con.patch
@@ -0,0 +1,813 @@
+From 55172f11776453c0f8defb1363dd144b29f181d3 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Mon, 17 Nov 2014 15:19:57 -0500
+Subject: [PATCH] Use asn1c helpers to encode/decode the getkeytab control
+
+Replaces manual encoding with automatically generated code.
+
+Fixes:
+https://fedorahosted.org/freeipa/ticket/4718
+https://fedorahosted.org/freeipa/ticket/4728
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com>
+---
+ Makefile                                           |   1 +
+ daemons/configure.ac                               |   2 +
+ .../ipa-slapi-plugins/ipa-pwd-extop/Makefile.am    |   7 +-
+ .../ipa-pwd-extop/ipa_pwd_extop.c                  | 241 ++++----------------
+ ipa-client/Makefile.am                             |   4 +
+ ipa-client/configure.ac                            |   2 +
+ ipa-client/ipa-getkeytab.c                         | 246 ++++-----------------
+ 7 files changed, 107 insertions(+), 396 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index c1a298f91717246e8dab5e3f0de47d0ac9b2ae35..8fd0c60e392d720f47c8ee7c4b674727dc5eb789 100644
+--- a/Makefile
++++ b/Makefile
+@@ -75,6 +75,7 @@ client: client-autogen
+ 
+ bootstrap-autogen: version-update client-autogen
+ 	@echo "Building IPA $(IPA_VERSION)"
++	cd asn1; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 	cd daemons; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR) --with-openldap; fi
+ 	cd install; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 
+diff --git a/daemons/configure.ac b/daemons/configure.ac
+index bfcdeadcd1dc73762d8c773ee50210d9bdb91e92..e81aa60e381e035aff73bf27475fc0f101a5fbf9 100644
+--- a/daemons/configure.ac
++++ b/daemons/configure.ac
+@@ -5,6 +5,7 @@ AC_INIT([ipa-server],
+         [https://hosted.fedoraproject.org/projects/freeipa/newticket])
+ 
+ AC_CONFIG_HEADERS([config.h])
++AC_CONFIG_SUBDIRS([../asn1])
+ 
+ AM_INIT_AUTOMAKE([foreign])
+ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
+@@ -305,6 +306,7 @@ AC_SUBST(LDFLAGS)
+ 
+ AC_CONFIG_FILES([
+     Makefile
++    ../asn1/Makefile
+     ipa-kdb/Makefile
+     ipa-sam/Makefile
+     ipa-otpd/Makefile
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+index 4cf80ec802b40bb579a44fc9357c6a8119dab577..77beca2da0810ed5507d95b21f99d22f63b05fc1 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+@@ -6,6 +6,7 @@ KRB5_UTIL_DIR = ../../../util
+ KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
+ 		 $(KRB5_UTIL_DIR)/ipa_pwd.c \
+ 		 $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
++ASN1_UTIL_DIR=../../../asn1
+ 
+ AM_CPPFLAGS =							\
+ 	-I.							\
+@@ -13,6 +14,7 @@ AM_CPPFLAGS =							\
+ 	-I$(srcdir)/../libotp					\
+ 	-I$(PLUGIN_COMMON_DIR)					\
+ 	-I$(KRB5_UTIL_DIR)					\
++	-I$(ASN1_UTIL_DIR)					\
+ 	-I$(COMMON_BER_DIR)					\
+ 	-DPREFIX=\""$(prefix)"\" 				\
+ 	-DBINDIR=\""$(bindir)"\"				\
+@@ -38,7 +40,10 @@ AM_LDFLAGS = \
+ # Plugin Binary
+ plugindir = $(libdir)/dirsrv/plugins
+ plugin_LTLIBRARIES = libipa_pwd_extop.la
+-libipa_pwd_extop_la_LIBADD  = $(builddir)/../libotp/libotp.la
++libipa_pwd_extop_la_LIBADD  = \
++	$(builddir)/../libotp/libotp.la \
++	$(ASN1_UTIL_DIR)/libipaasn1.la  \
++	$(NULL)
+ libipa_pwd_extop_la_SOURCES = 		\
+ 	authcfg.c			\
+ 	common.c			\
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+index b87ae0dc7a180008228f31293b49212df80584e8..ceea49cab50b0836c882240f210339e60d26729b 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+@@ -40,6 +40,7 @@
+ #include "ipapwd.h"
+ #include "util.h"
+ #include "authcfg.h"
++#include "ipa_asn1.h"
+ 
+ /*
+  * Password Modify - LDAP Extended Operation.
+@@ -1310,31 +1311,7 @@ free_and_return:
+ 	return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
+ }
+ 
+-/* Format of getkeytab request
+- *
+- * KeytabGetRequest ::= CHOICE {
+- *     newkeys      [0] Newkeys,
+- *     curkeys      [1] CurrentKeys,
+- *     reply        [2] Reply
+- * }
+- *
+- * NewKeys ::= SEQUENCE {
+- *     serviceIdentity [0] OCTET STRING,
+- *     enctypes        [1] SEQUENCE OF Int16
+- *     password        [2] OCTET STRING OPTIONAL,
+- * }
+- *
+- * CurrentKeys ::= SEQUENCE {
+- *     serviceIdentity [0] OCTET STRING,
+- * }
+- */
+-
+-#define GK_REQUEST_NEWKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
+-#define GK_REQUEST_CURKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_SVCNAME_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_ENCTYPES_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_PASSWORD_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
+-
++/* decode a getkeytab control request using libipaasn1 helpers */
+ static int decode_getkeytab_request(struct berval *extop, bool *wantold,
+                                     char **_svcname, char **_password,
+                                     krb5_key_salt_tuple **kenctypes,
+@@ -1342,96 +1319,44 @@ static int decode_getkeytab_request(struct berval *extop, bool *wantold,
+ {
+     int rc = LDAP_OPERATIONS_ERROR;
+     char *err_msg = NULL;
+-    BerElement *ber = NULL;
+-    ber_len_t tlen;
+-    ber_tag_t rtag;
+-    ber_tag_t ttag;
+-    ber_tag_t ctag;
+     char *svcname = NULL;
+     char *password = NULL;
+-    ber_int_t enctype;
++    long *etypes = NULL;
++    int numtypes = 0;
+     krb5_key_salt_tuple *enctypes = NULL;
+-    int num = 0;
+-
+-    ber = ber_init(extop);
+-    if (ber == NULL) {
+-        err_msg = "KeytabGet Request decode failed.\n";
+-        rc = LDAP_PROTOCOL_ERROR;
+-        goto done;
+-    }
+-
+-    /* check this is a request */
+-    rtag = ber_peek_tag(ber, &tlen);
+-    if (rtag != GK_REQUEST_NEWKEYS && rtag != GK_REQUEST_CURKEYS) {
+-        LOG_FATAL("ber_peek_tag failed, wrong request type\n");
+-        err_msg = "Invalid payload.\n";
+-        rc = LDAP_PROTOCOL_ERROR;
+-        goto done;
+-    }
+-
+-    /* ber parse code */
+-    ttag = ber_scanf(ber, "{ta", &ctag, &svcname);
+-    if (ttag == LBER_ERROR || ctag != GKREQ_SVCNAME_TAG) {
+-        LOG_FATAL("ber_scanf failed to decode service name\n");
+-        err_msg = "Invalid payload.\n";
++    bool newkt;
++    bool ret;
++    int i;
++
++    ret = ipaasn1_dec_getkt(extop->bv_val, extop->bv_len, &newkt,
++                            &svcname, &password, &etypes, &numtypes);
++    if (!ret) {
++        err_msg = "Failed to decode GetKeytab Control.\n";
+         rc = LDAP_PROTOCOL_ERROR;
+         goto done;
+     }
+ 
+-    if (rtag == GK_REQUEST_CURKEYS) {
+-        rc = LDAP_SUCCESS;
+-        goto done;
+-    }
+-
+-    ttag = ber_peek_tag(ber, &tlen);
+-    if (ttag != GKREQ_ENCTYPES_TAG) {
+-        LOG_FATAL("ber_peek_tag failed to find enctypes\n");
+-        err_msg = "Invalid payload.\n";
+-        rc = LDAP_PROTOCOL_ERROR;
+-        goto done;
+-    }
+-    ttag = ber_peek_tag(ber, &tlen);
+-    for (num = 0; ttag == LBER_INTEGER; num++) {
+-        if ((num % 10) == 0) {
+-            /* allocate space for at least 10 more enctypes */
+-            enctypes = realloc(enctypes,
+-                               (num + 10) * sizeof(krb5_key_salt_tuple));
++    if (newkt) {
++        if (numtypes) {
++            enctypes = malloc(numtypes * sizeof(krb5_key_salt_tuple));
+             if (!enctypes) {
+                 LOG_FATAL("allocation failed\n");
+                 err_msg = "Internal error\n";
+                 rc = LDAP_OPERATIONS_ERROR;
+                 goto done;
+             }
+-        }
+-
+-        ttag = ber_scanf(ber, "i", &enctype);
+-        if (ttag == LBER_ERROR) {
+-            LOG_FATAL("ber_scanf failed to decode enctype\n");
+-            err_msg = "Invalid payload.\n";
+-            rc = LDAP_PROTOCOL_ERROR;
+-            goto done;
+-        }
+-
+-        enctypes[num].ks_enctype = enctype;
+-        enctypes[num].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
+-        ttag = ber_peek_tag(ber, &tlen);
+-    }
+ 
+-    /* ttag peek done as last step of the previous for loop */
+-    if (ttag == GKREQ_PASSWORD_TAG) {
+-        /* optional password present */
+-        ttag = ber_scanf(ber, "a", &password);
+-        if (ttag == LBER_ERROR) {
+-            LOG_FATAL("ber_scanf failed to decode password\n");
+-            err_msg = "Invalid payload.\n";
+-            rc = LDAP_PROTOCOL_ERROR;
+-            goto done;
++            for (i = 0; i < numtypes; i++) {
++                enctypes[i].ks_enctype = etypes[i];
++                enctypes[i].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
++            }
+         }
+     }
+ 
+     rc = LDAP_SUCCESS;
+ 
+ done:
++    free(etypes);
+     if (rc != LDAP_SUCCESS) {
+         free(password);
+         free(svcname);
+@@ -1440,78 +1365,34 @@ done:
+     } else {
+         *_password = password;
+         *_svcname = svcname;
+-        *wantold = (rtag == GK_REQUEST_CURKEYS);
++        *wantold = (newkt == false);
+         *kenctypes = enctypes;
+-        *num_kenctypes = num;
++        *num_kenctypes = numtypes;
+     }
+-    if (ber) ber_free(ber, 1);
+     return rc;
+ }
+ 
+-/* Format of getkeytab reply
+- *
+- * Reply ::= SEQUENCE {
+- *     new_kvno        Int32
+- *     keys            SEQUENCE OF KrbKey,
+- * }
+- *
+- * KrbKey ::= SEQUENCE {
+- *     key       [0] EncryptionKey,
+- *     salt      [1] KrbSalt OPTIONAL,
+- *     s2kparams [2] OCTET STRING OPTIONAL,
+- * }
+- *
+- * EncryptionKey ::= SEQUENCE {
+- *     keytype   [0] Int32,
+- *     keyvalue  [1] OCTET STRING
+- * }
+- *
+- * KrbSalt ::= SEQUENCE {
+- *     type      [0] Int32,
+- *     salt      [1] OCTET STRING
+- * }
+- */
+-
+-#define GK_REPLY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
+-#define GKREP_KEY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
+-#define GKREP_SALT_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREP_S2KPARAMS_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
+-#define GKREP_KEYTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
+-#define GKREP_KEYVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREP_SALTTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
+-#define GKREP_SALTVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-
+ static int encode_getkeytab_reply(krb5_context krbctx,
+                                   krb5_keyblock *kmkey, int mkvno,
+                                   krb5_key_data *keys, int num_keys,
+                                   struct berval **_bvp)
+ {
+     int rc = LDAP_OPERATIONS_ERROR;
++    struct krb_key_salt ksdata[num_keys];
++    struct keys_container ksc = { num_keys, ksdata };
+     struct berval *bvp = NULL;
+-    BerElement *ber = NULL;
+-    ber_int_t kvno;
+-    krb5_data plain = { 0 };
++    int kvno;
++    bool ret;
+ 
+-    ber = ber_alloc();
+-    if (!ber) {
+-        LOG_OOM();
+-        goto done;
+-    }
++    memset(ksdata, '\0', num_keys * sizeof(struct krb_key_salt));
+ 
+     /* uses last key kvno */
+     kvno = keys[num_keys-1].key_data_kvno;
+ 
+-    rc = ber_printf(ber, "t{i{", GK_REPLY_TAG, kvno);
+-    if (rc == -1) {
+-        rc = LDAP_OPERATIONS_ERROR;
+-        LOG_FATAL("Failed to initiate key buffer\n");
+-        goto done;
+-    }
+-
+     for (int i = 0; i < num_keys; i++) {
+         krb5_enc_data cipher = { 0 };
++        krb5_data plain = { 0 };
+         krb5_int16 plen;
+-        void *p;
+ 
+         /* retrieve plain key */
+         memcpy(&plen, keys[i].key_data_contents[0], 2);
+@@ -1521,13 +1402,12 @@ static int encode_getkeytab_reply(krb5_context krbctx,
+         cipher.kvno = mkvno;
+ 
+         plain.length = le16toh(plen);
+-        p = realloc(plain.data, plain.length);
+-        if (!p) {
++        plain.data = malloc(plain.length);
++        if (!plain.data) {
+             LOG_FATAL("Failed to allocate plain buffer\n");
+             rc = LDAP_OPERATIONS_ERROR;
+             goto done;
+         }
+-        plain.data = p;
+ 
+         rc = krb5_c_decrypt(krbctx, kmkey, 0, 0, &cipher, &plain);
+         if (rc) {
+@@ -1536,68 +1416,37 @@ static int encode_getkeytab_reply(krb5_context krbctx,
+             goto done;
+         }
+ 
+-        rc = ber_printf(ber,
+-                        "{t{tito}",
+-                        GKREP_KEY_TAG,
+-                            GKREP_KEYTYPE_TAG,
+-                                (ber_int_t)keys[i].key_data_type[0],
+-                            GKREP_KEYVALUE_TAG,
+-                                plain.data, (ber_len_t)plain.length);
+-        if (rc == -1) {
+-            LOG_FATAL("Failed to encode key data\n");
+-            rc = LDAP_OPERATIONS_ERROR;
+-            goto done;
+-        }
++        ksc.ksdata[i].enctype = keys[i].key_data_type[0];
++        ksc.ksdata[i].key.enctype = keys[i].key_data_type[0];
++        ksc.ksdata[i].key.contents = (void *)plain.data;
++        ksc.ksdata[i].key.length = plain.length;
+ 
+         /* if salt available, add it */
+         if (keys[i].key_data_length[1] != 0) {
+-            rc = ber_printf(ber,
+-                            "t{tito}",
+-                            GKREP_SALT_TAG,
+-                                GKREP_SALTTYPE_TAG,
+-                                    (ber_int_t)keys[i].key_data_type[1],
+-                                GKREP_SALTVALUE_TAG,
+-                                    keys[i].key_data_contents[1],
+-                                    (ber_len_t)keys[i].key_data_length[1]);
+-            if (rc == -1) {
+-                LOG_FATAL("Failed to encode salt data\n");
+-                rc = LDAP_OPERATIONS_ERROR;
+-                goto done;
+-            }
+-        }
+-
+-        rc = ber_printf(ber, "}");
+-        if (rc == -1) {
+-            LOG_FATAL("Failed to encode data\n");
+-            rc = LDAP_OPERATIONS_ERROR;
+-            goto done;
++            ksc.ksdata[i].salttype = keys[i].key_data_type[1];
++            ksc.ksdata[i].salt.data = (void *)keys[i].key_data_contents[1];
++            ksc.ksdata[i].salt.length = keys[i].key_data_length[1];
+         }
+     }
+ 
+-    rc = ber_printf(ber, "}}");
+-    if (rc == -1) {
+-        LOG_FATAL("Failed to terminate key buffer\n");
+-        rc = LDAP_OPERATIONS_ERROR;
+-        goto done;
+-    }
++    bvp = calloc(1, sizeof(struct berval));
++    if (!bvp) goto done;
+ 
+-    rc = ber_flatten(ber, &bvp);
+-    if (rc == -1) {
+-        LOG_FATAL("Failed to encode key buffer\n");
+-        rc = LDAP_OPERATIONS_ERROR;
+-        goto done;
+-    }
++    ret = ipaasn1_enc_getktreply(kvno, &ksc,
++                                 (void **)&bvp->bv_val, &bvp->bv_len);
++    if (!ret) goto done;
+ 
+     rc = LDAP_SUCCESS;
+ 
+ done:
++    for (int i = 0; i < ksc.nkeys; i ++) {
++        free(ksc.ksdata[i].key.contents);
++    }
+     if (rc != LDAP_SUCCESS) {
+         if (bvp) ber_bvfree(bvp);
+     } else {
+         *_bvp = bvp;
+     }
+-    if (ber) ber_free(ber, 1);
+-    free(plain.data);
+     return rc;
+ }
+ 
+diff --git a/ipa-client/Makefile.am b/ipa-client/Makefile.am
+index 2df175e53b2a547acdad546db182b38011becd06..b9c7020f3b687b3c0030ed5166625e6ef07e2fa4 100644
+--- a/ipa-client/Makefile.am
++++ b/ipa-client/Makefile.am
+@@ -14,11 +14,13 @@ export AM_CFLAGS
+ 
+ KRB5_UTIL_DIR=../util
+ KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
++ASN1_UTIL_DIR=../asn1
+ 
+ AM_CPPFLAGS =							\
+ 	-I.							\
+ 	-I$(srcdir)						\
+ 	-I$(KRB5_UTIL_DIR)					\
++	-I$(ASN1_UTIL_DIR)					\
+ 	-DPREFIX=\""$(prefix)"\" 				\
+ 	-DBINDIR=\""$(bindir)"\"				\
+ 	-DLIBDIR=\""$(libdir)"\" 				\
+@@ -45,6 +47,7 @@ ipa_getkeytab_SOURCES =		\
+ 	$(NULL)
+ 
+ ipa_getkeytab_LDADD = 		\
++	../asn1/libipaasn1.la	\
+ 	$(KRB5_LIBS)		\
+ 	$(OPENLDAP_LIBS)	\
+ 	$(SASL_LIBS)		\
+@@ -80,6 +83,7 @@ ipa_join_LDADD = 		\
+ 	$(NULL)
+ 
+ SUBDIRS =			\
++	../asn1			\
+ 	ipaclient		\
+ 	ipa-install		\
+ 	man			\
+diff --git a/ipa-client/configure.ac b/ipa-client/configure.ac
+index 34625622d3e3bb64866b3b0b1a58d29e33f11a7d..78da8e6e413b8becbd4c75422abffb670050f446 100644
+--- a/ipa-client/configure.ac
++++ b/ipa-client/configure.ac
+@@ -8,6 +8,7 @@ AC_PROG_LIBTOOL
+ 
+ AC_CONFIG_SRCDIR([ipaclient/__init__.py])
+ AC_CONFIG_HEADERS([config.h])
++AC_CONFIG_SUBDIRS([../asn1])
+ 
+ AM_INIT_AUTOMAKE([foreign])
+ 
+@@ -205,6 +206,7 @@ dnl ---------------------------------------------------------------------------
+ 
+ AC_CONFIG_FILES([
+     Makefile
++    ../asn1/Makefile
+     ipaclient/Makefile
+     ipa-install/Makefile
+     man/Makefile
+diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
+index bb43c333dca6560807a120103a1cb535fa87b76a..15255d6a33c8c298f138868ac545d4ebea415fe5 100644
+--- a/ipa-client/ipa-getkeytab.c
++++ b/ipa-client/ipa-getkeytab.c
+@@ -40,6 +40,7 @@
+ #include "config.h"
+ 
+ #include "ipa_krb5.h"
++#include "ipa_asn1.h"
+ #include "ipa-client-common.h"
+ 
+ static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
+@@ -295,14 +296,15 @@ done:
+     return ret;
+ }
+ 
+-static BerElement *get_control_data(LDAPControl **list, const char *repoid)
++static int find_control_data(LDAPControl **list, const char *repoid,
++                             struct berval *data)
+ {
+     LDAPControl *control = NULL;
+     int i;
+ 
+     if (!list) {
+         fprintf(stderr, _("Missing reply control list!\n"));
+-        return NULL;
++        return LDAP_OPERATIONS_ERROR;
+     }
+ 
+     for (i = 0; list[i]; i++) {
+@@ -312,10 +314,22 @@ static BerElement *get_control_data(LDAPControl **list, const char *repoid)
+     }
+     if (!control) {
+         fprintf(stderr, _("Missing reply control!\n"));
+-        return NULL;
++        return LDAP_OPERATIONS_ERROR;
+     }
+ 
+-    return ber_init(&control->ldctl_value);
++    *data = control->ldctl_value;
++    return LDAP_SUCCESS;
++}
++
++static BerElement *get_control_data(LDAPControl **list, const char *repoid)
++{
++    struct berval data;
++    int ret;
++
++    ret = find_control_data(list, repoid, &data);
++    if (ret != LDAP_SUCCESS) return NULL;
++
++    return ber_init(&data);
+ }
+ 
+ static int ldap_set_keytab(krb5_context krbctx,
+@@ -435,124 +449,42 @@ error_out:
+ 	return -1;
+ }
+ 
+-/* Format of getkeytab control
+- *
+- * KeytabGetRequest ::= CHOICE {
+- *     newkeys      [0] Newkeys,
+- *     curkeys      [1] CurrentKeys,
+- *     reply        [2] Reply
+- * }
+- *
+- * NewKeys ::= SEQUENCE {
+- *     serviceIdentity [0] OCTET STRING,
+- *     enctypes        [1] SEQUENCE OF Int16
+- *     password        [2] OCTET STRING OPTIONAL,
+- * }
+- *
+- * CurrentKeys ::= SEQUENCE {
+- *     serviceIdentity [0] OCTET STRING,
+- * }
+- *
+- * Reply ::= SEQUENCE {
+- *     new_kvno        Int32
+- *     keys            SEQUENCE OF KrbKey,
+- * }
+- *
+- * KrbKey ::= SEQUENCE {
+- *     key       [0] EncryptionKey,
+- *     salt      [1] KrbSalt OPTIONAL,
+- *     s2kparams [2] OCTET STRING OPTIONAL,
+- * }
+- *
+- * EncryptionKey ::= SEQUENCE {
+- *     keytype   [0] Int32,
+- *     keyvalue  [1] OCTET STRING
+- * }
+- *
+- * KrbSalt ::= SEQUENCE {
+- *     type      [0] Int32,
+- *     salt      [1] OCTET STRING
+- * }
+- */
+-
+-#define GK_REQUEST_NEWKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
+-#define GK_REQUEST_CURKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_SVCNAME_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_ENCTYPES_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
+-#define GKREQ_PASSWORD_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
+-
++/* use asn1c generated code to fill up control */
+ static struct berval *create_getkeytab_control(const char *svc_princ, bool gen,
+                                                const char *password,
+                                                struct krb_key_salt *encsalts,
+                                                int num_encsalts)
+ {
+-    struct berval *bval = NULL;
+-    BerElement *be;
+-    ber_tag_t ctag;
+-    ber_int_t e;
+-    int ret, i;
+-
+-    be = ber_alloc_t(LBER_USE_DER);
+-    if (!be) {
+-        return NULL;
+-    }
+-
+-    if (gen) {
+-        ctag = GK_REQUEST_NEWKEYS;
+-    } else {
+-        ctag = GK_REQUEST_CURKEYS;
+-    }
+-
+-    ret = ber_printf(be, "t{ts", ctag, GKREQ_SVCNAME_TAG, svc_princ);
+-    if (ret == -1) {
+-        ber_free(be, 1);
+-        goto done;
+-    }
++    struct berval *result = NULL;
++    void *buffer = NULL;
++    size_t buflen;
++    long ets[num_encsalts];
++    bool ret;
++    int i;
+ 
+     if (gen) {
+-        ret = ber_printf(be, "t{", GKREQ_ENCTYPES_TAG);
+-        if (ret == -1) {
+-            ber_free(be, 1);
+-            goto done;
+-        }
+         for (i = 0; i < num_encsalts; i++) {
+-            e = encsalts[i].enctype;
+-            ret = ber_printf(be, "i", e);
+-            if (ret == -1) {
+-                ber_free(be, 1);
+-                goto done;
+-            }
+-        }
+-        ret = ber_printf(be, "}");
+-        if (ret == -1) {
+-            ber_free(be, 1);
+-            goto done;
+-        }
+-
+-        if (password) {
+-            ret = ber_printf(be, "ts", GKREQ_PASSWORD_TAG, password);
+-            if (ret == -1) {
+-                ber_free(be, 1);
+-                goto done;
+-            }
++            ets[i] = encsalts[i].enctype;
+         }
+     }
++    ret = ipaasn1_enc_getkt(gen, svc_princ,
++                            password, ets, num_encsalts,
++                            &buffer, &buflen);
++    if (!ret) goto done;
+ 
+-    ret = ber_printf(be, "}");
+-    if (ret == -1) {
+-        ber_free(be, 1);
+-        goto done;
+-    }
++    result = malloc(sizeof(struct berval));
++    if (!result) goto done;
+ 
+-    ret = ber_flatten(be, &bval);
+-    if (ret == -1) {
+-        ber_free(be, 1);
+-        goto done;
+-    }
++    result->bv_val = buffer;
++    result->bv_len = buflen;
+ 
+ done:
+-    ber_free(be, 1);
+-    return bval;
++    if (result == NULL) {
++        if (buffer) {
++            free(buffer);
++        }
++    }
++    return result;
+ }
+ 
+ #define GK_REPLY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
+@@ -571,13 +503,8 @@ static int ldap_get_keytab(krb5_context krbctx, bool generate, char *password,
+     struct berval *control = NULL;
+     LDAP *ld = NULL;
+     LDAPControl **srvctrl = NULL;
+-    BerElement *ber = NULL;
+-    ber_tag_t rtag;
+-    ber_tag_t ctag;
+-    ber_len_t tlen;
+-    ber_int_t vno;
+-    ber_int_t tint;
+-    struct berval tbval;
++    struct berval data;
++    bool res;
+     int ret;
+ 
+     *err_msg = NULL;
+@@ -609,98 +536,19 @@ static int ldap_get_keytab(krb5_context krbctx, bool generate, char *password,
+         goto done;
+     }
+ 
+-    ber = get_control_data(srvctrl, KEYTAB_GET_OID);
+-    if (!ber) {
+-        *err_msg = _("Failed to find or parse reply control!\n");
+-        ret = LDAP_OPERATIONS_ERROR;
+-        goto done;
+-    }
+-
+-    rtag = ber_scanf(ber, "t{i{", &ctag, &vno);
+-    if (rtag == LBER_ERROR || ctag != GK_REPLY_TAG) {
+-        *err_msg = _("Failed to parse control head!\n");
+-        ret = LDAP_OPERATIONS_ERROR;
+-        goto done;
+-    }
+-
+-    keys->nkeys = 0;
+-    keys->ksdata = NULL;
+-
+-    rtag = ber_peek_tag(ber, &tlen);
+-    for (int i = 0; rtag == LBER_SEQUENCE; i++) {
+-        if ((i % 5) == 0) {
+-            struct krb_key_salt *ksdata;
+-            ksdata = realloc(keys->ksdata,
+-                             (i + 5) * sizeof(struct krb_key_salt));
+-            if (!ksdata) {
+-                *err_msg = _("Out of memory!\n");
+-                ret = LDAP_OPERATIONS_ERROR;
+-                goto done;
+-            }
+-            keys->ksdata = ksdata;
+-        }
+-        memset(&keys->ksdata[i], 0, sizeof(struct krb_key_salt));
+-        keys->nkeys = i + 1;
+-
+-        rtag = ber_scanf(ber, "{t{io}", &ctag, &tint, &tbval);
+-        if (rtag == LBER_ERROR || ctag != GKREP_KEY_TAG) {
+-            *err_msg = _("Failed to parse enctype in key data!\n");
+-            ret = LDAP_OPERATIONS_ERROR;
+-            goto done;
+-        }
+-        keys->ksdata[i].enctype = tint;
+-        keys->ksdata[i].key.enctype = tint;
+-        keys->ksdata[i].key.length = tbval.bv_len;
+-        keys->ksdata[i].key.contents = malloc(tbval.bv_len);
+-        if (!keys->ksdata[i].key.contents) {
+-            *err_msg = _("Out of memory!\n");
+-            ret = LDAP_OPERATIONS_ERROR;
+-            goto done;
+-        }
+-        memcpy(keys->ksdata[i].key.contents, tbval.bv_val, tbval.bv_len);
+-        ber_memfree(tbval.bv_val);
+-
+-        rtag = ber_peek_tag(ber, &tlen);
+-        if (rtag == GKREP_SALT_TAG) {
+-            rtag = ber_scanf(ber, "t{io}", &ctag, &tint, &tbval);
+-            if (rtag == LBER_ERROR) {
+-                *err_msg = _("Failed to parse salt in key data!\n");
+-                ret = LDAP_OPERATIONS_ERROR;
+-                goto done;
+-            }
+-            keys->ksdata[i].salttype = tint;
+-            keys->ksdata[i].salt.length = tbval.bv_len;
+-            keys->ksdata[i].salt.data = malloc(tbval.bv_len);
+-            if (!keys->ksdata[i].salt.data) {
+-                *err_msg = _("Out of memory!\n");
+-                ret = LDAP_OPERATIONS_ERROR;
+-                goto done;
+-            }
+-            memcpy(keys->ksdata[i].salt.data, tbval.bv_val, tbval.bv_len);
+-            ber_memfree(tbval.bv_val);
+-        }
+-        rtag = ber_scanf(ber, "}");
+-        if (rtag == LBER_ERROR) {
+-            *err_msg = _("Failed to parse ending of key data!\n");
+-            ret = LDAP_OPERATIONS_ERROR;
+-            goto done;
+-        }
+-
+-        rtag = ber_peek_tag(ber, &tlen);
+-    }
++    ret = find_control_data(srvctrl, KEYTAB_GET_OID, &data);
++    if (ret != LDAP_SUCCESS) goto done;
+ 
+-    rtag = ber_scanf(ber, "}}");
+-    if (rtag == LBER_ERROR) {
+-        *err_msg = _("Failed to parse ending of control!\n");
++    res = ipaasn1_dec_getktreply(data.bv_val, data.bv_len, kvno, keys);
++    if (!res) {
++        *err_msg = _("Failed to decode control reply!\n");
+         ret = LDAP_OPERATIONS_ERROR;
+         goto done;
+     }
+ 
+-    *kvno = vno;
+     ret = LDAP_SUCCESS;
+ 
+ done:
+-    if (ber) ber_free(ber, 1);
+     if (ld) ldap_unbind_ext(ld, NULL, NULL);
+     if (control) ber_bvfree(control);
+     free(es);
+-- 
+2.1.0
+
diff --git a/SOURCES/0046-Fix-read_ip_addresses-should-return-ipaddr-object.patch b/SOURCES/0046-Fix-read_ip_addresses-should-return-ipaddr-object.patch
new file mode 100644
index 0000000..f8c56c9
--- /dev/null
+++ b/SOURCES/0046-Fix-read_ip_addresses-should-return-ipaddr-object.patch
@@ -0,0 +1,30 @@
+From fa9c01f32c4c12db64bfeed287ca546223c2afbd Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Thu, 20 Nov 2014 17:45:46 +0100
+Subject: [PATCH] Fix: read_ip_addresses should return ipaddr object
+
+Interactive prompt callback returns list of str instead of CheckedIPAddress
+instances.
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4747
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/installutils.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
+index 1e010edc6bf569a879c4f68efd2b273f57b01770..b05b1550a3b7c33a939b4173e57bf1329581d58a 100644
+--- a/ipaserver/install/installutils.py
++++ b/ipaserver/install/installutils.py
+@@ -247,7 +247,7 @@ def read_ip_addresses(host_name, fstore):
+         except Exception, e:
+             print "Error: Invalid IP Address %s: %s" % (ip, e)
+             continue
+-        ips.append(ip)
++        ips.append(ip_parsed)
+ 
+     return ips
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0046-Move-ipa-otpd-socket-directory.patch b/SOURCES/0046-Move-ipa-otpd-socket-directory.patch
deleted file mode 100644
index 87a59bf..0000000
--- a/SOURCES/0046-Move-ipa-otpd-socket-directory.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From e7d5a0c79e780fddb97bcbf2763a19a2c0b244c7 Mon Sep 17 00:00:00 2001
-From: Nathaniel McCallum <npmccallum@redhat.com>
-Date: Fri, 7 Feb 2014 11:56:33 -0500
-Subject: [PATCH 46/46] Move ipa-otpd socket directory
-
-https://fedorahosted.org/freeipa/ticket/4167
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- daemons/configure.ac                | 6 +++---
- daemons/ipa-otpd/Makefile.am        | 2 +-
- daemons/ipa-otpd/ipa-otpd.socket.in | 4 ++--
- freeipa.spec.in                     | 2 +-
- 4 files changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/daemons/configure.ac b/daemons/configure.ac
-index e57dad27614f268d3e5bbafc99b739a5cfa2589b..5646c3873beee996999e4f1d87aea653f4b5dd1b 100644
---- a/daemons/configure.ac
-+++ b/daemons/configure.ac
-@@ -60,10 +60,10 @@ AC_CHECK_LIB(k5crypto, main, [krb5crypto=k5crypto], [krb5crypto=crypto])
- AC_CHECK_LIB(krad, main, [], [AC_MSG_ERROR([libkrad not found])])
- KRB5_LIBS="-lkrb5 -l$krb5crypto -lcom_err"
- KRAD_LIBS="-lkrad"
--krb5kdcdir="${localstatedir}/kerberos/krb5kdc"
-+krb5rundir="${localstatedir}/run/krb5kdc"
- AC_SUBST(KRB5_LIBS)
- AC_SUBST(KRAD_LIBS)
--AC_SUBST(krb5kdcdir)
-+AC_SUBST(krb5rundir)
- 
- dnl ---------------------------------------------------------------------------
- dnl - Check for Mozilla LDAP and OpenLDAP SDK
-@@ -337,7 +337,7 @@ echo "
-         sysconfdir:               ${sysconfdir}
-         localstatedir:            ${localstatedir}
-         datadir:                  ${datadir}
--        krb5kdcdir:               ${krb5kdcdir}
-+        krb5rundir:               ${krb5rundir}
-         systemdsystemunitdir:     ${systemdsystemunitdir}
-         source code location:     ${srcdir}
-         compiler:                 ${CC}
-diff --git a/daemons/ipa-otpd/Makefile.am b/daemons/ipa-otpd/Makefile.am
-index af82a5fe08856573d2d245608ba1dbaad171c7fe..83921748426d801e1edeec23f956689be5fe98b5 100644
---- a/daemons/ipa-otpd/Makefile.am
-+++ b/daemons/ipa-otpd/Makefile.am
-@@ -9,7 +9,7 @@ systemdsystemunit_DATA = ipa-otpd.socket ipa-otpd@.service
- ipa_otpd_SOURCES = bind.c forward.c main.c parse.c query.c queue.c stdio.c
- 
- %.socket: %.socket.in
--	@sed -e 's|@krb5kdcdir[@]|$(krb5kdcdir)|g' \
-+	@sed -e 's|@krb5rundir[@]|$(krb5rundir)|g' \
- 	     -e 's|@UNLINK[@]|@UNLINK@|g' \
- 	     $< > $@
- 
-diff --git a/daemons/ipa-otpd/ipa-otpd.socket.in b/daemons/ipa-otpd/ipa-otpd.socket.in
-index b968beaa7b9e68c43b2c5386b62c096fa8b97764..ce3596d9f01b26e3e8bd63f447f85a486c8e0dff 100644
---- a/daemons/ipa-otpd/ipa-otpd.socket.in
-+++ b/daemons/ipa-otpd/ipa-otpd.socket.in
-@@ -2,8 +2,8 @@
- Description=ipa-otpd socket
- 
- [Socket]
--ListenStream=@krb5kdcdir@/DEFAULT.socket
--ExecStopPre=@UNLINK@ @krb5kdcdir@/DEFAULT.socket
-+ListenStream=@krb5rundir@/DEFAULT.socket
-+ExecStopPre=@UNLINK@ @krb5rundir@/DEFAULT.socket
- SocketMode=0600
- Accept=true
- 
-diff --git a/freeipa.spec.in b/freeipa.spec.in
-index ae8ee57f3ba2c0746bb0f7a1e65dab1da83cca22..cff79843d76a7251ae6065dba7341465733bb7cc 100644
---- a/freeipa.spec.in
-+++ b/freeipa.spec.in
-@@ -105,7 +105,7 @@ Requires: nss >= 3.14.3-12.0
- Requires: nss-tools >= 3.14.3-12.0
- %endif
- %if 0%{?krb5_dal_version} >= 4
--Requires: krb5-server >= 1.11.2-1
-+Requires: krb5-server >= 1.11.5-3
- %else
- %if 0%{krb5_dal_version} == 3
- # krb5 1.11 bumped DAL interface major version, a rebuild is needed
--- 
-1.8.5.3
-
diff --git a/SOURCES/0047-Use-correct-service-name-in-cainstance.backup_config.patch b/SOURCES/0047-Use-correct-service-name-in-cainstance.backup_config.patch
new file mode 100644
index 0000000..8ba39fc
--- /dev/null
+++ b/SOURCES/0047-Use-correct-service-name-in-cainstance.backup_config.patch
@@ -0,0 +1,29 @@
+From 5147e5f6c0aa53201938f1d3f25316089434fcc2 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Fri, 21 Nov 2014 07:52:24 +0000
+Subject: [PATCH] Use correct service name in cainstance.backup_config
+
+https://fedorahosted.org/freeipa/ticket/4754
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ipaserver/install/cainstance.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
+index 0c31d21648689ad5c577e9112fefdf47857b4915..ac494917744ce0fa2d8e38ce5ce9dab6b24bdebf 100644
+--- a/ipaserver/install/cainstance.py
++++ b/ipaserver/install/cainstance.py
+@@ -1861,7 +1861,8 @@ def backup_config(dogtag_constants=None):
+     if dogtag_constants is None:
+         dogtag_constants = dogtag.configured_constants()
+ 
+-    if services.knownservices.dogtag.is_running():
++    if services.knownservices[dogtag_constants.SERVICE_NAME].is_running(
++        dogtag_constants.PKI_INSTANCE_NAME):
+         raise RuntimeError("Dogtag must be stopped when creating backup of %s"
+                            % dogtag_constants.CS_CFG_PATH)
+     shutil.copy(dogtag_constants.CS_CFG_PATH,
+-- 
+2.1.0
+
diff --git a/SOURCES/0047-bindinstance-make-sure-zone-manager-is-initialized-i.patch b/SOURCES/0047-bindinstance-make-sure-zone-manager-is-initialized-i.patch
deleted file mode 100644
index 7a023ac..0000000
--- a/SOURCES/0047-bindinstance-make-sure-zone-manager-is-initialized-i.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From ea96ad03312cecad4ff6853aafc30d3cf2c618a9 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 26 Feb 2014 11:06:29 +0200
-Subject: [PATCH 47/51] bindinstance: make sure zone manager is initialized in
- add_master_dns_records
-
-Bind instance is configured using a short-circuited way when replica is set up.
-Make sure required properties are in place for that.
-
-https://fedorahosted.org/freeipa/ticket/4186
-
-Reviewed-By: Petr Viktorin <pviktori@redhat.com>
----
- ipaserver/install/bindinstance.py | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
-index 6d5a1d44d30c89278c24fe7ab5278355cb65b0b4..4dc4103f7cb94877d0652f0094b41feec56cee94 100644
---- a/ipaserver/install/bindinstance.py
-+++ b/ipaserver/install/bindinstance.py
-@@ -828,6 +828,7 @@ def add_master_dns_records(self, fqdn, ip_address, realm_name, domain_name,
-         self.reverse_zone = reverse_zone
-         self.ca_configured = ca_configured
-         self.first_instance = False
-+        self.zonemgr = 'hostmaster.%s' % self.domain
- 
-         self.__add_self()
-         self.__add_ipa_ca_record()
--- 
-1.8.5.3
-
diff --git a/SOURCES/0048-ipa-restore-Check-if-directory-is-provided-better-er.patch b/SOURCES/0048-ipa-restore-Check-if-directory-is-provided-better-er.patch
new file mode 100644
index 0000000..0568548
--- /dev/null
+++ b/SOURCES/0048-ipa-restore-Check-if-directory-is-provided-better-er.patch
@@ -0,0 +1,54 @@
+From 354f11fc9f417ba777e2e010597e72a013ae5d23 Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Fri, 21 Nov 2014 06:30:17 -0500
+Subject: [PATCH] ipa-restore: Check if directory is provided + better errors.
+
+https://fedorahosted.org/freeipa/ticket/4683
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 93f176d302a49319940555a0be3037620143e1f3..f290bae4dc6455bb22c4e726e72efe98205d970e 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -152,6 +152,9 @@ class Restore(admintool.AdminTool):
+         else:
+             self.backup_dir = dirname
+ 
++        if not os.path.isdir(dirname):
++            raise self.option_parser.error("must provide path to backup directory")
++
+         if options.gpg_keyring:
+             if (not os.path.exists(options.gpg_keyring + '.pub') or
+                not os.path.exists(options.gpg_keyring + '.sec')):
+@@ -213,7 +216,10 @@ class Restore(admintool.AdminTool):
+         try:
+             dirsrv = services.knownservices.dirsrv
+ 
+-            self.read_header()
++            try:
++                self.read_header()
++            except IOError as e:
++                raise admintool.ScriptError('Cannot read backup metadata: %s' % e)
+             # These two checks would normally be in the validate method but
+             # we need to know the type of backup we're dealing with.
+             if (self.backup_type != 'FULL' and not options.data_only and
+@@ -546,9 +552,9 @@ class Restore(admintool.AdminTool):
+         Read the backup file header that contains the meta data about
+         this particular backup.
+         '''
+-        fd = open(self.header)
+-        config = SafeConfigParser()
+-        config.readfp(fd)
++        with open(self.header) as fd:
++            config = SafeConfigParser()
++            config.readfp(fd)
+ 
+         self.backup_type = config.get('ipa', 'type')
+         self.backup_time = config.get('ipa', 'time')
+-- 
+2.1.0
+
diff --git a/SOURCES/0048-trustdomain_find-make-sure-we-skip-short-entries-whe.patch b/SOURCES/0048-trustdomain_find-make-sure-we-skip-short-entries-whe.patch
deleted file mode 100644
index b1718fb..0000000
--- a/SOURCES/0048-trustdomain_find-make-sure-we-skip-short-entries-whe.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From a11cfd34e2f92c3c71a0b568d758f7d5221b4e94 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 26 Feb 2014 17:59:05 +0200
-Subject: [PATCH 48/51] trustdomain_find: make sure we skip short entries when
- --pkey-only is specified
-
-With --pkey-only only primary key is returned. It makes no sense to check and
-replace boolean values then.
-
-https://fedorahosted.org/freeipa/ticket/4196
-
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- ipalib/plugins/trust.py | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index 0b6db27c696cd169c8f4b33128520961c20e3015..bd71253607d6009414ff8a24b042175f0cb08d66 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -1191,6 +1191,8 @@ def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **optio
-         return (filters, base_dn, ldap.SCOPE_SUBTREE)
- 
-     def post_callback(self, ldap, entries, truncated, *args, **options):
-+        if options.get('pkey_only', False):
-+            return truncated
-         trust_dn = self.obj.get_dn(args[0], trust_type=u'ad')
-         trust_entry = ldap.get_entry(trust_dn)
-         for entry in entries:
--- 
-1.8.5.3
-
diff --git a/SOURCES/0049-Stop-tracking-certificates-before-restoring-them-in-.patch b/SOURCES/0049-Stop-tracking-certificates-before-restoring-them-in-.patch
new file mode 100644
index 0000000..f8870c5
--- /dev/null
+++ b/SOURCES/0049-Stop-tracking-certificates-before-restoring-them-in-.patch
@@ -0,0 +1,57 @@
+From 318a05f1564e95ae3516d7cfdb6cd7c03a87b87d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 20 Nov 2014 13:57:46 +0000
+Subject: [PATCH] Stop tracking certificates before restoring them in
+ ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4727
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index f290bae4dc6455bb22c4e726e72efe98205d970e..9cb978a516f4f85307735b7428f6053461061022 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -26,7 +26,7 @@ import pwd
+ from ConfigParser import SafeConfigParser
+ 
+ from ipalib import api, errors
+-from ipapython import version, ipautil, certdb
++from ipapython import version, ipautil, certdb, dogtag
+ from ipapython.ipautil import run, user_input
+ from ipapython import admintool
+ from ipapython.dn import DN
+@@ -36,7 +36,7 @@ from ipaserver.install.cainstance import PKI_USER, create_ca_user
+ from ipaserver.install.replication import (wait_for_task, ReplicationManager,
+                                            get_cs_replication_manager)
+ from ipaserver.install import installutils
+-from ipaserver.install import httpinstance
++from ipaserver.install import dsinstance, httpinstance, cainstance
+ from ipapython import ipaldap
+ import ipapython.errors
+ from ipaplatform.tasks import tasks
+@@ -676,6 +676,12 @@ class Restore(admintool.AdminTool):
+             self.log.error('%s', e)
+ 
+     def cert_restore_prepare(self):
++        cainstance.stop_tracking_certificates(
++            dogtag.configured_constants())
++        httpinstance.HTTPInstance().stop_tracking_certificates()
++        dsinstance.DsInstance().stop_tracking_certificates(
++            realm_to_serverid(api.env.realm))
++
+         for basename in ('cert8.db', 'key3.db', 'secmod.db', 'pwdfile.txt'):
+             filename = os.path.join(paths.IPA_NSSDB_DIR, basename)
+             try:
+@@ -705,3 +711,5 @@ class Restore(admintool.AdminTool):
+                             (nickname, paths.IPA_NSSDB_DIR, e))
+ 
+         tasks.reload_systemwide_ca_store()
++
++        services.knownservices.certmonger.restart()
+-- 
+2.1.0
+
diff --git a/SOURCES/0049-ipa-kdb-in-case-of-delegation-use-original-client-s-.patch b/SOURCES/0049-ipa-kdb-in-case-of-delegation-use-original-client-s-.patch
deleted file mode 100644
index a3c7c45..0000000
--- a/SOURCES/0049-ipa-kdb-in-case-of-delegation-use-original-client-s-.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From ede01c14e58a98af728152635e5d75be0deb389d Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 25 Feb 2014 17:50:55 +0200
-Subject: [PATCH 49/51] ipa-kdb: in case of delegation use original client's
- database entry, not the proxy
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-https://fedorahosted.org/freeipa/ticket/4195
-
-Reviewed-By: Tomáš Babej <tbabej@redhat.com>
-Reviewed-By: Simo Sorce <ssorce@redhat.com>
----
- daemons/ipa-kdb/ipa_kdb_mspac.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
-index ff67391538234e2272ea1ec886ec96fa88ea579b..2a0480fff029d29fb56286d85108936f6c579901 100644
---- a/daemons/ipa-kdb/ipa_kdb_mspac.c
-+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
-@@ -1983,12 +1983,14 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     bool with_pac;
-     bool with_pad;
-     int result;
-+    krb5_db_entry *client_entry = NULL;
- 
-     /* When using s4u2proxy client_princ actually refers to the proxied user
-      * while client->princ to the proxy service asking for the TGS on behalf
-      * of the proxied user. So always use client_princ in preference */
-     if (client_princ != NULL) {
-         ks_client_princ = client_princ;
-+        kerr = ipadb_get_principal(context, client_princ, flags, &client_entry);
-     } else {
-         ks_client_princ = client->princ;
-     }
-@@ -2025,7 +2027,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-             }
-         }
- 
--        kerr = ipadb_get_pac(context, client, &pac);
-+        kerr = ipadb_get_pac(context, client_entry ? client_entry : client, &pac);
-         if (kerr != 0 && kerr != ENOENT) {
-             goto done;
-         }
-@@ -2041,7 +2043,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-         /* check or generate pac data */
-         if ((pac_auth_data == NULL) || (pac_auth_data[0] == NULL)) {
-             if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
--                kerr = ipadb_get_pac(context, client, &pac);
-+                kerr = ipadb_get_pac(context, client_entry ? client_entry : client, &pac);
-                 if (kerr != 0 && kerr != ENOENT) {
-                     goto done;
-                 }
-@@ -2094,6 +2096,9 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     kerr = 0;
- 
- done:
-+    if (client_entry != NULL) {
-+        ipadb_free_principal(context, client_entry);
-+    }
-     krb5_pac_free(context, pac);
-     return kerr;
- }
--- 
-1.8.5.3
-
diff --git a/SOURCES/0050-Fix-detection-of-encoding-in-zonemgr-option.patch b/SOURCES/0050-Fix-detection-of-encoding-in-zonemgr-option.patch
new file mode 100644
index 0000000..2a526dd
--- /dev/null
+++ b/SOURCES/0050-Fix-detection-of-encoding-in-zonemgr-option.patch
@@ -0,0 +1,40 @@
+From 296656789c1bc8e2667c989d10cac300f8b5b7fc Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Mon, 24 Nov 2014 12:46:37 +0100
+Subject: [PATCH] Fix detection of encoding in zonemgr option
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4762
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/bindinstance.py | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
+index 5bf784e62aec7c323a84fc5130e53c3deb86e6fd..f02fe8647dd38d05734311406152c50108077561 100644
+--- a/ipaserver/install/bindinstance.py
++++ b/ipaserver/install/bindinstance.py
+@@ -401,13 +401,14 @@ def zonemgr_callback(option, opt_str, value, parser):
+     """
+     Properly validate and convert --zonemgr Option to IA5String
+     """
+-    # validate the value first
+-    try:
+-        # IDNA support requires unicode
+-        value = value.decode(sys.stdin.encoding)
+-        validate_zonemgr_str(value)
+-    except ValueError, e:
+-        parser.error("invalid zonemgr: " + unicode(e))
++    if value is not None:
++        # validate the value first
++        try:
++            # IDNA support requires unicode
++            value = value.decode(getattr(sys.stdin, 'encoding', 'utf-8'))
++            validate_zonemgr_str(value)
++        except ValueError, e:
++            parser.error("invalid zonemgr: " + unicode(e))
+ 
+     parser.values.zonemgr = value
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0050-ipa-kdb-make-sure-we-don-t-produce-MS-PAC-in-case-of.patch b/SOURCES/0050-ipa-kdb-make-sure-we-don-t-produce-MS-PAC-in-case-of.patch
deleted file mode 100644
index a4909d1..0000000
--- a/SOURCES/0050-ipa-kdb-make-sure-we-don-t-produce-MS-PAC-in-case-of.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 817e83837d249a63395d90ac47dc975a23f00c6c Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 25 Feb 2014 20:53:49 +0200
-Subject: [PATCH 50/51] ipa-kdb: make sure we don't produce MS-PAC in case of
- authdata flag cleared by admin
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When admin clears authdata flag for the service principal, KDC will pass
-NULL client pointer (service proxy) to the DAL driver.
-
-Make sure we bail out correctly.
-
-Reviewed-By: Tomáš Babej <tbabej@redhat.com>
-Reviewed-By: Simo Sorce <ssorce@redhat.com>
----
- daemons/ipa-kdb/ipa_kdb_mspac.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
-index 2a0480fff029d29fb56286d85108936f6c579901..9137cd5ad1e6166fd5d6e765fab2c8178ca0587c 100644
---- a/daemons/ipa-kdb/ipa_kdb_mspac.c
-+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
-@@ -1985,6 +1985,14 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     int result;
-     krb5_db_entry *client_entry = NULL;
- 
-+
-+    /* When client is NULL, authdata flag on the service principal was cleared
-+     * by an admin. We don't generate MS-PAC in this case */
-+    if (client == NULL) {
-+        *signed_auth_data = NULL;
-+        return 0;
-+    }
-+
-     /* When using s4u2proxy client_princ actually refers to the proxied user
-      * while client->princ to the proxy service asking for the TGS on behalf
-      * of the proxied user. So always use client_princ in preference */
--- 
-1.8.5.3
-
diff --git a/SOURCES/0051-Too-big-font-in-input-fields.patch b/SOURCES/0051-Too-big-font-in-input-fields.patch
deleted file mode 100644
index 89a369c..0000000
--- a/SOURCES/0051-Too-big-font-in-input-fields.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 92cb7c52b3a6241c9a0e5bc4e0c91705723d118f Mon Sep 17 00:00:00 2001
-From: Adam Misnyovszki <amisnyov@redhat.com>
-Date: Wed, 26 Feb 2014 18:16:45 +0100
-Subject: [PATCH 51/51] Too big font in input fields
-
-In Firefox 27, default font size has bigger priority than body css,
-text input font size is therefore explicitly set to 1em. Also
-checkbox/radiobutton styling fixed.
-
-https://fedorahosted.org/freeipa/ticket/4180
-
-Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
----
- install/ui/ipa.css | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/install/ui/ipa.css b/install/ui/ipa.css
-index ad3d1aa1f8f8898ad8dff8f8ecc175238fad1181..29dfe80aacfa1e508f59d3008b2aa57f9477a448 100644
---- a/install/ui/ipa.css
-+++ b/install/ui/ipa.css
-@@ -1243,6 +1243,18 @@ table.scrollable tbody {
-     width: 250px;
- }
- 
-+input, select, textarea {
-+    font-size: 1em;
-+    font-family: "Liberation Sans",Arial,Sans;
-+}
-+
-+input[type=radio], input[type=checkbox],
-+.ui-widget input[type=radio], .ui-widget input[type=checkbox]{
-+     margin-right: 5px;
-+     position: relative;
-+     top: 3px;
-+}
-+
- .multivalued-widget [name=value] {
-     margin-bottom: 1em;
- }
--- 
-1.8.5.3
-
diff --git a/SOURCES/0051-webui-use-domain-name-instead-of-domain-SID-in-idran.patch b/SOURCES/0051-webui-use-domain-name-instead-of-domain-SID-in-idran.patch
new file mode 100644
index 0000000..63d5bae
--- /dev/null
+++ b/SOURCES/0051-webui-use-domain-name-instead-of-domain-SID-in-idran.patch
@@ -0,0 +1,149 @@
+From 8918cc58cb4cd24a4332c9935be75add89fd3c8b Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Tue, 4 Nov 2014 13:38:12 +0100
+Subject: [PATCH] webui: use domain name instead of domain SID in idrange adder
+ dialog
+
+It's more user friendly. Almost nobody remembers SIDs.
+
+https://fedorahosted.org/freeipa/ticket/4661
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/ui/src/freeipa/idrange.js | 16 +++++++---------
+ ipatests/test_webui/task_range.py | 20 ++++++++++----------
+ ipatests/test_webui/test_range.py |  4 ++--
+ 3 files changed, 19 insertions(+), 21 deletions(-)
+
+diff --git a/install/ui/src/freeipa/idrange.js b/install/ui/src/freeipa/idrange.js
+index 4e5dbfa00dcf80495d8a96f7fc961b9c6676691f..8af1598af335db2429512910d286bc3bada7b325 100644
+--- a/install/ui/src/freeipa/idrange.js
++++ b/install/ui/src/freeipa/idrange.js
+@@ -138,9 +138,7 @@ return {
+                 title: '@mo-param:idrange:ipasecondarybaserid:label'
+             },
+             {
+-                name: 'ipanttrusteddomainsid',
+-                label: '@i18n:objects.idrange.ipanttrusteddomainsid',
+-                title: '@mo-param:idrange:ipanttrusteddomainsid:label',
++                name: 'ipanttrusteddomainname',
+                 enabled: false
+             }
+         ],
+@@ -153,14 +151,14 @@ return {
+ IPA.idrange_adder_policy = function(spec) {
+     /*
+     The logic for enabling/requiring ipabaserid, ipasecondarybaserid and
+-    ipanttrusteddomainsid is as follows:
++    ipanttrusteddomainname is as follows:
+         1) for AD ranges (range type is ipa-ad-trust or ipa-ad-trust-posix):
+-           * ipanttrusteddomainsid is required
++           * ipanttrusteddomainname is required
+            * ipabaserid is required for ipa-ad-trust but disabled for
+              ipa-ad-trust-posix
+            * ipasecondarybaserid is disabled
+         2) for local ranges
+-           *  ipanttrusteddomainsid is disabled
++           *  ipanttrusteddomainname is disabled
+            A) if server has AD trust support:
+               * both ipabaserid and ipasecondarybaserid are required
+            B) if server does not have AD trust support:
+@@ -207,7 +205,7 @@ IPA.idrange_adder_policy = function(spec) {
+         var type_f = that.container.fields.get_field('iparangetype');
+         var baserid_f = that.container.fields.get_field('ipabaserid');
+         var secondarybaserid_f = that.container.fields.get_field('ipasecondarybaserid');
+-        var trusteddomainsid_f = that.container.fields.get_field('ipanttrusteddomainsid');
++        var trusteddomainname_f = that.container.fields.get_field('ipanttrusteddomainname');
+ 
+         var type_v = type_f.get_value()[0];
+         var baserid_v = baserid_f.get_value()[0] || '';
+@@ -221,10 +219,10 @@ IPA.idrange_adder_policy = function(spec) {
+             } else {
+                 disable(baserid_f);
+             }
+-            require(trusteddomainsid_f);
++            require(trusteddomainname_f);
+             disable(secondarybaserid_f);
+         } else {
+-            disable(trusteddomainsid_f);
++            disable(trusteddomainname_f);
+ 
+             if (IPA.trust_enabled) {
+                 require(baserid_f);
+diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
+index d46d345f03a2b50730e3107ef6f7c2222da4465c..b71285d1e6056b11e3e74703a568be27973de3bc 100644
+--- a/ipatests/test_webui/task_range.py
++++ b/ipatests/test_webui/task_range.py
+@@ -59,13 +59,13 @@ class range_tasks(UI_driver):
+         self.max_id = max_id
+         self.max_rid = max_rid
+ 
+-    def get_sid(self):
++    def get_domain(self):
+         result = self.execute_api_from_ui('trust_find', [], {})
+         trusts = result['result']['result']
+-        sid = None
++        domain = None
+         if trusts:
+-            sid = trusts[0]['ipanttrusteddomainsid']
+-        return sid
++            domain = trusts[0]['cn']
++        return domain
+ 
+     def get_data(self, pkey, size=50, add_data=None):
+ 
+@@ -81,7 +81,7 @@ class range_tasks(UI_driver):
+         }
+         return data
+ 
+-    def get_add_data(self, pkey, range_type='ipa-local', size=50, shift=100, sid=None):
++    def get_add_data(self, pkey, range_type='ipa-local', size=50, shift=100, domain=None):
+ 
+         base_id = self.max_id + shift
+         self.max_id = base_id + size
+@@ -98,19 +98,19 @@ class range_tasks(UI_driver):
+             ('callback', self.check_range_type_mod, range_type)
+         ]
+ 
+-        if not sid:
++        if not domain:
+             base_rid = self.max_rid + shift
+             self.max_rid = base_rid + size
+             add.append(('textbox', 'ipasecondarybaserid', str(base_rid)))
+-        if sid:
+-            add.append(('textbox', 'ipanttrusteddomainsid', sid))
++        if domain:
++            add.append(('textbox', 'ipanttrusteddomainname', domain))
+ 
+         return add
+ 
+     def check_range_type_mod(self, range_type):
+         if range_type == 'ipa-local':
+-            self.assert_disabled("[name=ipanttrusteddomainsid]")
++            self.assert_disabled("[name=ipanttrusteddomainname]")
+             self.assert_disabled("[name=ipasecondarybaserid]", negative=True)
+         elif range_type == 'ipa-ad-trust':
+-            self.assert_disabled("[name=ipanttrusteddomainsid]", negative=True)
++            self.assert_disabled("[name=ipanttrusteddomainname]", negative=True)
+             self.assert_disabled("[name=ipasecondarybaserid]")
+diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
+index 5c2e33b90833d5e03014e72fad302e58c986ca25..e1c46e50a85171bafabe80bd772ed9ac983a6ca4 100644
+--- a/ipatests/test_webui/test_range.py
++++ b/ipatests/test_webui/test_range.py
+@@ -74,11 +74,11 @@ class test_range(range_tasks):
+ 
+             self.add_record(trust_mod.ENTITY, trust_data)
+ 
+-            sid = self.get_sid()
++            domain = self.get_domain()
+ 
+             self.navigate_to_entity(ENTITY)
+ 
+-            add = self.get_add_data(pkey_ad, range_type='ipa-ad-trust', sid=sid)
++            add = self.get_add_data(pkey_ad, range_type='ipa-ad-trust', domain=domain)
+             data = self.get_data(pkey_ad, add_data=add)
+             self.add_record(ENTITY, data, navigate=False)
+             self.assert_record_value('Active Directory domain range', pkey_ad, column)
+-- 
+2.1.0
+
diff --git a/SOURCES/0052-trust-make-sure-we-always-discover-topology-of-the-f.patch b/SOURCES/0052-trust-make-sure-we-always-discover-topology-of-the-f.patch
deleted file mode 100644
index 93b27ce..0000000
--- a/SOURCES/0052-trust-make-sure-we-always-discover-topology-of-the-f.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From bbba8c95ed2f5e551b4e468b394f5e0839be9f6f Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Thu, 27 Feb 2014 13:43:17 +0200
-Subject: [PATCH 52/53] trust: make sure we always discover topology of the
- forest trust
-
-Even though we are creating idranges for subdomains only in case
-there is algorithmic ID mapping in use, we still need to fetch
-list of subdomains for all other cases.
-
-https://fedorahosted.org/freeipa/ticket/4205
----
- ipalib/plugins/trust.py | 37 ++++++-------------------------------
- 1 file changed, 6 insertions(+), 31 deletions(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index bd71253607d6009414ff8a24b042175f0cb08d66..f2b00a6f58f5890e37aaa033a35dcf9bc39ccbc4 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -458,38 +458,13 @@ def execute(self, *keys, **options):
- 
-         result['result'] = entry_to_dict(trusts[0][1], **options)
- 
--        # For AD trusts with algorithmic mapping, we need to add a separate
--        # range for each subdomain.
--        if (options.get('trust_type') == u'ad' and
--            created_range_type != u'ipa-ad-trust-posix'):
--
-+        # Fetch topology of the trust forest -- we need always to do it
-+        # for AD trusts, regardless of the type of idranges associated with it
-+        # Note that fetch_domains_from_trust will add needed ranges for
-+        # the algorithmic ID mapping case.
-+        if options.get('trust_type') == u'ad':
-             domains = fetch_domains_from_trust(self, self.trustinstance,
-                                                result['result'], **options)
--            if domains and len(domains) > 0:
--                for dom in domains:
--                    range_name = dom['cn'][0].upper() + '_id_range'
--                    dom_sid = dom['ipanttrusteddomainsid'][0]
--
--                    # Enforce the same range type as the range for the root
--                    # level domain.
--
--                    # This will skip the detection of the POSIX attributes if
--                    # they are not available, since it has been already
--                    # detected when creating the range for the root level domain
--                    passed_options = options
--                    passed_options.update(range_type=created_range_type)
--
--                    # Do not pass the base id to the subdomains since it would
--                    # clash with the root level domain
--                    if 'base_id' in passed_options:
--                        del passed_options['base_id']
--
--                    # Try to add the range for each subdomain
--                    try:
--                        add_range(self, range_name, dom_sid, *keys,
--                                  **passed_options)
--                    except errors.DuplicateEntry:
--                        pass
- 
-         # Format the output into human-readable values
-         result['result']['trusttype'] = [trust_type_string(
-@@ -1270,7 +1245,7 @@ def fetch_domains_from_trust(self, trustinstance, trust_entry, **options):
-     # trust range must exist by the time fetch_domains_from_trust is called
-     range_name = trust_name.upper() + '_id_range'
-     old_range = api.Command.idrange_show(range_name, raw=True)['result']
--    idrange_type = old_range['iparangetype']
-+    idrange_type = old_range['iparangetype'][0]
- 
-     for dom in domains:
-         dom['trust_type'] = u'ad'
--- 
-1.8.5.3
-
diff --git a/SOURCES/0052-webui-normalize-idview-tab-labels.patch b/SOURCES/0052-webui-normalize-idview-tab-labels.patch
new file mode 100644
index 0000000..e00a15e
--- /dev/null
+++ b/SOURCES/0052-webui-normalize-idview-tab-labels.patch
@@ -0,0 +1,48 @@
+From 6d8d3b19480e9072df1aababe14d449b64e25a55 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Tue, 4 Nov 2014 15:49:34 +0100
+Subject: [PATCH] webui: normalize idview tab labels
+
+ID View tab labels are no longer redundant.
+
+https://fedorahosted.org/freeipa/ticket/4650
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/ui/src/freeipa/idviews.js | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/install/ui/src/freeipa/idviews.js b/install/ui/src/freeipa/idviews.js
+index cbc78ae7c62916b6334a8ef0cdf12a92485b0876..823936401653096a0a649282e3b18f573de09804 100644
+--- a/install/ui/src/freeipa/idviews.js
++++ b/install/ui/src/freeipa/idviews.js
+@@ -112,7 +112,7 @@ return {
+             nested_entity: 'idoverrideuser',
+             search_all_entries: true,
+             label: '@mo:idoverrideuser.label',
+-            tab_label: '@mo:idoverrideuser.label',
++            tab_label: '@mo:user.label',
+             name: 'idoverrideuser',
+             columns: [
+                 {
+@@ -132,7 +132,7 @@ return {
+             nested_entity: 'idoverridegroup',
+             search_all_entries: true,
+             label: '@mo:idoverridegroup.label',
+-            tab_label: '@mo:idoverridegroup.label',
++            tab_label: '@mo:group.label',
+             name: 'idoverridegroup',
+             columns: [
+                 {
+@@ -148,7 +148,7 @@ return {
+             $type: 'idview_appliedtohosts',
+             name: 'appliedtohosts',
+             attribute: 'appliedtohosts',
+-            tab_label: '@i18n:objects.idview.appliedtohosts',
++            tab_label: '@mo:host.label',
+             facet_group: 'appliedto',
+             actions: [
+                 'idview_apply',
+-- 
+2.1.0
+
diff --git a/SOURCES/0053-copy_schema_to_ca-Fallback-to-old-import-location-fo.patch b/SOURCES/0053-copy_schema_to_ca-Fallback-to-old-import-location-fo.patch
new file mode 100644
index 0000000..080350d
--- /dev/null
+++ b/SOURCES/0053-copy_schema_to_ca-Fallback-to-old-import-location-fo.patch
@@ -0,0 +1,43 @@
+From 5cea94bf6ba5ecbd9e18b0bf352ca82c62e6ee34 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <pviktori@redhat.com>
+Date: Mon, 24 Nov 2014 15:01:29 +0100
+Subject: [PATCH] copy_schema_to_ca: Fallback to old import location for
+ ipaplatform.services
+
+This file is copied to older servers that might not have the ipaplatform
+refactoring.
+Import from the old location if the new one is not available.
+
+https://fedorahosted.org/freeipa/ticket/4763
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/share/copy-schema-to-ca.py | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/install/share/copy-schema-to-ca.py b/install/share/copy-schema-to-ca.py
+index fc53fe4cb52486cc618bec77aabe8283ad5eadbc..1614e11636c2f52e231ea2ff40d882209194c60a 100755
+--- a/install/share/copy-schema-to-ca.py
++++ b/install/share/copy-schema-to-ca.py
+@@ -15,13 +15,17 @@ import sys
+ import pwd
+ import shutil
+ 
+-from ipaplatform import services
+ from ipapython import ipautil, dogtag
+ from ipapython.ipa_log_manager import root_logger, standard_logging_setup
+ from ipaserver.install.dsinstance import DS_USER, schema_dirname
+ from ipaserver.install.cainstance import PKI_USER
+ from ipalib import api
+ 
++try:
++    from ipaplatform import services
++except ImportError:
++    from ipapython import services  # pylint: disable=no-name-in-module
++
+ SERVERID = "PKI-IPA"
+ SCHEMA_FILENAMES = (
+     "60kerberos.ldif",
+-- 
+2.1.0
+
diff --git a/SOURCES/0053-ipaserver-dcerpc-catch-the-case-of-insuffient-permis.patch b/SOURCES/0053-ipaserver-dcerpc-catch-the-case-of-insuffient-permis.patch
deleted file mode 100644
index eeccfc1..0000000
--- a/SOURCES/0053-ipaserver-dcerpc-catch-the-case-of-insuffient-permis.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 504e8701fd7870b18febe9b544244d5d2744bb16 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 26 Feb 2014 17:43:34 +0200
-Subject: [PATCH 53/53] ipaserver/dcerpc: catch the case of insuffient
- permissions when establishing trust
-
-We attempt to delete the trust that might exist already. If there are not enough
-privileges to do so, we wouldn't be able to create trust at the next step and it will fail.
-However, failure to create trust will be due to the name collision as we already had
-the trust with the same name before. Thus, raise access denied exception here
-to properly indicate wrong access level instead of returning NT_STATUS_OBJECT_NAME_COLLISION.
-
-https://fedorahosted.org/freeipa/ticket/4202
-
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- ipaserver/dcerpc.py | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index d809c416baac072a2489fbd3c167f08665b7a24e..5972e622292a033d4fc979cbf5401fa02151f35c 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -892,8 +892,11 @@ def establish_trust(self, another_domain, trustdom_secret):
-             dname.string = another_domain.info['dns_domain']
-             res = self._pipe.QueryTrustedDomainInfoByName(self._policy_handle, dname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)
-             self._pipe.DeleteTrustedDomain(self._policy_handle, res.info_ex.sid)
--        except RuntimeError, e:
--            pass
-+        except RuntimeError, (num, message):
-+            # Ignore anything but access denied (NT_STATUS_ACCESS_DENIED)
-+            if num == -1073741790:
-+                raise access_denied_error
-+
-         try:
-             trustdom_handle = self._pipe.CreateTrustedDomainEx2(self._policy_handle, info, self.auth_info, security.SEC_STD_DELETE)
-         except RuntimeError, (num, message):
--- 
-1.8.5.3
-
diff --git a/SOURCES/0054-Remove-redefinition-of-LOG-from-ipa-otp-lasttoken.patch b/SOURCES/0054-Remove-redefinition-of-LOG-from-ipa-otp-lasttoken.patch
new file mode 100644
index 0000000..bb2d6ec
--- /dev/null
+++ b/SOURCES/0054-Remove-redefinition-of-LOG-from-ipa-otp-lasttoken.patch
@@ -0,0 +1,29 @@
+From b28d6f940b8e523d6077cddf6dbde40666428950 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 17:20:18 +0000
+Subject: [PATCH] Remove redefinition of LOG from ipa-otp-lasttoken
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+index d20fca1e705f7406362a3ba2def9ba102bd1622d..15b404dcdb6bd88c70ccc7c5fed7a5829483590b 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+@@ -47,9 +47,6 @@
+ #include "util.h"
+ 
+ #define PLUGIN_NAME               "ipa-otp-lasttoken"
+-#define LOG(sev, ...) \
+-    slapi_log_error(SLAPI_LOG_ ## sev, PLUGIN_NAME, \
+-                    "%s: %s\n", __func__, __VA_ARGS__), -1
+ 
+ static void *plugin_id;
+ static const Slapi_PluginDesc preop_desc = {
+-- 
+2.1.0
+
diff --git a/SOURCES/0054-fix-filtering-of-subdomain-based-trust-users.patch b/SOURCES/0054-fix-filtering-of-subdomain-based-trust-users.patch
deleted file mode 100644
index 4b094ce..0000000
--- a/SOURCES/0054-fix-filtering-of-subdomain-based-trust-users.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From 4b7059b4f29832d98b4ff4f266007d007ca07a19 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Fri, 28 Feb 2014 22:03:29 +0200
-Subject: [PATCH] fix filtering of subdomain-based trust users
-
-https://fedorahosted.org/freeipa/ticket/4207
----
- daemons/ipa-kdb/ipa_kdb_mspac.c | 41 ++++++++++++++++++++++++++++++++---------
- 1 file changed, 32 insertions(+), 9 deletions(-)
-
-diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
-index 9137cd5ad1e6166fd5d6e765fab2c8178ca0587c..68f27f0e2d9028cdaece80c4bd3440d0438d20db 100644
---- a/daemons/ipa-kdb/ipa_kdb_mspac.c
-+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
-@@ -806,6 +806,12 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
-     krb5_error_code kerr;
-     enum ndr_err_code ndr_err;
- 
-+    /* When no client entry is there, we cannot generate MS-PAC */
-+    if (!client) {
-+        *pac = NULL;
-+        return 0;
-+    }
-+
-     ipactx = ipadb_get_context(kcontext);
-     if (!ipactx) {
-         return KRB5_KDB_DBNOTINITED;
-@@ -1534,6 +1540,12 @@ static krb5_error_code ipadb_add_transited_service(krb5_context context,
-     uint32_t i;
-     char *tmpstr;
- 
-+    /* When proxy is NULL, authdata flag on the service principal was cleared
-+     * by an admin. We don't generate MS-PAC in this case */
-+    if (proxy == NULL) {
-+        return 0;
-+    }
-+
-     tmpctx = talloc_new(NULL);
-     if (!tmpctx) {
-         kerr = ENOMEM;
-@@ -1731,6 +1743,12 @@ static krb5_error_code ipadb_verify_pac(krb5_context context,
-     }
- 
-     if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
-+        if (proxy == NULL) {
-+            *pac = NULL;
-+            kerr = 0;
-+            goto done;
-+        }
-+
-         kerr = ipadb_add_transited_service(context, proxy, server,
-                                            old_pac, new_pac);
-         if (kerr) {
-@@ -1986,20 +2004,27 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     krb5_db_entry *client_entry = NULL;
- 
- 
--    /* When client is NULL, authdata flag on the service principal was cleared
--     * by an admin. We don't generate MS-PAC in this case */
--    if (client == NULL) {
--        *signed_auth_data = NULL;
--        return 0;
--    }
-+    is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
- 
-     /* When using s4u2proxy client_princ actually refers to the proxied user
-      * while client->princ to the proxy service asking for the TGS on behalf
-      * of the proxied user. So always use client_princ in preference */
-     if (client_princ != NULL) {
-         ks_client_princ = client_princ;
--        kerr = ipadb_get_principal(context, client_princ, flags, &client_entry);
-+        if (!is_as_req) {
-+            kerr = ipadb_get_principal(context, client_princ, flags, &client_entry);
-+            /* If we didn't find client_princ in our database, it might be:
-+             * - a principal from another realm, handle it down in ipadb_get/verify_pac()
-+             */
-+            if (!kerr) {
-+                client_entry = NULL;
-+            }
-+        }
-     } else {
-+        if (client == NULL) {
-+            *signed_auth_data = NULL;
-+            return 0;
-+        }
-         ks_client_princ = client->princ;
-     }
- 
-@@ -2014,8 +2039,6 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-                                   "currently not supported.");
-     }
- 
--    is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
--
-     if (is_as_req && with_pac && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) {
-         /* Be aggressive here: special case for discovering range type
-          * immediately after establishing the trust by IPA framework */
--- 
-1.8.5.3
-
diff --git a/SOURCES/0055-Unload-P11_Helper-object-s-library-when-it-is-finali.patch b/SOURCES/0055-Unload-P11_Helper-object-s-library-when-it-is-finali.patch
new file mode 100644
index 0000000..2a2309d
--- /dev/null
+++ b/SOURCES/0055-Unload-P11_Helper-object-s-library-when-it-is-finali.patch
@@ -0,0 +1,81 @@
+From e31080c46bfba67d6ed3ac1fa8ded1cb69e4aa97 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 17:33:23 +0000
+Subject: [PATCH] Unload P11_Helper object's library when it is finalized in
+ ipap11helper
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipapython/ipap11helper/library.c   | 5 +++++
+ ipapython/ipap11helper/p11helper.c | 9 +++++++--
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/ipapython/ipap11helper/library.c b/ipapython/ipap11helper/library.c
+index 51e24ebc2be5953a6820b768e75a3e8ccb026a64..619604dc6358e41c18c786adc64fe0326dde5f4b 100644
+--- a/ipapython/ipap11helper/library.c
++++ b/ipapython/ipap11helper/library.c
+@@ -70,6 +70,11 @@ CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle)
+ 
+ 	// Retrieve the entry point for C_GetFunctionList
+ 	pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
++	if (pGetFunctionList == NULL)
++	{
++		dlclose(pDynLib);
++		return NULL;
++	}
+ 
+ 	// Store the handle so we can dlclose it later
+ 	*moduleHandle = pDynLib;
+diff --git a/ipapython/ipap11helper/p11helper.c b/ipapython/ipap11helper/p11helper.c
+index 038c26c4520cc8f71edbee15b0ccd9bf292d7588..558185e8236b79d6c5ee0ca46afb257f5fec94ab 100644
+--- a/ipapython/ipap11helper/p11helper.c
++++ b/ipapython/ipap11helper/p11helper.c
+@@ -66,6 +66,7 @@ PyObject_HEAD
+ CK_SLOT_ID slot;
+ CK_FUNCTION_LIST_PTR p11;
+ CK_SESSION_HANDLE session;
++void *module_handle;
+ } P11_Helper;
+ 
+ typedef enum {
+@@ -478,6 +479,7 @@ P11_Helper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+         self->slot = 0;
+         self->session = 0;
+         self->p11 = NULL;
++        self->module_handle = NULL;
+     }
+ 
+     return (PyObject *) self;
+@@ -496,12 +498,12 @@ static int P11_Helper_init(P11_Helper *self, PyObject *args, PyObject *kwds) {
+     CK_C_GetFunctionList pGetFunctionList = loadLibrary(library_path,
+             &module_handle);
+     if (!pGetFunctionList) {
+-        if (module_handle != NULL)
+-            unloadLibrary(module_handle);
+         PyErr_SetString(ipap11helperError, "Could not load the library.");
+         return -1;
+     }
+ 
++    self->module_handle = module_handle;
++
+     /*
+      * Load the function list
+      */
+@@ -567,9 +569,12 @@ P11_Helper_finalize(P11_Helper* self) {
+      */
+     self->p11->C_Finalize(NULL);
+ 
++    unloadLibrary(self->module_handle);
++
+     self->p11 = NULL;
+     self->session = 0;
+     self->slot = 0;
++    self->module_handle = NULL;
+ 
+     return Py_None;
+ }
+-- 
+2.1.0
+
diff --git a/SOURCES/0055-ipa-kdb-do-not-fetch-client-principal-if-it-is-the-s.patch b/SOURCES/0055-ipa-kdb-do-not-fetch-client-principal-if-it-is-the-s.patch
deleted file mode 100644
index a736514..0000000
--- a/SOURCES/0055-ipa-kdb-do-not-fetch-client-principal-if-it-is-the-s.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 278b347c6f84140b4fc58d7c11749bbf6c44a50c Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Thu, 6 Mar 2014 10:26:29 +0200
-Subject: [PATCH] ipa-kdb: do not fetch client principal if it is the same as
- existing entry
-
-When client principal is the same as supplied client entry, don't fetch it
-again.
-
-Note that when client principal is not NULL, client entry might be NULL for
-cross-realm case, so we need to make sure to not dereference NULL pointer here.
-
-Also fix reverted condition for case when we didn't find the client principal
-in the database, preventing a memory leak.
-
-https://fedorahosted.org/freeipa/ticket/4223
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- daemons/ipa-kdb/ipa_kdb_mspac.c | 19 +++++++++++++------
- 1 file changed, 13 insertions(+), 6 deletions(-)
-
-diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
-index 68f27f0e2d9028cdaece80c4bd3440d0438d20db..8481278760aba2d5dec5c337813f394633d67e46 100644
---- a/daemons/ipa-kdb/ipa_kdb_mspac.c
-+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
-@@ -2002,6 +2002,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     bool with_pad;
-     int result;
-     krb5_db_entry *client_entry = NULL;
-+    krb5_boolean is_equal;
- 
- 
-     is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
-@@ -2012,12 +2013,18 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
-     if (client_princ != NULL) {
-         ks_client_princ = client_princ;
-         if (!is_as_req) {
--            kerr = ipadb_get_principal(context, client_princ, flags, &client_entry);
--            /* If we didn't find client_princ in our database, it might be:
--             * - a principal from another realm, handle it down in ipadb_get/verify_pac()
--             */
--            if (!kerr) {
--                client_entry = NULL;
-+            is_equal = false;
-+            if ((client != NULL) && (client->princ != NULL)) {
-+                is_equal = krb5_principal_compare(context, client_princ, client->princ);
-+            }
-+            if (!is_equal) {
-+                kerr = ipadb_get_principal(context, client_princ, flags, &client_entry);
-+                /* If we didn't find client_princ in our database, it might be:
-+                 * - a principal from another realm, handle it down in ipadb_get/verify_pac()
-+                 */
-+                if (kerr != 0) {
-+                    client_entry = NULL;
-+                }
-             }
-         }
-     } else {
--- 
-1.8.5.3
-
diff --git a/SOURCES/0056-Fix-Kerberos-error-handling-in-ipa-sam.patch b/SOURCES/0056-Fix-Kerberos-error-handling-in-ipa-sam.patch
new file mode 100644
index 0000000..7e6107e
--- /dev/null
+++ b/SOURCES/0056-Fix-Kerberos-error-handling-in-ipa-sam.patch
@@ -0,0 +1,28 @@
+From 5d835f8ace9ec1b89c67585b22cd230c497cf833 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 17:40:35 +0000
+Subject: [PATCH] Fix Kerberos error handling in ipa-sam
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ daemons/ipa-sam/ipa_sam.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
+index 3b69f9e8255490aac17d08033e2a3584c6bf9e24..e71129901b5ac1816c300b707e40c2e43d711338 100644
+--- a/daemons/ipa-sam/ipa_sam.c
++++ b/daemons/ipa-sam/ipa_sam.c
+@@ -4233,7 +4233,7 @@ static int bind_callback(LDAP *ldap_struct, struct smbldap_state *ldap_state, vo
+ 	krb5_free_principal(data.context, in_creds.server);
+ 	krb5_free_principal(data.context, in_creds.client);
+ 
+-	if (rc) {
++	if (rc != 0 && rc != KRB5KRB_AP_ERR_TKT_NYV && rc != KRB5KRB_AP_ERR_TKT_EXPIRED) {
+ 		rc = bind_callback_obtain_creds(&data);
+ 		if (rc) {
+ 			bind_callback_cleanup(&data, rc);
+-- 
+2.1.0
+
diff --git a/SOURCES/0056-ipa-replica-install-never-checks-for-7389-port.patch b/SOURCES/0056-ipa-replica-install-never-checks-for-7389-port.patch
deleted file mode 100644
index e00e968..0000000
--- a/SOURCES/0056-ipa-replica-install-never-checks-for-7389-port.patch
+++ /dev/null
@@ -1,220 +0,0 @@
-From c088cccb0b27e0defd5457f756a2d4c68e8eff55 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Tue, 11 Mar 2014 16:28:19 +0100
-Subject: [PATCH 56/58] ipa-replica-install never checks for 7389 port
-
-When creating replica from a Dogtag 9 based IPA server, the port 7389
-which is required for the installation is never checked by
-ipa-replica-conncheck even though it knows that it is being installed
-from the Dogtag 9 based FreeIPA. If the 7389 port would be blocked by
-firewall, installation would stuck with no hint to user.
-
-Make sure that the port configuration parsed from replica info file
-is used consistently in the installers.
-
-https://fedorahosted.org/freeipa/ticket/4240
-
-Reviewed-By: Petr Viktorin <pviktori@redhat.com>
----
- install/tools/ipa-ca-install      | 17 +++++------------
- install/tools/ipa-replica-install | 18 ++++++------------
- ipaserver/install/cainstance.py   | 12 +++++-------
- ipaserver/install/installutils.py | 16 ++++++++++++++++
- 4 files changed, 32 insertions(+), 31 deletions(-)
-
-diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
-index 4edd26d337a50eebe686daae539c257f706e0158..bb3e595a3df47f00b3929f546db7b04dd7eda32a 100755
---- a/install/tools/ipa-ca-install
-+++ b/install/tools/ipa-ca-install
-@@ -30,7 +30,7 @@ from ipaserver.install import installutils, service
- from ipaserver.install import certs
- from ipaserver.install.installutils import (HostnameLocalhost, ReplicaConfig,
-         expand_replica_info, read_replica_info, get_host_name, BadHostError,
--        private_ccache)
-+        private_ccache, read_replica_info_dogtag_port)
- from ipaserver.install import dsinstance, cainstance, bindinstance
- from ipaserver.install.replication import replica_conn_check
- from ipapython import version
-@@ -159,31 +159,24 @@ def main():
-             sys.exit(0)
-     config.dir = dir
-     config.setup_ca = True
-+    config.ca_ds_port = read_replica_info_dogtag_port(config.dir)
- 
-     if not ipautil.file_exists(config.dir + "/cacert.p12"):
-         print 'CA cannot be installed in CA-less setup.'
-         sys.exit(1)
- 
--    portfile = config.dir + "/dogtag_directory_port.txt"
--    if not ipautil.file_exists(portfile):
--        dogtag_master_ds_port = str(dogtag.Dogtag9Constants.DS_PORT)
--    else:
--        with open(portfile) as fd:
--            dogtag_master_ds_port = fd.read()
--
-     if not options.skip_conncheck:
-         replica_conn_check(
-             config.master_host_name, config.host_name, config.realm_name, True,
--            dogtag_master_ds_port, options.admin_password)
-+            config.ca_ds_port, options.admin_password)
- 
-     if options.skip_schema_check:
-         root_logger.info("Skipping CA DS schema check")
-     else:
--        cainstance.replica_ca_install_check(config, dogtag_master_ds_port)
-+        cainstance.replica_ca_install_check(config)
- 
-     # Configure the CA if necessary
--    CA = cainstance.install_replica_ca(
--        config, dogtag_master_ds_port, postinstall=True)
-+    CA = cainstance.install_replica_ca(config, postinstall=True)
- 
-     # We need to ldap_enable the CA now that DS is up and running
-     CA.ldap_enable('CA', config.host_name, config.dirman_password,
-diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
-index 0e7aefef48d47fefa290607e0604c014d9469fdd..e039fd1e7cb213b3269d0a5d2305a96f68e36e29 100755
---- a/install/tools/ipa-replica-install
-+++ b/install/tools/ipa-replica-install
-@@ -37,8 +37,8 @@ from ipaserver.install import memcacheinstance
- from ipaserver.install import otpdinstance
- from ipaserver.install.replication import replica_conn_check, ReplicationManager
- from ipaserver.install.installutils import (ReplicaConfig, expand_replica_info,
--                                            read_replica_info ,get_host_name,
--                                            BadHostError, private_ccache)
-+        read_replica_info, get_host_name, BadHostError, private_ccache,
-+        read_replica_info_dogtag_port)
- from ipaserver.plugins.ldap2 import ldap2
- from ipaserver.install import cainstance
- from ipalib import api, errors, util
-@@ -534,6 +534,7 @@ def main():
-             sys.exit(0)
-     config.dir = dir
-     config.setup_ca = options.setup_ca
-+    config.ca_ds_port = read_replica_info_dogtag_port(config.dir)
- 
-     if config.setup_ca and not ipautil.file_exists(config.dir + "/cacert.p12"):
-         print 'CA cannot be installed in CA-less setup.'
-@@ -541,18 +542,11 @@ def main():
- 
-     installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
- 
--    portfile = config.dir + "/dogtag_directory_port.txt"
--    if not ipautil.file_exists(portfile):
--        dogtag_master_ds_port = str(dogtag.Dogtag9Constants.DS_PORT)
--    else:
--        with open(portfile) as fd:
--            dogtag_master_ds_port = fd.read()
--
-     # check connection
-     if not options.skip_conncheck:
-         replica_conn_check(
-             config.master_host_name, config.host_name, config.realm_name,
--            options.setup_ca, dogtag_master_ds_port, options.admin_password)
-+            options.setup_ca, config.ca_ds_port, options.admin_password)
- 
- 
-     # check replica host IP resolution
-@@ -657,7 +651,7 @@ def main():
-     if options.skip_schema_check:
-         root_logger.info("Skipping CA DS schema check")
-     else:
--        cainstance.replica_ca_install_check(config, dogtag_master_ds_port)
-+        cainstance.replica_ca_install_check(config)
- 
-     # Configure ntpd
-     if options.conf_ntp:
-@@ -669,7 +663,7 @@ def main():
-     ds = install_replica_ds(config)
- 
-     # Configure the CA if necessary
--    CA = cainstance.install_replica_ca(config, dogtag_master_ds_port)
-+    CA = cainstance.install_replica_ca(config)
- 
-     # Always try to install DNS records
-     install_dns_records(config, options)
-diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
-index 52c91b68c2d073a9b1c6aedc1811aa26db046e6b..126bbae66e8a9ae8d9cc6e624745ab1cc37bf4c1 100644
---- a/ipaserver/install/cainstance.py
-+++ b/ipaserver/install/cainstance.py
-@@ -1574,7 +1574,7 @@ def is_master(self):
-         return master == 'New'
- 
- 
--def replica_ca_install_check(config, master_ds_port):
-+def replica_ca_install_check(config):
-     if not config.setup_ca:
-         return
- 
-@@ -1583,8 +1583,6 @@ def replica_ca_install_check(config, master_ds_port):
-         # Replica of old "self-signed" master - CA won't be installed
-         return
- 
--    master_ds_port = int(master_ds_port)
--
-     # Exit if we have an old-style (Dogtag 9) CA already installed
-     ca = CAInstance(config.realm_name, certs.NSS_DIR,
-         dogtag_constants=dogtag.Dogtag9Constants)
-@@ -1592,13 +1590,13 @@ def replica_ca_install_check(config, master_ds_port):
-         root_logger.info('Dogtag 9 style CA instance found')
-         sys.exit("A CA is already configured on this system.")
- 
--    if master_ds_port != dogtag.Dogtag9Constants.DS_PORT:
-+    if config.ca_ds_port != dogtag.Dogtag9Constants.DS_PORT:
-         root_logger.debug(
-             'Installing CA Replica from master with a merged database')
-         return
- 
-     # Check if the master has the necessary schema in its CA instance
--    ca_ldap_url = 'ldap://%s:%s' % (config.master_host_name, master_ds_port)
-+    ca_ldap_url = 'ldap://%s:%s' % (config.master_host_name, config.ca_ds_port)
-     objectclass = 'ipaObject'
-     root_logger.debug('Checking if IPA schema is present in %s', ca_ldap_url)
-     try:
-@@ -1627,7 +1625,7 @@ def replica_ca_install_check(config, master_ds_port):
-         exit('IPA schema missing on master CA directory server')
- 
- 
--def install_replica_ca(config, master_ds_port, postinstall=False):
-+def install_replica_ca(config, postinstall=False):
-     """
-     Install a CA on a replica.
- 
-@@ -1676,7 +1674,7 @@ def install_replica_ca(config, master_ds_port, postinstall=False):
-                           config.dirman_password, config.dirman_password,
-                           pkcs12_info=(cafile,),
-                           master_host=config.master_host_name,
--                          master_replication_port=master_ds_port,
-+                          master_replication_port=config.ca_ds_port,
-                           subject_base=config.subject_base)
- 
-     # Restart httpd since we changed it's config and added ipa-pki-proxy.conf
-diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
-index 32671adc895b0cb2632729e8bdb44b5df02c1314..8be8cd3ffa86256c096ddc99227210f2daeb3185 100644
---- a/ipaserver/install/installutils.py
-+++ b/ipaserver/install/installutils.py
-@@ -538,6 +538,22 @@ def read_replica_info(dir, rconfig):
-     except NoOptionError:
-         pass
- 
-+def read_replica_info_dogtag_port(config_dir):
-+    portfile = config_dir + "/dogtag_directory_port.txt"
-+    default_port = dogtag.Dogtag9Constants.DS_PORT
-+    if not ipautil.file_exists(portfile):
-+        dogtag_master_ds_port = default_port
-+    else:
-+        with open(portfile) as fd:
-+            try:
-+                dogtag_master_ds_port = int(fd.read())
-+            except (ValueError, IOError), e:
-+                root_logger.debug('Cannot parse dogtag DS port: %s', e)
-+                root_logger.debug('Default to %d', default_port)
-+                dogtag_master_ds_port = default_port
-+
-+    return dogtag_master_ds_port
-+
- def check_server_configuration():
-     """
-     Check if IPA server is configured on the system.
--- 
-1.8.5.3
-
diff --git a/SOURCES/0057-Avoid-passing-non-terminated-string-to-is_master_hos.patch b/SOURCES/0057-Avoid-passing-non-terminated-string-to-is_master_hos.patch
deleted file mode 100644
index 006eb6a..0000000
--- a/SOURCES/0057-Avoid-passing-non-terminated-string-to-is_master_hos.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From a8fde83022360a02e53b70fd7bd4d61de1ccc7cb Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Fri, 7 Mar 2014 10:06:52 +0100
-Subject: [PATCH 57/58] Avoid passing non-terminated string to is_master_host
-
-When string is not terminated, queries with corrupted base may be sent
-to LDAP:
-
-... cn=ipa1.example.com<garbage>,cn=masters...
-
-https://fedorahosted.org/freeipa/ticket/4214
-
-Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
----
- daemons/ipa-kdb/ipa_kdb_mspac.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
-index 8481278760aba2d5dec5c337813f394633d67e46..a73a3cb46e104b43493177e333deb2b0d6226c2a 100644
---- a/daemons/ipa-kdb/ipa_kdb_mspac.c
-+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
-@@ -488,13 +488,14 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
-         }
- 
-         data = krb5_princ_component(ipactx->context, princ, 1);
--        strres = malloc(data->length);
-+        strres = malloc(data->length+1);
-         if (strres == NULL) {
-             krb5_free_principal(ipactx->kcontext, princ);
-             return ENOENT;
-         }
- 
-         memcpy(strres, data->data, data->length);
-+        strres[data->length] = '\0';
-         krb5_free_principal(ipactx->kcontext, princ);
- 
-         /* Only add PAC to TGT to services on IPA masters to allow querying
--- 
-1.8.5.3
-
diff --git a/SOURCES/0057-Fix-unchecked-return-value-in-ipa-kdb.patch b/SOURCES/0057-Fix-unchecked-return-value-in-ipa-kdb.patch
new file mode 100644
index 0000000..7cff879
--- /dev/null
+++ b/SOURCES/0057-Fix-unchecked-return-value-in-ipa-kdb.patch
@@ -0,0 +1,28 @@
+From 253b6378741d4de5ca68fb60351ae22156a96359 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 18:10:27 +0000
+Subject: [PATCH] Fix unchecked return value in ipa-kdb
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ 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 c8f6c76fb5b3bc7d47ec8a1551579d53d226027e..a4500070760e83994c8155a12ee6414b5ebee9e0 100644
+--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
+@@ -2070,7 +2070,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
+                             krb5_princ_component(context, ks_client_princ, 1)->length,
+                             ipactx->kdc_hostname, strlen(ipactx->kdc_hostname),
+                             NULL, NULL, &result) == 0) {
+-                kerr = ipadb_reinit_mspac(ipactx, true);
++                (void)ipadb_reinit_mspac(ipactx, true);
+             }
+         }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0058-Fix-unchecked-return-values-in-ipa-winsync.patch b/SOURCES/0058-Fix-unchecked-return-values-in-ipa-winsync.patch
new file mode 100644
index 0000000..f333fd8
--- /dev/null
+++ b/SOURCES/0058-Fix-unchecked-return-values-in-ipa-winsync.patch
@@ -0,0 +1,108 @@
+From c7b939714ed7b39056c776e5b4a721dd192178bd Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 18:10:59 +0000
+Subject: [PATCH] Fix unchecked return values in ipa-winsync
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ .../ipa-winsync/ipa-winsync-config.c               | 40 +++++++++++-----------
+ 1 file changed, 20 insertions(+), 20 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c b/daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c
+index 65ceaea685a276db91aab356dab617e260095873..8b62aed41bfe4704d542e37e70e9d128fa33507e 100644
+--- a/daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c
++++ b/daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c
+@@ -905,9 +905,9 @@ ipa_winsync_config_refresh_domain(
+ 
+     if (!iwdc->realm_name) {
+         /* error - could not find the IPA config entry with the realm name */
+-        LOG_FATAL("Error: could not find the entry containing the realm name for "
+-                  "ds subtree [%s] filter [%s] attr [%s]\n",
+-                  slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr);
++        LOG_FATAL("Error: could not find the entry containing the realm name "
++                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
++                  ret, slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr);
+         goto out;
+     }
+ 
+@@ -918,9 +918,9 @@ ipa_winsync_config_refresh_domain(
+                                            &new_user_objclasses, NULL);
+     if (!new_user_objclasses) {
+         /* error - could not find the entry containing list of objectclasses */
+-        LOG_FATAL("Error: could not find the entry containing the new user objectclass list for "
+-                  "ds subtree [%s] filter [%s] attr [%s]\n",
+-                  slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr);
++        LOG_FATAL("Error: could not find the entry containing the new user objectclass list "
++                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
++                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr);
+         goto out;
+     }
+ 
+@@ -933,9 +933,9 @@ ipa_winsync_config_refresh_domain(
+                                            NULL, &iwdc->homedir_prefix);
+     if (!iwdc->homedir_prefix) {
+         /* error - could not find the home dir prefix */
+-        LOG_FATAL("Error: could not find the entry containing the home directory prefix for "
+-                  "ds subtree [%s] filter [%s] attr [%s]\n",
+-                  slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr);
++        LOG_FATAL("Error: could not find the entry containing the home directory prefix "
++                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
++                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr);
+         goto out;
+     }
+ 
+@@ -950,8 +950,8 @@ ipa_winsync_config_refresh_domain(
+                                                NULL, &iwdc->login_shell);
+         if (!iwdc->login_shell) {
+             LOG("Warning: could not find the entry containing the login shell "
+-                "attribute for ds subtree [%s] filter [%s] attr [%s]\n",
+-                slapi_sdn_get_dn(ds_subtree), new_entry_filter,
++                "attribute [%d] ds subtree [%s] filter [%s] attr [%s]\n",
++                ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter,
+                 login_shell_attr);
+         }
+     }
+@@ -969,9 +969,9 @@ ipa_winsync_config_refresh_domain(
+                                            NULL, &default_group_name);
+     if (!default_group_name) {
+         /* error - could not find the default group name */
+-        LOG_FATAL("Error: could not find the entry containing the default group name for "
+-                  "ds subtree [%s] filter [%s] attr [%s]\n",
+-                  slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr);
++        LOG_FATAL("Error: could not find the entry containing the default group name "
++                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
++                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr);
+         goto out;
+     }
+ 
+@@ -1014,9 +1014,9 @@ ipa_winsync_config_refresh_domain(
+                                                    NULL, &inactivated_group_dn);
+             if (!inactivated_group_dn) {
+                 /* error - could not find the inactivated group dn */
+-                LOG("Could not find the DN of the inactivated users group ds "
+-                    "subtree [%s] filter [%s]. Ignoring\n",
+-                    slapi_sdn_get_dn(ds_subtree), inactivated_filter);
++                LOG("Could not find the DN of the inactivated users group "
++                    "[%d] ds subtree [%s] filter [%s]. Ignoring\n",
++                    ret, slapi_sdn_get_dn(ds_subtree), inactivated_filter);
+                 goto out;
+             }
+         }
+@@ -1026,9 +1026,9 @@ ipa_winsync_config_refresh_domain(
+                                                    NULL, &activated_group_dn);
+             if (!activated_group_dn) {
+                 /* error - could not find the activated group dn */
+-                LOG("Could not find the DN of the activated users group ds "
+-                    "subtree [%s] filter [%s]. Ignoring\n",
+-                    slapi_sdn_get_dn(ds_subtree), activated_filter);
++                LOG("Could not find the DN of the activated users group "
++                    "[%d] ds subtree [%s] filter [%s]. Ignoring\n",
++                    ret, slapi_sdn_get_dn(ds_subtree), activated_filter);
+                 goto out;
+             }
+         }
+-- 
+2.1.0
+
diff --git a/SOURCES/0058-ipa-sam-cache-gid-to-sid-and-uid-to-sid-requests-in-.patch b/SOURCES/0058-ipa-sam-cache-gid-to-sid-and-uid-to-sid-requests-in-.patch
deleted file mode 100644
index cd202e4..0000000
--- a/SOURCES/0058-ipa-sam-cache-gid-to-sid-and-uid-to-sid-requests-in-.patch
+++ /dev/null
@@ -1,303 +0,0 @@
-From e5bd495a9a7d71f5dde5661d960e372bb2609965 Mon Sep 17 00:00:00 2001
-From: Jason Woods <devel@jasonwoods.me.uk>
-Date: Fri, 7 Mar 2014 16:38:24 +0000
-Subject: [PATCH 58/58] ipa-sam: cache gid to sid and uid to sid requests in
- idmap cache
-
-Add idmap_cache calls to ipa-sam to prevent huge numbers of LDAP calls to the
-directory service for gid/uid<->sid resolution.
-
-Additionally, this patch further reduces number of queries by:
- - fast fail on uidNumber=0 which doesn't exist in FreeIPA,
- - return fallback group correctly when looking up user primary group as is
-   done during init,
- - checking for group objectclass in case insensitive way
-
-Patch by Jason Woods <devel@jasonwoods.me.uk>
-
-Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
-
-https://fedorahosted.org/freeipa/ticket/4234
-and
-https://bugzilla.redhat.com/show_bug.cgi?id=1073829
-https://bugzilla.redhat.com/show_bug.cgi?id=1074314
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- daemons/ipa-sam/ipa_sam.c | 128 +++++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 114 insertions(+), 14 deletions(-)
-
-diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
-index 1ca504db4e442c834ebe44d7e3503abafd6f9602..3b69f9e8255490aac17d08033e2a3584c6bf9e24 100644
---- a/daemons/ipa-sam/ipa_sam.c
-+++ b/daemons/ipa-sam/ipa_sam.c
-@@ -82,6 +82,18 @@ struct trustAuthInOutBlob {
- 	struct AuthenticationInformationArray previous;/* [subcontext(0),flag(LIBNDR_FLAG_REMAINING)] */
- }/* [gensize,public,nopush] */;
- 
-+/* from generated idmap.h - hopefully OK */
-+enum id_type {
-+	ID_TYPE_NOT_SPECIFIED,
-+	ID_TYPE_UID,
-+	ID_TYPE_GID,
-+	ID_TYPE_BOTH
-+};
-+
-+struct unixid {
-+	uint32_t id;
-+	enum id_type type;
-+}/* [public] */;
- 
- enum ndr_err_code ndr_pull_trustAuthInOutBlob(struct ndr_pull *ndr, int ndr_flags, struct trustAuthInOutBlob *r); /*available in libndr-samba.so */
- bool sid_check_is_builtin(const struct dom_sid *sid); /* available in libpdb.so */
-@@ -91,6 +103,7 @@ char *sid_string_talloc(TALLOC_CTX *mem_ctx, const struct dom_sid *sid); /* avai
- char *sid_string_dbg(const struct dom_sid *sid); /* available in libsmbconf.so */
- char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s); /* available in libsmbconf.so */
- bool secrets_store(const char *key, const void *data, size_t size); /* available in libpdb.so */
-+void idmap_cache_set_sid2unixid(const struct dom_sid *sid, struct unixid *unix_id); /* available in libsmbconf.so */
- 
- #define LDAP_PAGE_SIZE 1024
- #define LDAP_OBJ_SAMBASAMACCOUNT "ipaNTUserAttrs"
-@@ -750,8 +763,8 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
- 	}
- 
- 	for (c = 0; values[c] != NULL; c++) {
--		if (strncmp(LDAP_OBJ_GROUPMAP, values[c]->bv_val,
--			                       values[c]->bv_len) == 0) {
-+		if (strncasecmp(LDAP_OBJ_GROUPMAP, values[c]->bv_val,
-+						   values[c]->bv_len) == 0) {
- 			break;
- 		}
- 	}
-@@ -769,6 +782,9 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
- 		}
- 
- 		unixid_from_gid(id, strtoul(gid_str, NULL, 10));
-+
-+		idmap_cache_set_sid2unixid(sid, id);
-+
- 		ret = true;
- 		goto done;
- 	}
-@@ -785,8 +801,11 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
- 
- 	unixid_from_uid(id, strtoul(value, NULL, 10));
- 
-+	idmap_cache_set_sid2unixid(sid, id);
-+
- 	ret = true;
-  done:
-+
- 	TALLOC_FREE(mem_ctx);
- 	return ret;
- }
-@@ -806,6 +825,18 @@ static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
- 	int rc;
- 	enum idmap_error_code err;
- 	TALLOC_CTX *tmp_ctx = talloc_stackframe();
-+	struct unixid id;
-+
-+	/* Fast fail if we get a request for uidNumber=0 because it currently
-+	 * will never exist in the directory
-+	 * Saves an expensive LDAP call of which failure will never be cached
-+	 */
-+	if (uid == 0) {
-+		DEBUG(3, ("ERROR: Received request for uid %u, "
-+			  "fast failing as it will never exist\n",
-+			  (unsigned int)uid));
-+		goto done;
-+	}
- 
- 	filter = talloc_asprintf(tmp_ctx,
- 				 "(&(uidNumber=%u)"
-@@ -852,6 +883,10 @@ static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
- 
- 	sid_copy(sid, user_sid);
- 
-+	unixid_from_uid(&id, uid);
-+
-+	idmap_cache_set_sid2unixid(sid, &id);
-+
- 	ret = true;
- 
- done:
-@@ -866,21 +901,30 @@ static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
- 	struct ldapsam_privates *priv =
- 		(struct ldapsam_privates *)methods->private_data;
- 	char *filter;
--	const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
-+	const char *attrs[] = { LDAP_ATTRIBUTE_SID, LDAP_ATTRIBUTE_OBJECTCLASS, NULL };
- 	LDAPMessage *result = NULL;
- 	LDAPMessage *entry = NULL;
- 	bool ret = false;
--	char *group_sid_string;
-+	char *group_sid_string = NULL;
- 	struct dom_sid *group_sid = NULL;
-+	struct berval **values;
-+	size_t c;
- 	int rc;
- 	enum idmap_error_code err;
- 	TALLOC_CTX *tmp_ctx = talloc_stackframe();
-+	struct unixid id;
- 
- 	filter = talloc_asprintf(tmp_ctx,
--				 "(&(gidNumber=%u)"
--				 "(objectClass=%s))",
-+				 "(|(&(gidNumber=%u)"
-+				     "(objectClass=%s))"
-+				   "(&(uidNumber=%u)"
-+				     "(objectClass=%s)"
-+				     "(objectClass=%s)))",
- 				 (unsigned int)gid,
--				 LDAP_OBJ_GROUPMAP);
-+				 LDAP_OBJ_GROUPMAP,
-+				 (unsigned int)gid,
-+				 LDAP_OBJ_POSIXACCOUNT,
-+				 LDAP_OBJ_SAMBASAMACCOUNT);
- 	if (filter == NULL) {
- 		DEBUG(3, ("talloc_asprintf failed\n"));
- 		goto done;
-@@ -892,14 +936,46 @@ static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
- 	}
- 	smbldap_talloc_autofree_ldapmsg(tmp_ctx, result);
- 
--	if (ldap_count_entries(priv2ld(priv), result) != 1) {
--		DEBUG(3, ("ERROR: Got %d entries for gid %u, expected one\n",
-+	if (ldap_count_entries(priv2ld(priv), result) == 0) {
-+		DEBUG(3, ("ERROR: Got %d entries for gid %u, expected at least one\n",
- 			   ldap_count_entries(priv2ld(priv), result),
- 			   (unsigned int)gid));
- 		goto done;
- 	}
- 
--	entry = ldap_first_entry(priv2ld(priv), result);
-+	for (entry = ldap_first_entry(priv2ld(priv), result);
-+		 entry != NULL;
-+		 entry = ldap_next_entry(priv2ld(priv), entry)) {
-+
-+		values = ldap_get_values_len(priv2ld(priv), entry, "objectClass");
-+		if (values == NULL) {
-+			DEBUG(10, ("Cannot find any objectclasses.\n"));
-+			goto done;
-+		}
-+
-+		for (c = 0; values[c] != NULL; c++) {
-+			if (strncasecmp(LDAP_OBJ_GROUPMAP, values[c]->bv_val,
-+							   values[c]->bv_len) == 0) {
-+				goto found;
-+			}
-+		}
-+
-+	}
-+
-+found:
-+	/* If we didn't find a group we found a user - so this is a primary group
-+	 * For user private group, use fallback group */
-+	if (entry == NULL) {
-+
-+		DEBUG(10, ("Did not find user private group %u, "
-+			   "returning fallback group.\n", (unsigned int)gid));
-+
-+		sid_copy(sid,
-+			 &priv->ipasam_privates->fallback_primary_group);
-+		ret = true;
-+		goto done;
-+
-+	}
- 
- 	group_sid_string = get_single_attribute(tmp_ctx, priv2ld(priv), entry,
- 						LDAP_ATTRIBUTE_SID);
-@@ -910,7 +986,7 @@ static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
- 	}
- 
- 	err = sss_idmap_sid_to_smb_sid(priv->ipasam_privates->idmap_ctx,
--				       group_sid_string, &group_sid);
-+					   group_sid_string, &group_sid);
- 	if (err != IDMAP_SUCCESS) {
- 		DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
- 			  group_sid_string));
-@@ -919,6 +995,10 @@ static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
- 
- 	sid_copy(sid, group_sid);
- 
-+	unixid_from_gid(&id, gid);
-+
-+	idmap_cache_set_sid2unixid(sid, &id);
-+
- 	ret = true;
- 
- done:
-@@ -2456,10 +2536,16 @@ static int delete_subtree(struct ldapsam_privates *ldap_state, char* dn)
- 	rc = smbldap_search(ldap_state->smbldap_state, dn, scope, filter, NULL, 0, &result);
- 	TALLOC_FREE(filter);
- 
--	if (result != NULL) {
--		smbldap_talloc_autofree_ldapmsg(dn, result);
-+	if (rc != LDAP_SUCCESS) {
-+		return rc;
- 	}
- 
-+	if (result == NULL) {
-+		return LDAP_NO_MEMORY;
-+	}
-+
-+	smbldap_talloc_autofree_ldapmsg(dn, result);
-+
- 	for (entry = ldap_first_entry(state, result);
- 	     entry != NULL;
- 	     entry = ldap_next_entry(state, entry)) {
-@@ -2467,6 +2553,9 @@ static int delete_subtree(struct ldapsam_privates *ldap_state, char* dn)
- 		/* remove child entries */
- 		if ((entry_dn != NULL) && (strcmp(entry_dn, dn) != 0)) {
- 			rc = smbldap_delete(ldap_state->smbldap_state, entry_dn);
-+			if (rc != LDAP_SUCCESS) {
-+				return rc;
-+			}
- 		}
- 	}
- 	rc = smbldap_delete(ldap_state->smbldap_state, dn);
-@@ -2856,6 +2945,7 @@ static int ipasam_get_sid_by_gid(struct ldapsam_privates *ldap_state,
- 	struct dom_sid *sid = NULL;
- 	int count;
- 	enum idmap_error_code err;
-+	struct unixid id;
- 
- 	tmp_ctx = talloc_new("ipasam_get_sid_by_gid");
- 	if (tmp_ctx == NULL) {
-@@ -2910,6 +3000,10 @@ static int ipasam_get_sid_by_gid(struct ldapsam_privates *ldap_state,
- 	}
- 	sid_copy(_sid, sid);
- 
-+	unixid_from_gid(&id, gid);
-+
-+	idmap_cache_set_sid2unixid(sid, &id);
-+
- 	ret = 0;
- 
- done:
-@@ -2929,6 +3023,7 @@ static int ipasam_get_primary_group_sid(TALLOC_CTX *mem_ctx,
- 	uint32_t uid;
- 	uint32_t gid;
- 	struct dom_sid *group_sid;
-+	struct unixid id;
- 
- 	TALLOC_CTX *tmp_ctx = talloc_init("ipasam_get_primary_group_sid");
- 	if (tmp_ctx == NULL) {
-@@ -2967,8 +3062,13 @@ static int ipasam_get_primary_group_sid(TALLOC_CTX *mem_ctx,
- 		}
- 	}
- 
--        ret = 0;
-+	unixid_from_gid(&id, gid);
-+
-+	idmap_cache_set_sid2unixid(group_sid, &id);
-+
-+	ret = 0;
- done:
-+
- 	if (ret == 0) {
- 		*_group_sid = talloc_steal(mem_ctx, group_sid);
- 	}
--- 
-1.8.5.3
-
diff --git a/SOURCES/0059-Fix-unchecked-return-value-in-ipa-join.patch b/SOURCES/0059-Fix-unchecked-return-value-in-ipa-join.patch
new file mode 100644
index 0000000..f78a191
--- /dev/null
+++ b/SOURCES/0059-Fix-unchecked-return-value-in-ipa-join.patch
@@ -0,0 +1,32 @@
+From e6f71d031a114cd8fbd752e1ce8e2a02007a009b Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 18:12:02 +0000
+Subject: [PATCH] Fix unchecked return value in ipa-join
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipa-client/ipa-join.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/ipa-client/ipa-join.c b/ipa-client/ipa-join.c
+index 46f64572dcaeb3be61dadf87a07520ad21fb4f47..ac8251fef3b0a03de0920e8732b44bac208f55a6 100644
+--- a/ipa-client/ipa-join.c
++++ b/ipa-client/ipa-join.c
+@@ -208,8 +208,11 @@ connect_ldap(const char *hostname, const char *binddn, const char *bindpw) {
+     struct berval bindpw_bv;
+ 
+     if (debug) {
+-        ldapdebug=2;
++        ldapdebug = 2;
+         ret = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldapdebug);
++        if (ret != LDAP_OPT_SUCCESS) {
++            goto fail;
++        }
+     }
+ 
+     if (ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, CAFILE) != LDAP_OPT_SUCCESS)
+-- 
+2.1.0
+
diff --git a/SOURCES/0059-ipaserver-dcerpc-make-sure-to-always-return-unicode-.patch b/SOURCES/0059-ipaserver-dcerpc-make-sure-to-always-return-unicode-.patch
deleted file mode 100644
index 0289984..0000000
--- a/SOURCES/0059-ipaserver-dcerpc-make-sure-to-always-return-unicode-.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 1a5cf5b28ca3143c72abaa85db59cf827d25a379 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 12 Mar 2014 17:51:43 +0200
-Subject: [PATCH 59/60] ipaserver/dcerpc: make sure to always return unicode
- SID of the trust domain
-
-Trusted domain SID could be obtained through different means. When it is
-fetched from the AD DC via LDAP, it needs to be extracted from a default
-context and explicitly converted to unicode.
-
-https://fedorahosted.org/freeipa/ticket/4246
-
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- ipaserver/dcerpc.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index 5972e622292a033d4fc979cbf5401fa02151f35c..f1c75089b875787debcee22316a4898b424d923f 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -750,7 +750,7 @@ def retrieve_anonymously(self, remote_host, discover_srv=False):
- 
-     def parse_naming_context(self, context):
-         naming_ref = re.compile('.*<SID=(S-.*)>.*')
--        return naming_ref.match(context).group(1)
-+        return unicode(naming_ref.match(context).group(1))
- 
-     def retrieve(self, remote_host):
-         self.init_lsa_pipe(remote_host)
--- 
-1.8.5.3
-
diff --git a/SOURCES/0060-Fix-unchecked-return-value-in-krb5-common-utils.patch b/SOURCES/0060-Fix-unchecked-return-value-in-krb5-common-utils.patch
new file mode 100644
index 0000000..2a04221
--- /dev/null
+++ b/SOURCES/0060-Fix-unchecked-return-value-in-krb5-common-utils.patch
@@ -0,0 +1,30 @@
+From d0f047e12c2c84ac9b5d98834bfa83c69987d681 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 10 Nov 2014 18:12:52 +0000
+Subject: [PATCH] Fix unchecked return value in krb5 common utils
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ util/ipa_krb5.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
+index 6334ed3b09b91a79648a16c0fd60dd6ff00d2fa2..feb23eae9099b83b96a26cf36b7cbc31b478c4f6 100644
+--- a/util/ipa_krb5.c
++++ b/util/ipa_krb5.c
+@@ -730,6 +730,10 @@ struct berval *create_key_control(struct keys_container *keys,
+ 
+         if (ksdata[i].salttype == NO_SALT) {
+             ret = ber_printf(be, "}");
++            if (ret == -1) {
++                ber_free(be, 1);
++                return NULL;
++            }
+             continue;
+         }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0060-trust-do-not-fetch-subdomains-in-case-shared-secret-.patch b/SOURCES/0060-trust-do-not-fetch-subdomains-in-case-shared-secret-.patch
deleted file mode 100644
index f2d8e65..0000000
--- a/SOURCES/0060-trust-do-not-fetch-subdomains-in-case-shared-secret-.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From f06e746602f34a1c60580fe3bbb105a8a1cab8a2 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Wed, 12 Mar 2014 19:01:00 +0200
-Subject: [PATCH 60/60] trust: do not fetch subdomains in case shared secret
- was used to set up the trust
-
-Until incoming trust is validated from AD side, we cannot run any operations
-against AD using the trust. Also, Samba currently does not suport verifying
-trust against the other party (returns WERR_NOT_SUPPORTED).
-
-This needs to be added to the documentation:
-
-   When using 'ipa trust-add ad.domain --trust-secret', one has to manually
-   validate incoming trust using forest trust properties in AD Domains and
-   Trusts tool.
-
-   Once incoming trust is validated at AD side, use IPA command
-   'ipa trust-fetch-domains ad.domain' to retrieve topology of the AD forest.
-   From this point on the trust should be usable.
-
-https://fedorahosted.org/freeipa/ticket/4246
-
-Reviewed-By: Martin Kosek <mkosek@redhat.com>
----
- ipalib/plugins/trust.py | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
-index f2b00a6f58f5890e37aaa033a35dcf9bc39ccbc4..fe2795cad86e173a150f35db6301119930463a10 100644
---- a/ipalib/plugins/trust.py
-+++ b/ipalib/plugins/trust.py
-@@ -462,7 +462,8 @@ def execute(self, *keys, **options):
-         # for AD trusts, regardless of the type of idranges associated with it
-         # Note that fetch_domains_from_trust will add needed ranges for
-         # the algorithmic ID mapping case.
--        if options.get('trust_type') == u'ad':
-+        if (options.get('trust_type') == u'ad' and
-+            options.get('trust_secret') is None):
-             domains = fetch_domains_from_trust(self, self.trustinstance,
-                                                result['result'], **options)
- 
--- 
-1.8.5.3
-
diff --git a/SOURCES/0061-Fix-memory-leak-in-GetKeytabControl-asn1-code.patch b/SOURCES/0061-Fix-memory-leak-in-GetKeytabControl-asn1-code.patch
new file mode 100644
index 0000000..79d12ca
--- /dev/null
+++ b/SOURCES/0061-Fix-memory-leak-in-GetKeytabControl-asn1-code.patch
@@ -0,0 +1,52 @@
+From 456593766c073ab9ea43052d7bb0fceffbff2221 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 24 Nov 2014 13:57:10 +0000
+Subject: [PATCH] Fix memory leak in GetKeytabControl asn1 code
+
+https://fedorahosted.org/freeipa/ticket/4713
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ asn1/ipa_asn1.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/asn1/ipa_asn1.c b/asn1/ipa_asn1.c
+index 50851a804f59bdb3fcb9ba832b093860d914452d..9efca964ac340208f478483ecfbb70b32d72181c 100644
+--- a/asn1/ipa_asn1.c
++++ b/asn1/ipa_asn1.c
+@@ -77,12 +77,12 @@ bool ipaasn1_enc_getktreply(int kvno, struct keys_container *keys,
+ {
+     GetKeytabControl_t gkctrl = { 0 };
+     bool ret = false;
++    KrbKey_t *KK;
+ 
+     gkctrl.present = GetKeytabControl_PR_reply;
+     gkctrl.choice.reply.newkvno = kvno;
+ 
+     for (int i = 0; i < keys->nkeys; i++) {
+-        KrbKey_t *KK;
+         KK = calloc(1, sizeof(KrbKey_t));
+         if (!KK) goto done;
+         KK->key.type = keys->ksdata[i].key.enctype;
+@@ -109,9 +109,18 @@ bool ipaasn1_enc_getktreply(int kvno, struct keys_container *keys,
+     }
+ 
+     ret = encode_GetKeytabControl(&gkctrl, buf, len);
++    KK = NULL;
+ 
+ done:
+     ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetKeytabControl, &gkctrl);
++    if (KK) {
++        free(KK->key.value.buf);
++        if (KK->salt) {
++            free(KK->salt->value.buf);
++            free(KK->salt);
++        }
++        free(KK);
++    }
+     return ret;
+ }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0061-Update-Dogtag-9-database-during-replica-installation.patch b/SOURCES/0061-Update-Dogtag-9-database-during-replica-installation.patch
deleted file mode 100644
index fc97678..0000000
--- a/SOURCES/0061-Update-Dogtag-9-database-during-replica-installation.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-From 2e031c9469f0313014dbe8c47d0be3fee370f287 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Thu, 13 Mar 2014 08:25:11 +0100
-Subject: [PATCH] Update Dogtag 9 database during replica installation
-
-When Dogtag 10 based FreeIPA replica is being installed for a Dogtag 9
-based master, the PKI database is not updated and miss several ACLs
-which prevent some of the PKI functions, e.g. an ability to create
-other clones.
-
-Add an update file to do the database update. Content is based on
-recommendation from PKI team:
-   * https://bugzilla.redhat.com/show_bug.cgi?id=1075118#c9
-
-This update file can be removed when Dogtag database upgrades are done
-in PKI component. Upstream tickets:
-   * https://fedorahosted.org/pki/ticket/710 (database upgrade framework)
-   * https://fedorahosted.org/pki/ticket/906 (checking database version)
-
-Also make sure that PKI service is restarted in the end of the installation
-as the other services to make sure it picks changes done during LDAP
-updates.
-
-https://fedorahosted.org/freeipa/ticket/4243
----
- install/tools/ipa-replica-install            |  4 ++++
- install/tools/ipa-server-install             |  4 ++++
- install/updates/50-dogtag10-migration.update | 18 ++++++++++++++++++
- install/updates/Makefile.am                  |  1 +
- 4 files changed, 27 insertions(+)
- create mode 100644 install/updates/50-dogtag10-migration.update
-
-diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
-index e039fd1e7cb213b3269d0a5d2305a96f68e36e29..4418b41784313121e73b560ee84715ddeba8bc54 100755
---- a/install/tools/ipa-replica-install
-+++ b/install/tools/ipa-replica-install
-@@ -704,6 +704,10 @@ def main():
-     service.print_msg("Restarting the KDC")
-     krb.restart()
- 
-+    if CA and config.setup_ca:
-+        service.print_msg("Restarting the certificate server")
-+        CA.restart(dogtag.configured_constants().PKI_INSTANCE_NAME)
-+
-     if options.setup_dns:
-         install_bind(config, options)
- 
-diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
-index 458ebba550d0fe7675bd874e23c7d730c53297e6..dfbbb91bf3bb8461333193b5a3e72c3ec06d4582 100755
---- a/install/tools/ipa-server-install
-+++ b/install/tools/ipa-server-install
-@@ -1186,6 +1186,10 @@ def main():
-     service.print_msg("Restarting the KDC")
-     krb.restart()
- 
-+    if setup_ca:
-+        service.print_msg("Restarting the certificate server")
-+        ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME)
-+
-     # Create a BIND instance
-     bind = bindinstance.BindInstance(fstore, dm_password)
-     bind.setup(host_name, ip_address, realm_name, domain_name, dns_forwarders,
-diff --git a/install/updates/50-dogtag10-migration.update b/install/updates/50-dogtag10-migration.update
-new file mode 100644
-index 0000000000000000000000000000000000000000..d718923544f0cb00f61b7b56940695e3891c4780
---- /dev/null
-+++ b/install/updates/50-dogtag10-migration.update
-@@ -0,0 +1,18 @@
-+# PKI/Dogtag does not automatically upgrade it's database. When Dogtag 10
-+# based replica is being installed from a Dogtag 9 based replica,
-+# the database will miss ACLs added in Dogtag 10 resulting in limited
-+# functionality.
-+#
-+# This update file can be removed when Dogtag database upgrades are done
-+# in PKI component. Upstream tickets:
-+#    * https://fedorahosted.org/pki/ticket/710 (database upgrade framework)
-+#    * https://fedorahosted.org/pki/ticket/906 (checking database version)
-+
-+dn: cn=aclResources,o=ipaca
-+addifexist:resourceACLS:'certServer.ca.account:login,logout:allow (login,logout) user="anybody":Anybody can login and logout'
-+addifexist:resourceACLS:'certServer.ca.certrequests:execute:allow (execute) group="Certificate Manager Agents":Agents may execute cert request operations'
-+addifexist:resourceACLS:'certServer.ca.certs:execute:allow (execute) group="Certificate Manager Agents":Agents may execute cert operations'
-+addifexist:resourceACLS:'certServer.ca.groups:execute:allow (execute) group="Administrators":Admins may execute group operations'
-+addifexist:resourceACLS:'certServer.ca.users:execute:allow (execute) group="Administrators":Admins may execute user operations'
-+replace:resourceACLS:'certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group":Anybody is allowed to read domain.xml but only Subsystem group is allowed to modify the domain.xml::certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group" || group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise RA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TKS Administrators" || group="Enterprise TPS Administrators":Anybody is allowed to read domain.xml but only Subsystem group and Enterprise Administrators are allowed to modify the domain.xml'
-+replace:resourceACLS:'certServer.ca.connectorInfo:read,modify:allow (modify,read) group="Enterprise KRA Administrators":Only Enterprise Administrators are allowed to update the connector information::certServer.ca.connectorInfo:read,modify:allow (read) group="Enterprise KRA Administrators";allow (modify) group="Enterprise KRA Administrators" || group="Subsystem Group":Only Enterprise Administrators and Subsystem Group are allowed to update the connector information'
-diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
-index 40c3b3c8916faa267254a29d0f458ca53201950c..fb73c410dbcd1978c3a5deeb184dc10cdba866ae 100644
---- a/install/updates/Makefile.am
-+++ b/install/updates/Makefile.am
-@@ -36,6 +36,7 @@ app_DATA =				\
- 	40-otp.update			\
- 	45-roles.update			\
- 	50-7_bit_check.update	        \
-+	50-dogtag10-migration.update	\
- 	50-lockout-policy.update	\
- 	50-groupuuid.update		\
- 	50-hbacservice.update		\
--- 
-1.8.5.3
-
diff --git a/SOURCES/0062-AD-trust-improve-trust-validation.patch b/SOURCES/0062-AD-trust-improve-trust-validation.patch
new file mode 100644
index 0000000..2bd259d
--- /dev/null
+++ b/SOURCES/0062-AD-trust-improve-trust-validation.patch
@@ -0,0 +1,75 @@
+From 6d3e68480293b50cf3ac40ad09f3ab48de764089 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Mon, 24 Nov 2014 15:07:49 +0200
+Subject: [PATCH] AD trust: improve trust validation
+
+Trust validation requires AD DC to contact IPA server to verify that trust account
+actually works. It can fail due to DNS or firewall issue or if AD DC was able to
+resolve IPA master(s) via SRV records, it still may contact a replica that has
+no trust data replicated yet.
+
+In case AD DC still returns 'access denied', wait 5 seconds and try validation again.
+Repeat validation until we hit a limit of 10 attempts, at which point raise
+exception telling what's happening.
+
+https://fedorahosted.org/freeipa/ticket/4764
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ ipaserver/dcerpc.py | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
+index caeca3c4ab357193aef4d0e6a373240acfdf1993..e342c4973746a113c0ad4f15a1e6050583461ccf 100644
+--- a/ipaserver/dcerpc.py
++++ b/ipaserver/dcerpc.py
+@@ -58,6 +58,7 @@ import pysss
+ from ipaplatform.paths import paths
+ 
+ from ldap.filter import escape_filter_chars
++from time import sleep
+ 
+ __doc__ = _("""
+ Classes to manage trust joins using DCE-RPC calls
+@@ -93,6 +94,8 @@ dcerpc_error_codes = {
+ dcerpc_error_messages = {
+     "NT_STATUS_OBJECT_NAME_NOT_FOUND":
+          errors.NotFound(reason=_('Cannot find specified domain or server name')),
++    "WERR_NO_LOGON_SERVERS":
++         errors.RemoteRetrieveError(reason=_('AD DC was unable to reach any IPA domain controller. Most likely it is a DNS or firewall issue')),
+     "NT_STATUS_INVALID_PARAMETER_MIX":
+          errors.RequirementError(name=_('At least the domain or IP address should be specified')),
+ }
+@@ -699,6 +702,7 @@ class TrustDomainInstance(object):
+         self._policy_handle = None
+         self.read_only = False
+         self.ftinfo_records = None
++        self.validation_attempts = 0
+ 
+     def __gen_lsa_connection(self, binding):
+        if self.creds is None:
+@@ -1011,9 +1015,18 @@ class TrustDomainInstance(object):
+                                           netlogon.NETLOGON_CONTROL_TC_VERIFY,
+                                           another_domain.info['dns_domain'])
+         if (result and (result.flags and netlogon.NETLOGON_VERIFY_STATUS_RETURNED)):
+-            # netr_LogonControl2Ex() returns non-None result only if overall call
+-            # result was WERR_OK which means verification was correct.
+-            # We only check that it was indeed status for verification process
++            if (result.pdc_connection_status[0] != 0) and (result.tc_connection_status[0] != 0):
++                if result.pdc_connection_status[1] == "WERR_ACCESS_DENIED":
++                    # Most likely AD DC hit another IPA replica which yet has no trust secret replicated
++                    # Sleep and repeat again
++                    self.validation_attempts += 1
++                    if self.validation_attempts < 10:
++                        sleep(5)
++                        return self.verify_trust(another_domain)
++                    raise errors.ACIError(reason=_('IPA master denied trust validation requests from AD DC '
++                                                   '%(count)d times. Most likely AD DC contacted a replica '
++                                                   'that has no trust information replicated yet.' % (self.validation_attempts)))
++                raise assess_dcerpc_exception(*result.pdc_connection_status)
+             return True
+         return False
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0062-Prohibit-deletion-of-active-subdomain-range.patch b/SOURCES/0062-Prohibit-deletion-of-active-subdomain-range.patch
deleted file mode 100644
index 3820074..0000000
--- a/SOURCES/0062-Prohibit-deletion-of-active-subdomain-range.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 35916294df8acc87e70c6b6796c644824caed64a Mon Sep 17 00:00:00 2001
-From: Tomas Babej <tbabej@redhat.com>
-Date: Thu, 13 Mar 2014 12:36:17 +0100
-Subject: [PATCH] Prohibit deletion of active subdomain range
-
-Changes the code in the idrange_del method to not only check for
-the root domains that match the SID in the IDRange, but for the
-SIDs of subdomains of trusts as well.
-
-https://fedorahosted.org/freeipa/ticket/4247
-
-Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
----
- ipalib/plugins/idrange.py | 20 ++++++++++++++++----
- 1 file changed, 16 insertions(+), 4 deletions(-)
-
-diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
-index cf74a75ffda42b2d2e40d2ab35c79ed069dd0f52..56ef4bba3ad0203d7d2462db6c4de90e1cb555cd 100644
---- a/ipalib/plugins/idrange.py
-+++ b/ipalib/plugins/idrange.py
-@@ -567,14 +567,26 @@ class idrange_del(LDAPDelete):
-         range_sid = old_attrs.get('ipanttrusteddomainsid')
- 
-         if range_sid is not None:
-+            # Search for trusted domain with SID specified in the ID range entry
-             range_sid = range_sid[0]
--            result = api.Command['trust_find'](ipanttrusteddomainsid=range_sid)
-+            domain_filter=('(&(objectclass=ipaNTTrustedDomain)'
-+                           '(ipanttrusteddomainsid=%s))' % range_sid)
- 
--            if result['count'] > 0:
-+            try:
-+                (trust_domains, truncated) = ldap.find_entries(
-+                    base_dn=DN(api.env.container_trusts, api.env.basedn),
-+                    filter=domain_filter)
-+            except errors.NotFound:
-+                pass
-+            else:
-+                # If there's an entry, it means that there's active domain
-+                # of a trust that this range belongs to, so raise a
-+                # DependentEntry error
-                 raise errors.DependentEntry(
--                    label='Active Trust',
-+                    label='Active Trust domain',
-                     key=keys[0],
--                    dependent=result['result'][0]['cn'][0])
-+                    dependent=trust_domains[0].dn[0].value)
-+
- 
-         return dn
- 
--- 
-1.8.5.3
-
diff --git a/SOURCES/0063-Add-TLS-1.2-to-the-protocol-list-in-mod_nss-config.patch b/SOURCES/0063-Add-TLS-1.2-to-the-protocol-list-in-mod_nss-config.patch
new file mode 100644
index 0000000..647bde3
--- /dev/null
+++ b/SOURCES/0063-Add-TLS-1.2-to-the-protocol-list-in-mod_nss-config.patch
@@ -0,0 +1,72 @@
+From 6b1fe8db7d5bb08899b3b1ed4a8a48e82d73f13e Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 25 Nov 2014 08:12:53 +0000
+Subject: [PATCH] Add TLS 1.2 to the protocol list in mod_nss config
+
+https://fedorahosted.org/freeipa/ticket/4653
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ install/tools/ipa-upgradeconfig   | 13 +++++++++++++
+ ipaserver/install/httpinstance.py |  7 ++++---
+ 2 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index 3484f8e8768fe05dddb08e9a40e58d8ad9c2e1e7..6b687fbd73d01f6574cd8ea3193cedba4d5c0e67 100644
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -1274,6 +1274,18 @@ def fix_trust_flags():
+     sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True)
+ 
+ 
++def update_mod_nss_protocol(http):
++    root_logger.info('[Updating mod_nss protocol versions]')
++
++    if sysupgrade.get_upgrade_state('nss.conf', 'protocol_updated_tls12'):
++        root_logger.info("Protocol versions already updated")
++        return
++
++    http.set_mod_nss_protocol()
++
++    sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12', True)
++
++
+ def main():
+     """
+     Get some basics about the system. If getting those basics fail then
+@@ -1375,6 +1387,7 @@ def main():
+     http.change_mod_nss_port_from_http()
+ 
+     http.stop()
++    update_mod_nss_protocol(http)
+     fix_trust_flags()
+     http.start()
+ 
+diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
+index 14efa5b937784054bd6aace9ba4cda8f0b46aeb6..f9e020039734c7ff61e06ead0e30fb28701d6fc8 100644
+--- a/ipaserver/install/httpinstance.py
++++ b/ipaserver/install/httpinstance.py
+@@ -115,7 +115,8 @@ class HTTPInstance(service.Service):
+ 
+ 
+         self.step("setting mod_nss port to 443", self.__set_mod_nss_port)
+-        self.step("setting mod_nss protocol list to TLSv1.0 and TLSv1.1", self.__set_mod_nss_protocol)
++        self.step("setting mod_nss protocol list to TLSv1.0 - TLSv1.2",
++                  self.set_mod_nss_protocol)
+         self.step("setting mod_nss password file", self.__set_mod_nss_passwordfile)
+         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
+         self.step("adding URL rewriting rules", self.__add_include)
+@@ -205,8 +206,8 @@ class HTTPInstance(service.Service):
+     def __set_mod_nss_nickname(self, nickname):
+         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSNickname', nickname)
+ 
+-    def __set_mod_nss_protocol(self):
+-        installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSProtocol', 'TLSv1.0,TLSv1.1', False)
++    def set_mod_nss_protocol(self):
++        installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSProtocol', 'TLSv1.0,TLSv1.1,TLSv1.2', False)
+ 
+     def enable_mod_nss_renegotiate(self):
+         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRenegotiation', 'on', False)
+-- 
+2.1.0
+
diff --git a/SOURCES/0063-extdom-do-not-return-results-from-the-wrong-domain.patch b/SOURCES/0063-extdom-do-not-return-results-from-the-wrong-domain.patch
deleted file mode 100644
index fdaa145..0000000
--- a/SOURCES/0063-extdom-do-not-return-results-from-the-wrong-domain.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 8d8cbc740af171a24e768fd6e4af17013d1fa261 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 25 Mar 2014 11:29:58 +0100
-Subject: [PATCH] extdom: do not return results from the wrong domain
-
-Resolves: https://fedorahosted.org/freeipa/ticket/4264
-Reviewed-By: Tomas Babej <tbabej@redhat.com>
----
- .../ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c   | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
-index 675fc368042373314e9416dcf7d5866cb8c9871e..025d37dc5eda05c8db43d4e8176fd7898ed32fe7 100644
---- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
-+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
-@@ -359,6 +359,9 @@ int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                         if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                             if (strcasecmp(locat+1, domain_name) == 0  ) {
-                                 locat[0] = 0;
-+                            } else {
-+                                ret = LDAP_NO_SUCH_OBJECT;
-+                                goto done;
-                             }
-                         }
-                         res->data.name.object_name =
-@@ -368,6 +371,9 @@ int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                         if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                             if (strcasecmp(locat+1, domain_name) == 0) {
-                                 locat[0] = 0;
-+                            } else {
-+                                ret = LDAP_NO_SUCH_OBJECT;
-+                                goto done;
-                             }
-                         }
-                         res->data.name.object_name =
-@@ -408,6 +414,9 @@ int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                     if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                         if (strcasecmp(locat+1, domain_name) == 0) {
-                             locat[0] = 0;
-+                        } else {
-+                            ret = LDAP_NO_SUCH_OBJECT;
-+                            goto done;
-                         }
-                     }
-                     res->data.user.user_name =
-@@ -428,6 +437,9 @@ int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                     if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                         if (strcasecmp(locat+1, domain_name) == 0) {
-                             locat[0] = 0;
-+                        } else {
-+                            ret = LDAP_NO_SUCH_OBJECT;
-+                            goto done;
-                         }
-                     }
-                     res->data.group.group_name =
--- 
-1.8.5.3
-
diff --git a/SOURCES/0064-Proxy-PKI-clone-ca-ee-ca-profileSubmit-URI.patch b/SOURCES/0064-Proxy-PKI-clone-ca-ee-ca-profileSubmit-URI.patch
deleted file mode 100644
index ab22fb9..0000000
--- a/SOURCES/0064-Proxy-PKI-clone-ca-ee-ca-profileSubmit-URI.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 8e8a020f8d2476cca321349fa24db4bee95270d8 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Thu, 20 Mar 2014 09:34:53 +0100
-Subject: [PATCH] Proxy PKI clone /ca/ee/ca/profileSubmit URI
-
-PKI change done in ticket https://fedorahosted.org/pki/ticket/816
-requires the PKI Clone's SSL Server certificate to be issued by
-it's associated PKI master.
-
-Allow this call on IPA master.
-
-https://fedorahosted.org/freeipa/ticket/4265
-
-Reviewed-By: Jan Cholasta <jcholast@redhat.com>
----
- install/conf/ipa-pki-proxy.conf | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/install/conf/ipa-pki-proxy.conf b/install/conf/ipa-pki-proxy.conf
-index 6f0463242b75a58cf63a38e62c23fa372aeacf64..224cdd45b5b5f72671a179570fd15772fe8cfaab 100644
---- a/install/conf/ipa-pki-proxy.conf
-+++ b/install/conf/ipa-pki-proxy.conf
-@@ -1,9 +1,9 @@
--# VERSION 3 - DO NOT REMOVE THIS LINE
-+# VERSION 4 - DO NOT REMOVE THIS LINE
- 
- ProxyRequests Off
- 
- # matches for ee port
--<LocationMatch "^/ca/ee/ca/checkRequest|^/ca/ee/ca/getCertChain|^/ca/ee/ca/getTokenInfo|^/ca/ee/ca/tokenAuthenticate|^/ca/ocsp|^/ca/ee/ca/updateNumberRange|^/ca/ee/ca/getCRL">
-+<LocationMatch "^/ca/ee/ca/checkRequest|^/ca/ee/ca/getCertChain|^/ca/ee/ca/getTokenInfo|^/ca/ee/ca/tokenAuthenticate|^/ca/ocsp|^/ca/ee/ca/updateNumberRange|^/ca/ee/ca/getCRL|^/ca/ee/ca/profileSubmit">
-     NSSOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
-     NSSVerifyClient none
-     ProxyPassMatch ajp://localhost:$DOGTAG_PORT
--- 
-1.8.5.3
-
diff --git a/SOURCES/0064-webui-add-radius-fields-to-user-page.patch b/SOURCES/0064-webui-add-radius-fields-to-user-page.patch
new file mode 100644
index 0000000..57e905c
--- /dev/null
+++ b/SOURCES/0064-webui-add-radius-fields-to-user-page.patch
@@ -0,0 +1,39 @@
+From 86a59f4a86fd0e7b60143aeb30ada95fad0f3f5f Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 13 Nov 2014 13:08:16 +0100
+Subject: [PATCH] webui: add radius fields to user page
+
+add --radius=ID --radius-username=radiusUserName to Web UI
+
+https://fedorahosted.org/freeipa/ticket/4686
+
+Reviewed-By: Tomas Babej <tbabej@redhat.com>
+---
+ install/ui/src/freeipa/user.js | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
+index be01170b79b14f9094ba2a43a0a245d145df0cdf..4f53a27cf36ca65fe971982006062ad3b15d87c9 100644
+--- a/install/ui/src/freeipa/user.js
++++ b/install/ui/src/freeipa/user.js
+@@ -159,6 +159,17 @@ return {
+                                 { label: '@i18n:authtype.type_otp', value: 'otp' }
+                             ],
+                             tooltip: '@i18n:authtype.user_tooltip'
++                        },
++                        {
++                            $type: 'entity_select',
++                            name: 'ipatokenradiusconfiglink',
++                            flags: ['w_if_no_aci'],
++                            other_entity: 'radiusproxy',
++                            other_field: 'cn'
++                        },
++                        {
++                            name: 'ipatokenradiususername',
++                            flags: ['w_if_no_aci']
+                         }
+                     ]
+                 },
+-- 
+2.1.0
+
diff --git a/SOURCES/0065-Fix-zonemgr-option-encoding-detection.patch b/SOURCES/0065-Fix-zonemgr-option-encoding-detection.patch
new file mode 100644
index 0000000..e4698df
--- /dev/null
+++ b/SOURCES/0065-Fix-zonemgr-option-encoding-detection.patch
@@ -0,0 +1,30 @@
+From 818fb211ae6e66de4014036cf2a003ade42a5c4a Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Tue, 25 Nov 2014 14:03:27 +0100
+Subject: [PATCH] Fix zonemgr option encoding detection
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4766
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/bindinstance.py | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
+index f02fe8647dd38d05734311406152c50108077561..547cf19ee36140b5f29fcf7d217933fa68e1952b 100644
+--- a/ipaserver/install/bindinstance.py
++++ b/ipaserver/install/bindinstance.py
+@@ -405,7 +405,10 @@ def zonemgr_callback(option, opt_str, value, parser):
+         # validate the value first
+         try:
+             # IDNA support requires unicode
+-            value = value.decode(getattr(sys.stdin, 'encoding', 'utf-8'))
++            encoding = getattr(sys.stdin, 'encoding', None)
++            if encoding is None:
++                encoding = 'utf-8'
++            value = value.decode(encoding)
+             validate_zonemgr_str(value)
+         except ValueError, e:
+             parser.error("invalid zonemgr: " + unicode(e))
+-- 
+2.1.0
+
diff --git a/SOURCES/0065-Make-ipa-client-automount-backwards-compatible.patch b/SOURCES/0065-Make-ipa-client-automount-backwards-compatible.patch
deleted file mode 100644
index dd62f62..0000000
--- a/SOURCES/0065-Make-ipa-client-automount-backwards-compatible.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From cebfd91869bdc22fa8f72c4e47d32cac73487e45 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Tue, 1 Apr 2014 16:23:14 +0200
-Subject: [PATCH] Make ipa-client-automount backwards compatible
-
-ipa-client-automount calls automountlocation-show command during the
-process. Unfortunately, FreeIPA commands are forward compatible only
-and thus fail the installer.
-
-Similarly to ipa-client-install, call XML-RPC interface directly
-with version fixed to 2.0 (command was already available at that
-version) to fix the failure.
-
-https://fedorahosted.org/freeipa/ticket/4290
----
- ipa-client/ipa-install/ipa-client-automount | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/ipa-client/ipa-install/ipa-client-automount b/ipa-client/ipa-install/ipa-client-automount
-index 62531bfe1d923b1705aed1187da6766b54c90a0c..77829b927e8c1772598d1a4e590c3f99977aa8eb 100755
---- a/ipa-client/ipa-install/ipa-client-automount
-+++ b/ipa-client/ipa-install/ipa-client-automount
-@@ -440,7 +440,12 @@ def main():
-         except errors.KerberosError, e:
-             sys.exit('Cannot connect to the server due to ' + str(e))
-         try:
--            api.Command['automountlocation_show'](unicode(options.location))
-+            # Use the RPC directly so older servers are supported
-+            result = api.Backend.xmlclient.forward(
-+                'automountlocation_show',
-+                unicode(options.location),
-+                version=u'2.0',
-+            )
-         except errors.VersionError, e:
-             sys.exit('This client is incompatible: ' + str(e))
-         except errors.NotFound:
--- 
-1.8.5.3
-
diff --git a/SOURCES/0066-Catch-USBError-during-YubiKey-location.patch b/SOURCES/0066-Catch-USBError-during-YubiKey-location.patch
new file mode 100644
index 0000000..157f4c8
--- /dev/null
+++ b/SOURCES/0066-Catch-USBError-during-YubiKey-location.patch
@@ -0,0 +1,40 @@
+From 238225b49c52d44ab926c97c0f3bf9d93230d99a Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Fri, 7 Nov 2014 10:47:43 -0500
+Subject: [PATCH] Catch USBError during YubiKey location
+
+https://fedorahosted.org/freeipa/ticket/4693
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ipalib/plugins/otptoken_yubikey.py | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/ipalib/plugins/otptoken_yubikey.py b/ipalib/plugins/otptoken_yubikey.py
+index 7095887ac7cdf5d4b7d0d30edc6cab0222246664..4c2594182c08a9de3f2f5861aac60b39a9ce022a 100644
+--- a/ipalib/plugins/otptoken_yubikey.py
++++ b/ipalib/plugins/otptoken_yubikey.py
+@@ -25,6 +25,7 @@ from ipalib.plugins.otptoken import otptoken
+ 
+ import os
+ 
++import usb.core
+ import yubico
+ 
+ __doc__ = _("""
+@@ -81,8 +82,10 @@ class otptoken_add_yubikey(Command):
+         # Open the YubiKey
+         try:
+             yk = yubico.find_yubikey()
+-        except yubico.yubikey.YubiKeyError, e:
+-            raise NotFound(reason=_('No YubiKey found'))
++        except usb.core.USBError as e:
++            raise NotFound(reason="No YubiKey found: %s" % e.strerror)
++        except yubico.yubikey.YubiKeyError as e:
++            raise NotFound(reason=e.reason)
+ 
+         assert yk.version_num() >= (2, 1)
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0066-Convert-external-CA-chain-to-PKCS-7-before-passing-i.patch b/SOURCES/0066-Convert-external-CA-chain-to-PKCS-7-before-passing-i.patch
deleted file mode 100644
index 09ecea3..0000000
--- a/SOURCES/0066-Convert-external-CA-chain-to-PKCS-7-before-passing-i.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From 15c68b5ab6441a443f0a135da2b553ee1f9cbcf9 Mon Sep 17 00:00:00 2001
-From: Jan Cholasta <jcholast@redhat.com>
-Date: Fri, 8 Aug 2014 10:15:26 +0200
-Subject: [PATCH] Convert external CA chain to PKCS#7 before passing it to
- pkispawn.
-
-https://fedorahosted.org/freeipa/ticket/4397
----
- install/tools/ipa-server-install       |  6 +++---
- install/tools/man/ipa-server-install.1 | 10 +++++++---
- ipaserver/install/cainstance.py        | 13 ++++++++++++-
- 3 files changed, 22 insertions(+), 7 deletions(-)
-
-diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
-index dfbbb91bf3bb8461333193b5a3e72c3ec06d4582..feea616b089261bf46392d5514e6e3cc9e12fcac 100755
---- a/install/tools/ipa-server-install
-+++ b/install/tools/ipa-server-install
-@@ -174,11 +174,11 @@ def parse_options():
- 
-     cert_group = OptionGroup(parser, "certificate system options")
-     cert_group.add_option("", "--external-ca", dest="external_ca", action="store_true",
--                      default=False, help="Generate a CSR to be signed by an external CA")
-+                      default=False, help="Generate a CSR for the IPA CA certificate to be signed by an external CA")
-     cert_group.add_option("", "--external_cert_file", dest="external_cert_file",
--                      help="PEM file containing a certificate signed by the external CA")
-+                      help="File containing the IPA CA certificate signed by the external CA in PEM format")
-     cert_group.add_option("", "--external_ca_file", dest="external_ca_file",
--                      help="PEM file containing the external CA chain")
-+                      help="File containing the external CA certificate chain in PEM format")
-     cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
-                       default=True, help="disables pkinit setup steps")
-     cert_group.add_option("--dirsrv_pkcs12", dest="dirsrv_pkcs12",
-diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
-index 4adf1d037517bb211bd4c5e5e915380777e8f337..d713d2db4cb863dff77e451b22c5a9b1fbbfeecd 100644
---- a/install/tools/man/ipa-server-install.1
-+++ b/install/tools/man/ipa-server-install.1
-@@ -85,13 +85,17 @@ An unattended installation that will never prompt for user input
- .SS "CERTIFICATE SYSTEM OPTIONS"
- .TP
- \fB\-\-external\-ca\fR
--Generate a CSR to be signed by an external CA
-+Generate a CSR for the IPA CA certificate to be signed by an external CA.
- .TP
- \fB\-\-external_cert_file\fR=\fIFILE\fR
--PEM file containing a certificate signed by the external CA. Must be given with \-\-external_ca_file.
-+File containing the IPA CA certificate signed by the external CA in PEM format. Must be given with \-\-external_ca_file.
- .TP
- \fB\-\-external_ca_file\fR=\fIFILE\fR
--PEM file containing the external CA chain
-+File containing the external CA certificate chain in PEM format. Must be given with \-\-external_cert_file.
-+
-+If the CA certificate chain is in PKCS#7 format you can convert it to PEM using:
-+
-+    openssl pkcs7 -in PKCS7_FILE -print_certs -out PEM_FILE
- .TP
- \fB\-\-no\-pkinit\fR
- Disables pkinit setup steps
-diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
-index 126bbae66e8a9ae8d9cc6e624745ab1cc37bf4c1..233fa5d95fb7068b22a1c3daaed89176ff14a380 100644
---- a/ipaserver/install/cainstance.py
-+++ b/ipaserver/install/cainstance.py
-@@ -578,9 +578,20 @@ def __spawn_instance(self):
-             config.set("CA", "pki_external_csr_path", self.csr_file)
- 
-         elif self.external == 2:
-+            cert_chain, stderr, rc = ipautil.run(
-+                ['/usr/bin/openssl', 'crl2pkcs7',
-+                 '-certfile', self.cert_chain_file,
-+                 '-nocrl'])
-+            # Dogtag chokes on the header and footer, remove them
-+            # https://bugzilla.redhat.com/show_bug.cgi?id=1127838
-+            cert_chain = re.search(
-+                r'(?<=-----BEGIN PKCS7-----).*?(?=-----END PKCS7-----)',
-+                cert_chain, re.DOTALL).group(0)
-+            cert_chain_file = ipautil.write_tmp_file(cert_chain)
-+
-             config.set("CA", "pki_external", "True")
-             config.set("CA", "pki_external_ca_cert_path", self.cert_file)
--            config.set("CA", "pki_external_ca_cert_chain_path", self.cert_chain_file)
-+            config.set("CA", "pki_external_ca_cert_chain_path", cert_chain_file.name)
-             config.set("CA", "pki_external_step_two", "True")
- 
-         # Generate configuration file
--- 
-1.9.3
-
diff --git a/SOURCES/0067-Use-NSS-protocol-range-API-to-set-available-TLS-prot.patch b/SOURCES/0067-Use-NSS-protocol-range-API-to-set-available-TLS-prot.patch
new file mode 100644
index 0000000..0fc2801
--- /dev/null
+++ b/SOURCES/0067-Use-NSS-protocol-range-API-to-set-available-TLS-prot.patch
@@ -0,0 +1,149 @@
+From 8c544d9583c4172634f3180d6f90e6d4f37595ed Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Thu, 30 Oct 2014 11:52:14 -0400
+Subject: [PATCH] Use NSS protocol range API to set available TLS protocols
+
+Protocols are configured as an inclusive range from SSLv3 through
+TLSv1.2. The allowed values in the range are ssl3, tls1.0,
+tls1.1 and tls1.2.
+
+This is overridable per client by setting tls_version_min and/or
+tls_version_max.
+
+https://fedorahosted.org/freeipa/ticket/4653
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ freeipa.spec.in     |  2 +-
+ ipalib/constants.py |  4 ++++
+ ipalib/rpc.py       |  5 ++++-
+ ipapython/dogtag.py |  4 +++-
+ ipapython/nsslib.py | 17 +++++++++++++++--
+ 5 files changed, 27 insertions(+), 5 deletions(-)
+
+diff --git a/freeipa.spec.in b/freeipa.spec.in
+index e29f77de0db89035d15008c6be2da0ae7e96158a..1c975b3912d0a7470a32f1b7e314cfde74446e85 100644
+--- a/freeipa.spec.in
++++ b/freeipa.spec.in
+@@ -271,7 +271,7 @@ Requires: gnupg
+ Requires: iproute
+ Requires: keyutils
+ Requires: pyOpenSSL
+-Requires: python-nss >= 0.15
++Requires: python-nss >= 0.16
+ Requires: python-lxml
+ Requires: python-netaddr
+ Requires: libipa_hbac-python
+diff --git a/ipalib/constants.py b/ipalib/constants.py
+index 1eed7ca6ad0e5920318dadc68ed36fff6cf889f2..111bafe5ed0c3d2df58a1b6839feedc58a14fcc4 100644
+--- a/ipalib/constants.py
++++ b/ipalib/constants.py
+@@ -122,6 +122,10 @@ DEFAULT_CONFIG = (
+ 
+     ('rpc_protocol', 'jsonrpc'),
+ 
++    # Define an inclusive range of SSL/TLS version support
++    ('tls_version_min', 'tls1.0'),
++    ('tls_version_max', 'tls1.2'),
++
+     # Time to wait for a service to start, in seconds
+     ('startup_timeout', 300),
+ 
+diff --git a/ipalib/rpc.py b/ipalib/rpc.py
+index 5934f0c26e4b7c0a44adbab978c1f9b319d72e9f..806f6bb9adf004660c9cb285cf31b09a988afa93 100644
+--- a/ipalib/rpc.py
++++ b/ipalib/rpc.py
+@@ -68,6 +68,7 @@ from ipalib.krb_utils import KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, KRB5KRB_AP_ERR_TKT
+                              KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, KRB5_REALM_CANT_RESOLVE
+ from ipapython.dn import DN
+ from ipalib.capabilities import VERSION_WITHOUT_CAPABILITIES
++from ipalib import api
+ 
+ COOKIE_NAME = 'ipa_session'
+ KEYRING_COOKIE_NAME = '%s_cookie:%%s' % COOKIE_NAME
+@@ -488,7 +489,9 @@ class SSLTransport(LanguageAwareTransport):
+         if sys.version_info < (2, 7):
+             conn = NSSHTTPS(host, 443, dbdir=dbdir, no_init=no_init)
+         else:
+-            conn = NSSConnection(host, 443, dbdir=dbdir, no_init=no_init)
++            conn = NSSConnection(host, 443, dbdir=dbdir, no_init=no_init,
++                                 tls_version_min=api.env.tls_version_min,
++                                 tls_version_max=api.env.tls_version_max)
+         self.dbdir=dbdir
+ 
+         conn.connect()
+diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py
+index 14824b99431e85dd73613befd72e500d370cfe2c..0e0aacca798377517244075ed6b07dff63e87358 100644
+--- a/ipapython/dogtag.py
++++ b/ipapython/dogtag.py
+@@ -234,7 +234,9 @@ def https_request(host, port, url, secdir, password, nickname, **kw):
+     """
+ 
+     def connection_factory(host, port):
+-        conn = nsslib.NSSConnection(host, port, dbdir=secdir)
++        conn = nsslib.NSSConnection(host, port, dbdir=secdir,
++                                    tls_version_min=api.env.tls_version_min,
++                                    tls_version_max=api.env.tls_version_max)
+         conn.set_debuglevel(0)
+         conn.connect()
+         conn.sock.set_client_auth_data_callback(
+diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
+index 93b0c56fcff4fc69841a6823aae8f694c1f76ff0..57fa3ff4fa5a044577f21fe43c2c0b0596c2e4f8 100644
+--- a/ipapython/nsslib.py
++++ b/ipapython/nsslib.py
+@@ -171,7 +171,8 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
+     default_port = httplib.HTTPSConnection.default_port
+ 
+     def __init__(self, host, port=None, strict=None,
+-                 dbdir=None, family=socket.AF_UNSPEC, no_init=False):
++                 dbdir=None, family=socket.AF_UNSPEC, no_init=False,
++                 tls_version_min='tls1.1', tls_version_max='tls1.2'):
+         """
+         :param host: the server to connect to
+         :param port: the port to use (default is set in HTTPConnection)
+@@ -180,6 +181,8 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
+         :param no_init: do not initialize the NSS database. This requires
+                         that the database has already been initialized or
+                         the request will fail.
++        :param tls_min_version: mininum version of SSL/TLS supported
++        :param tls_max_version: maximum version of SSL/TLS supported.
+         """
+         httplib.HTTPConnection.__init__(self, host, port, strict)
+         NSSAddressFamilyFallback.__init__(self, family)
+@@ -199,6 +202,8 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
+         nss.nss_init(dbdir)
+         ssl.set_domestic_policy()
+         nss.set_password_callback(self.password_callback)
++        self.tls_version_min = str(tls_version_min)
++        self.tls_version_max = str(tls_version_max)
+ 
+     def _create_socket(self):
+         # TODO: remove the try block once python-nss is guaranteed to contain
+@@ -218,6 +223,11 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
+         self.sock = ssl.SSLSocket(family=self.family)
+         self.sock.set_ssl_option(ssl.SSL_SECURITY, True)
+         self.sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
++        try:
++            self.sock.set_ssl_version_range(self.tls_version_min, self.tls_version_max)
++        except NSPRError, e:
++            root_logger.error('Failed to set TLS range to %s, %s' % (self.tls_version_min, self.tls_version_max))
++            raise
+         self.sock.set_ssl_option(ssl_require_safe_negotiation, False)
+         self.sock.set_ssl_option(ssl_enable_renegotiation, ssl_renegotiate_requires_xtn)
+         # Provide a callback which notifies us when the SSL handshake is complete
+@@ -236,8 +246,11 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
+         """
+         Verify callback. If we get here then the certificate is ok.
+         """
++        channel = sock.get_ssl_channel_info()
++        suite = ssl.get_cipher_suite_info(channel.cipher_suite)
+         root_logger.debug("handshake complete, peer = %s", sock.get_peer_name())
+-        pass
++        root_logger.debug('Protocol: %s' % channel.protocol_version_str.upper())
++        root_logger.debug('Cipher: %s' % suite.cipher_suite_name)
+ 
+     def connect(self):
+         self.connect_socket(self.host, self.port)
+-- 
+2.1.0
+
diff --git a/SOURCES/0067-ipaserver-dcerpc.py-if-search-of-a-closest-GC-failed.patch b/SOURCES/0067-ipaserver-dcerpc.py-if-search-of-a-closest-GC-failed.patch
deleted file mode 100644
index 8a6db38..0000000
--- a/SOURCES/0067-ipaserver-dcerpc.py-if-search-of-a-closest-GC-failed.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From f2acf0d67bab3f3797c387705f93c3a3d0164134 Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 19 Aug 2014 16:19:45 +0300
-Subject: [PATCH] ipaserver/dcerpc.py: if search of a closest GC failed, try to
- find any GC
-
-https://fedorahosted.org/freeipa/ticket/4458
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- ipaserver/dcerpc.py | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index f1c75089b875787debcee22316a4898b424d923f..b11476a262ccce4315131b9ffbd93b625de940e7 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -588,7 +588,11 @@ class DomainValidator(object):
-         try:
-             result = netrc.finddc(domain=domain, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_GC | nbt.NBT_SERVER_CLOSEST)
-         except RuntimeError, e:
--            finddc_error = e
-+            try:
-+                # If search of closest GC failed, attempt to find any one
-+                result = netrc.finddc(domain=domain, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_GC)
-+            except RuntimeError, e:
-+                finddc_error = e
- 
-         if not self._domains:
-             self._domains = self.get_trusted_domains()
--- 
-1.9.3
-
diff --git a/SOURCES/0068-Throw-zonemgr-error-message-before-installation-proc.patch b/SOURCES/0068-Throw-zonemgr-error-message-before-installation-proc.patch
new file mode 100644
index 0000000..d753f55
--- /dev/null
+++ b/SOURCES/0068-Throw-zonemgr-error-message-before-installation-proc.patch
@@ -0,0 +1,136 @@
+From 453332215667d6ff9595e6dedeeb3ed5ba7e5bdf Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Thu, 27 Nov 2014 14:16:23 +0100
+Subject: [PATCH] Throw zonemgr error message before installation proceeds
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4771
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/parameters.py | 35 +++++------------------------------
+ ipalib/util.py       | 45 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+), 30 deletions(-)
+
+diff --git a/ipalib/parameters.py b/ipalib/parameters.py
+index 0cf14a4cd2900459ccd5d6d52912960c642223aa..7fa55fd6a6854ffa97da211ca5ef04b7ad974dc4 100644
+--- a/ipalib/parameters.py
++++ b/ipalib/parameters.py
+@@ -112,7 +112,7 @@ from errors import ConversionError, RequirementError, ValidationError
+ from errors import PasswordMismatch, Base64DecodeError
+ from constants import TYPE_ERROR, CALLABLE_ERROR, LDAP_GENERALIZED_TIME_FORMAT
+ from text import Gettext, FixMe
+-from util import json_serialize
++from util import json_serialize, validate_idna_domain
+ from ipapython.dn import DN
+ from ipapython.dnsutil import DNSName
+ import dns.name
+@@ -1950,36 +1950,11 @@ class DNSNameParam(Param):
+             error = None
+ 
+             try:
+-                domain_name = DNSName(value)
+-            except dns.name.BadEscape:
+-                error = _('invalid escape code in domain name')
+-            except dns.name.EmptyLabel:
+-                error = _('empty DNS label')
+-            except dns.name.NameTooLong:
+-                error = _('domain name cannot be longer than 255 characters')
+-            except dns.name.LabelTooLong:
+-                error = _('DNS label cannot be longer than 63 characters')
+-            except dns.exception.SyntaxError:
+-                error = _('invalid domain name')
+-            else:
+-                #compare if IDN normalized and original domain match
+-                #there is N:1 mapping between unicode and IDNA names
+-                #user should use normalized names to avoid mistakes
+-                labels = re.split(u'[.\uff0e\u3002\uff61]', value, flags=re.UNICODE)
+-                try:
+-                    map(lambda label: label.encode("ascii"), labels)
+-                except UnicodeError:
+-                    # IDNA
+-                    is_nonnorm = any(encodings.idna.nameprep(x) != x for x in labels)
+-                    if is_nonnorm:
+-                        error = _("domain name '%(domain)s' should be normalized to"
+-                          ": %(normalized)s") % {
+-                          'domain': value,
+-                          'normalized': '.'.join([encodings.idna.nameprep(x) for x in labels])}
+-            if error:
++                validate_idna_domain(value)
++            except ValueError as e:
+                 raise ConversionError(name=self.get_param_name(), index=index,
+-                                      error=error)
+-            value = domain_name
++                                      error=unicode(e))
++            value = DNSName(value)
+ 
+             if self.only_absolute and not value.is_absolute():
+                 value = value.make_absolute()
+diff --git a/ipalib/util.py b/ipalib/util.py
+index 7a283106d70ba6a3e25cc7129d57b44b80876882..2c17d80a0427a5c7e45a6a0b64fa1f4d39fffa8a 100644
+--- a/ipalib/util.py
++++ b/ipalib/util.py
+@@ -28,6 +28,7 @@ import socket
+ import re
+ import decimal
+ import dns
++import encodings
+ import netaddr
+ from types import NoneType
+ from weakref import WeakKeyDictionary
+@@ -277,6 +278,7 @@ def validate_zonemgr(zonemgr):
+ 
+ def validate_zonemgr_str(zonemgr):
+     zonemgr = normalize_zonemgr(zonemgr)
++    validate_idna_domain(zonemgr)
+     zonemgr = DNSName(zonemgr)
+     return validate_zonemgr(zonemgr)
+ 
+@@ -589,3 +591,46 @@ def validate_dnssec_forwarder(ip_addr):
+         return False
+ 
+     return True
++
++
++def validate_idna_domain(value):
++    """
++    Validate if value is valid IDNA domain.
++
++    If domain is not valid, raises ValueError
++    :param value:
++    :return:
++    """
++    error = None
++
++    try:
++        DNSName(value)
++    except dns.name.BadEscape:
++        error = _('invalid escape code in domain name')
++    except dns.name.EmptyLabel:
++        error = _('empty DNS label')
++    except dns.name.NameTooLong:
++        error = _('domain name cannot be longer than 255 characters')
++    except dns.name.LabelTooLong:
++        error = _('DNS label cannot be longer than 63 characters')
++    except dns.exception.SyntaxError:
++        error = _('invalid domain name')
++    else:
++        #compare if IDN normalized and original domain match
++        #there is N:1 mapping between unicode and IDNA names
++        #user should use normalized names to avoid mistakes
++        labels = re.split(u'[.\uff0e\u3002\uff61]', value, flags=re.UNICODE)
++        try:
++            map(lambda label: label.encode("ascii"), labels)
++        except UnicodeError:
++            # IDNA
++            is_nonnorm = any(encodings.idna.nameprep(x) != x for x in labels)
++            if is_nonnorm:
++                error = _("domain name '%(domain)s' should be normalized to"
++                          ": %(normalized)s") % {
++                          'domain': value,
++                          'normalized': '.'.join([encodings.idna.nameprep(x)
++                                                  for x in labels])}
++
++    if error:
++        raise ValueError(error)
+-- 
+2.1.0
+
diff --git a/SOURCES/0068-ipaserver-dcerpc.py-make-PDC-discovery-more-robust.patch b/SOURCES/0068-ipaserver-dcerpc.py-make-PDC-discovery-more-robust.patch
deleted file mode 100644
index a1ba8b9..0000000
--- a/SOURCES/0068-ipaserver-dcerpc.py-make-PDC-discovery-more-robust.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From 41b252a5b47f57919bf98c41947d5927ed0d5aaf Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 19 Aug 2014 16:21:21 +0300
-Subject: [PATCH] ipaserver/dcerpc.py: make PDC discovery more robust
-
-Certain operations against AD domain controller can only be done if its
-FSMO role is primary domain controller. We need to use writable DC and
-PDC when creating trust and updating name suffix routing information.
-
-https://fedorahosted.org/freeipa/ticket/4479
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- ipaserver/dcerpc.py | 21 ++++++++++++++++-----
- 1 file changed, 16 insertions(+), 5 deletions(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index b11476a262ccce4315131b9ffbd93b625de940e7..78bfc5dbefc778519c5db0ac12d6551710257ba9 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -706,16 +706,19 @@ class TrustDomainInstance(object):
-         binding_template=lambda x,y,z: u'%s:%s[%s]' % (x, y, z)
-         return [binding_template(t, remote_host, o) for t in transports for o in options]
- 
--    def retrieve_anonymously(self, remote_host, discover_srv=False):
-+    def retrieve_anonymously(self, remote_host, discover_srv=False, search_pdc=False):
-         """
-         When retrieving DC information anonymously, we can't get SID of the domain
-         """
-         netrc = net.Net(creds=self.creds, lp=self.parm)
-+        flags = nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE
-+        if search_pdc:
-+            flags = flags | nbt.NBT_SERVER_PDC
-         try:
-             if discover_srv:
--                result = netrc.finddc(domain=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
-+                result = netrc.finddc(domain=remote_host, flags=flags)
-             else:
--                result = netrc.finddc(address=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
-+                result = netrc.finddc(address=remote_host, flags=flags)
-         except RuntimeError, e:
-             raise assess_dcerpc_exception(message=str(e))
- 
-@@ -726,6 +729,7 @@ class TrustDomainInstance(object):
-         self.info['dns_forest'] = unicode(result.forest)
-         self.info['guid'] = unicode(result.domain_uuid)
-         self.info['dc'] = unicode(result.pdc_dns_name)
-+        self.info['is_pdc'] = (result.server_type & nbt.NBT_SERVER_PDC) != 0
- 
-         # Netlogon response doesn't contain SID of the domain.
-         # We need to do rootDSE search with LDAP_SERVER_EXTENDED_DN_OID control to reveal the SID
-@@ -774,6 +778,13 @@ class TrustDomainInstance(object):
-         self.info['sid'] = unicode(result.sid)
-         self.info['dc'] = remote_host
- 
-+        try:
-+            result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_ROLE)
-+        except RuntimeError, (num, message):
-+            raise assess_dcerpc_exception(num=num, message=message)
-+
-+        self.info['is_pdc'] = (result.role == lsa.LSA_ROLE_PRIMARY)
-+
-     def generate_auth(self, trustdom_secret):
-         def arcfour_encrypt(key, data):
-             c = RC4.RC4(key)
-@@ -1069,9 +1080,9 @@ class TrustDomainJoins(object):
-         rd.creds.set_anonymous()
-         rd.creds.set_workstation(self.local_domain.hostname)
-         if realm_server is None:
--            rd.retrieve_anonymously(realm, discover_srv=True)
-+            rd.retrieve_anonymously(realm, discover_srv=True, search_pdc=True)
-         else:
--            rd.retrieve_anonymously(realm_server, discover_srv=False)
-+            rd.retrieve_anonymously(realm_server, discover_srv=False, search_pdc=True)
-         rd.read_only = True
-         if realm_admin and realm_passwd:
-             if 'name' in rd.info:
--- 
-1.9.3
-
diff --git a/SOURCES/0069-certs-Fix-incorrect-flag-handling-in-load_cacert.patch b/SOURCES/0069-certs-Fix-incorrect-flag-handling-in-load_cacert.patch
new file mode 100644
index 0000000..e8e73d1
--- /dev/null
+++ b/SOURCES/0069-certs-Fix-incorrect-flag-handling-in-load_cacert.patch
@@ -0,0 +1,62 @@
+From 9c9050a11a14f548fe2f0f0746c686a8ccc09488 Mon Sep 17 00:00:00 2001
+From: Tomas Babej <tbabej@redhat.com>
+Date: Tue, 2 Dec 2014 13:13:51 +0100
+Subject: [PATCH] certs: Fix incorrect flag handling in load_cacert
+
+For CA certificates that are not certificates of IPA CA, we incorrectly
+set the trust flags to ",,", regardless what the actual trust_flags
+parameter was passed.
+
+Make the load_cacert method respect trust_flags and make it a required
+argument.
+
+https://fedorahosted.org/freeipa/ticket/4779
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/certs.py      | 6 ++----
+ ipaserver/install/dsinstance.py | 2 +-
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
+index 5399a0fa566c6f7df81a9d1e347f6ac99e5188c9..7292cbbe3574f57d32daa6f1e310669486fa5eff 100644
+--- a/ipaserver/install/certs.py
++++ b/ipaserver/install/certs.py
+@@ -238,7 +238,7 @@ class CertDB(object):
+                          "-k", self.passwd_fname])
+             self.set_perms(self.pk12_fname)
+ 
+-    def load_cacert(self, cacert_fname, trust_flags='C,,'):
++    def load_cacert(self, cacert_fname, trust_flags):
+         """
+         Load all the certificates from a given file. It is assumed that
+         this file creates CA certificates.
+@@ -255,11 +255,9 @@ class CertDB(object):
+                 (rdn, subject_dn) = get_cert_nickname(cert)
+                 if subject_dn == ca_dn:
+                     nick = get_ca_nickname(self.realm)
+-                    tf = trust_flags
+                 else:
+                     nick = str(subject_dn)
+-                    tf = ',,'
+-                self.nssdb.add_cert(cert, nick, tf, pem=True)
++                self.nssdb.add_cert(cert, nick, trust_flags, pem=True)
+             except RuntimeError:
+                 break
+ 
+diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
+index da535347117166e6cb445b0ebf14ad71787f72ba..860ad992ea94b8275fdfd1b4435607375c1d3d80 100644
+--- a/ipaserver/install/dsinstance.py
++++ b/ipaserver/install/dsinstance.py
+@@ -841,7 +841,7 @@ class DsInstance(service.Service):
+         certdb.cacert_name = cacert_name
+         status = True
+         try:
+-            certdb.load_cacert(cacert_fname)
++            certdb.load_cacert(cacert_fname, 'C,,')
+         except ipautil.CalledProcessError, e:
+             root_logger.critical("Error importing CA cert file named [%s]: %s" %
+                                          (cacert_fname, str(e)))
+-- 
+2.1.0
+
diff --git a/SOURCES/0069-ipaserver-dcerpc.py-be-more-open-to-what-domains-can.patch b/SOURCES/0069-ipaserver-dcerpc.py-be-more-open-to-what-domains-can.patch
deleted file mode 100644
index 595950a..0000000
--- a/SOURCES/0069-ipaserver-dcerpc.py-be-more-open-to-what-domains-can.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 027f61099c63c91aaac95a6c2b9d9a75e7b1f83e Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 19 Aug 2014 16:23:58 +0300
-Subject: [PATCH] ipaserver/dcerpc.py: be more open to what domains can be seen
- through the forest trust
-
-https://fedorahosted.org/freeipa/ticket/4463
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- ipaserver/dcerpc.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index 78bfc5dbefc778519c5db0ac12d6551710257ba9..fcf1e4e775868f17220cac3c0203cc67dba2f839 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -1031,7 +1031,7 @@ def fetch_domains(api, mydomain, trustdomain, creds=None):
- 
-     result = []
-     for t in domains.array:
--        if ((t.trust_attributes & trust_attributes['NETR_TRUST_ATTRIBUTE_WITHIN_FOREST']) and
-+        if (not (t.trust_flags & trust_flags['NETR_TRUST_FLAG_PRIMARY']) and
-             (t.trust_flags & trust_flags['NETR_TRUST_FLAG_IN_FOREST'])):
-             res = dict()
-             res['cn'] = unicode(t.dns_name)
--- 
-1.9.3
-
diff --git a/SOURCES/0070-Preliminary-refactoring-of-libotp-files.patch b/SOURCES/0070-Preliminary-refactoring-of-libotp-files.patch
new file mode 100644
index 0000000..95100d4
--- /dev/null
+++ b/SOURCES/0070-Preliminary-refactoring-of-libotp-files.patch
@@ -0,0 +1,2309 @@
+From d3c2efc7362f8eeb1cfb22b5d59bdec22226af65 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Mon, 10 Nov 2014 20:58:20 -0500
+Subject: [PATCH] Preliminary refactoring of libotp files
+
+There are no major changes in this commit other than changing filenames
+and symbols to have consistent namespaces. This prepares for larger
+changes to come in subsequent commits.
+
+Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
+---
+ .../ipa-otp-lasttoken/Makefile.am                  |   1 -
+ .../ipa-otp-lasttoken/ipa_otp_lasttoken.c          |  10 +-
+ .../ipa-slapi-plugins/ipa-pwd-extop/Makefile.am    |   1 -
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h   |   2 +-
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c  |  12 +-
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c  |  11 +-
+ daemons/ipa-slapi-plugins/libotp/Makefile.am       |  10 +-
+ daemons/ipa-slapi-plugins/libotp/hotp.c            | 170 ++++++
+ daemons/ipa-slapi-plugins/libotp/hotp.h            |  60 +++
+ daemons/ipa-slapi-plugins/libotp/libotp.c          | 573 ---------------------
+ daemons/ipa-slapi-plugins/libotp/libotp.h          |  93 ----
+ daemons/ipa-slapi-plugins/libotp/librfc.c          | 170 ------
+ daemons/ipa-slapi-plugins/libotp/librfc.h          |  63 ---
+ daemons/ipa-slapi-plugins/libotp/otp_token.c       | 572 ++++++++++++++++++++
+ daemons/ipa-slapi-plugins/libotp/otp_token.h       |  87 ++++
+ daemons/ipa-slapi-plugins/libotp/t_hotp.c          | 121 +++++
+ daemons/ipa-slapi-plugins/libotp/t_librfc.c        | 121 -----
+ 17 files changed, 1033 insertions(+), 1044 deletions(-)
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/hotp.c
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/hotp.h
+ delete mode 100644 daemons/ipa-slapi-plugins/libotp/libotp.c
+ delete mode 100644 daemons/ipa-slapi-plugins/libotp/libotp.h
+ delete mode 100644 daemons/ipa-slapi-plugins/libotp/librfc.c
+ delete mode 100644 daemons/ipa-slapi-plugins/libotp/librfc.h
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/otp_token.c
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/otp_token.h
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/t_hotp.c
+ delete mode 100644 daemons/ipa-slapi-plugins/libotp/t_librfc.c
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
+index d12fbcc891c5f210028b1c02ffbd83908e50acc6..cb6340960818eb4874a70f36603feda93652370f 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
+@@ -3,7 +3,6 @@ PLUGIN_COMMON_DIR = ../common
+ AM_CPPFLAGS =							\
+ 	-I.							\
+ 	-I$(srcdir)						\
+-	-I$(srcdir)/../libotp					\
+ 	-I$(PLUGIN_COMMON_DIR)					\
+ 	-I/usr/include/dirsrv					\
+ 	-DPREFIX=\""$(prefix)"\" 				\
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+index 15b404dcdb6bd88c70ccc7c5fed7a5829483590b..19217ba7fbf562231dd74b25cfd13a0f4d930e7c 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+@@ -41,7 +41,7 @@
+ #  include <config.h>
+ #endif
+ 
+-#include <libotp.h>
++#include "../libotp/otp_token.h"
+ #include <time.h>
+ 
+ #include "util.h"
+@@ -61,7 +61,7 @@ target_is_only_enabled_token(Slapi_PBlock *pb)
+ {
+     Slapi_DN *target_sdn = NULL;
+     Slapi_DN *token_sdn = NULL;
+-    struct otptoken **tokens;
++    struct otp_token **tokens;
+     char *user_dn = NULL;
+     bool match;
+ 
+@@ -75,10 +75,10 @@ target_is_only_enabled_token(Slapi_PBlock *pb)
+         return false;
+ 
+     /* Get the SDN of the only enabled token. */
+-    tokens = otptoken_find(plugin_id, user_dn, NULL, true, NULL);
++    tokens = otp_token_find(plugin_id, user_dn, NULL, true, NULL);
+     if (tokens != NULL && tokens[0] != NULL && tokens[1] == NULL)
+-        token_sdn = slapi_sdn_dup(otptoken_get_sdn(tokens[0]));
+-    otptoken_free_array(tokens);
++        token_sdn = slapi_sdn_dup(otp_token_get_sdn(tokens[0]));
++    otp_token_free_array(tokens);
+     if (token_sdn == NULL)
+         return false;
+ 
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+index 77beca2da0810ed5507d95b21f99d22f63b05fc1..eeb352611e5b67a2f6803b59414fb31c37f39f33 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+@@ -11,7 +11,6 @@ ASN1_UTIL_DIR=../../../asn1
+ AM_CPPFLAGS =							\
+ 	-I.							\
+ 	-I$(srcdir)						\
+-	-I$(srcdir)/../libotp					\
+ 	-I$(PLUGIN_COMMON_DIR)					\
+ 	-I$(KRB5_UTIL_DIR)					\
+ 	-I$(ASN1_UTIL_DIR)					\
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
+index f8851122b920bb8317d5d6b74915504a98a674cf..2e9d4fe86b34c64731728882db7c81e3871d7d07 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
+@@ -41,7 +41,7 @@
+ #  include <config.h>
+ #endif
+ 
+-#include <libotp.h>
++#include "../libotp/otp_token.h"
+ 
+ #include <stdio.h>
+ #include <string.h>
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+index 1f595d01d986ca2950672d796d62f5f78b05c212..1dff6db1a8cfcc295ba43d1c29d8887e3cf37fec 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+@@ -1140,11 +1140,11 @@ done:
+ static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
+                                struct berval *creds)
+ {
+-    struct otptoken **tokens = NULL;
++    struct otp_token **tokens = NULL;
+     bool success = false;
+ 
+     /* Find all of the user's active tokens. */
+-    tokens = otptoken_find(ipapwd_plugin_id, dn, NULL, true, NULL);
++    tokens = otp_token_find(ipapwd_plugin_id, dn, NULL, true, NULL);
+     if (tokens == NULL) {
+         slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
+                         "%s: can't find tokens for '%s'.\n", __func__, dn);
+@@ -1157,12 +1157,12 @@ static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
+     /* Loop through each token. */
+     for (int i = 0; tokens[i] && !success; i++) {
+         /* Attempt authentication. */
+-        success = otptoken_validate_berval(tokens[i], OTP_VALIDATE_STEPS,
++        success = otp_token_validate_berval(tokens[i], OTP_VALIDATE_STEPS,
+                                            creds, true);
+ 
+         /* Truncate the password to remove the OTP code at the end. */
+         if (success) {
+-            creds->bv_len -= otptoken_get_digits(tokens[i]);
++            creds->bv_len -= otp_token_get_digits(tokens[i]);
+             creds->bv_val[creds->bv_len] = '\0';
+         }
+ 
+@@ -1170,10 +1170,10 @@ static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
+                         "%s: token authentication %s "
+                         "(user: '%s', token: '%s\').\n", __func__,
+                         success ? "succeeded" : "failed", dn,
+-                        slapi_sdn_get_ndn(otptoken_get_sdn(tokens[i])));
++                        slapi_sdn_get_ndn(otp_token_get_sdn(tokens[i])));
+     }
+ 
+-    otptoken_free_array(tokens);
++    otp_token_free_array(tokens);
+     return success;
+ }
+ 
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+index cbb4536e7d119f4550e4b523eb02e34d058ae7a1..10c49b724ee276d2b1fb89891a6eb4ee8eaa8fab 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+@@ -37,8 +37,7 @@
+  * All rights reserved.
+  * END COPYRIGHT BLOCK **/
+ 
+-
+-#include <libotp.h>
++#include "../libotp/otp_token.h"
+ #include "syncreq.h"
+ 
+ #define OTP_SYNC_MAX_STEPS 25
+@@ -56,7 +55,7 @@ bool sync_request_present(Slapi_PBlock *pb)
+ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
+                          const char *user_dn)
+ {
+-    struct otptoken **tokens = NULL;
++    struct otp_token **tokens = NULL;
+     LDAPControl **controls = NULL;
+     struct berval *second = NULL;
+     struct berval *first = NULL;
+@@ -91,10 +90,10 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
+         /* Process the synchronization. */
+         success = false;
+         if (ber_scanf(ber, "}") != LBER_ERROR) {
+-            tokens = otptoken_find(plugin_id, user_dn, token_dn, true, NULL);
++            tokens = otp_token_find(plugin_id, user_dn, token_dn, true, NULL);
+             if (tokens != NULL) {
+-                success = otptoken_sync_berval(tokens, OTP_SYNC_MAX_STEPS, first, second);
+-                otptoken_free_array(tokens);
++                success = otp_token_sync_berval(tokens, OTP_SYNC_MAX_STEPS, first, second);
++                otp_token_free_array(tokens);
+             }
+         }
+ 
+diff --git a/daemons/ipa-slapi-plugins/libotp/Makefile.am b/daemons/ipa-slapi-plugins/libotp/Makefile.am
+index 6aa60c56a2293916ba7c1d773968055c3f94a4fe..012c8339199af5f63e6434b94109af2d93a38b45 100644
+--- a/daemons/ipa-slapi-plugins/libotp/Makefile.am
++++ b/daemons/ipa-slapi-plugins/libotp/Makefile.am
+@@ -1,9 +1,11 @@
+ MAINTAINERCLEANFILES = *~ Makefile.in
+ AM_CPPFLAGS = -I/usr/include/dirsrv
+ 
+-noinst_LTLIBRARIES = librfc.la libotp.la
+-libotp_la_LIBADD = librfc.la
++noinst_LTLIBRARIES = libhotp.la libotp.la
++libhotp_la_SOURCES = hotp.c hotp.h
++libotp_la_SOURCES = otp_token.c otp_token.h
++libotp_la_LIBADD = libhotp.la
+ 
+-check_PROGRAMS = t_librfc
++check_PROGRAMS = t_hotp
+ TESTS = $(check_PROGRAMS)
+-t_librfc_LDADD = $(NSPR_LIBS) $(NSS_LIBS) librfc.la
++t_hotp_LDADD = $(NSPR_LIBS) $(NSS_LIBS) libhotp.la
+diff --git a/daemons/ipa-slapi-plugins/libotp/hotp.c b/daemons/ipa-slapi-plugins/libotp/hotp.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..619bc63ab1bee99d71c2f0fb887809762107c94c
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/hotp.c
+@@ -0,0 +1,170 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++/*
++ * This file contains an implementation of HOTP (RFC 4226) and TOTP (RFC 6238).
++ * For details of how these algorithms work, please see the relevant RFCs.
++ */
++
++#include "hotp.h"
++#include <time.h>
++
++#include <nss.h>
++#include <pk11pub.h>
++#include <hasht.h>
++#include <prnetdb.h>
++
++struct digest_buffer {
++    uint8_t buf[SHA512_LENGTH];
++    unsigned int len;
++};
++
++static const struct {
++    const char *algo;
++    CK_MECHANISM_TYPE mech;
++} algo2mech[] = {
++    { "sha1",   CKM_SHA_1_HMAC },
++    { "sha256", CKM_SHA256_HMAC },
++    { "sha384", CKM_SHA384_HMAC },
++    { "sha512", CKM_SHA512_HMAC },
++    { }
++};
++
++/*
++ * This code is mostly cargo-cult taken from here:
++ *   http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn5.html
++ *
++ * It should implement HMAC with the given mechanism (SHA: 1, 256, 384, 512).
++ */
++static bool hmac(SECItem *key, CK_MECHANISM_TYPE mech, const SECItem *in,
++                 struct digest_buffer *out)
++{
++    SECItem param = { siBuffer, NULL, 0 };
++    PK11SlotInfo *slot = NULL;
++    PK11SymKey *symkey = NULL;
++    PK11Context *ctx = NULL;
++    bool ret = false;
++    SECStatus s;
++
++    slot = PK11_GetBestSlot(mech, NULL);
++    if (slot == NULL) {
++        slot = PK11_GetInternalKeySlot();
++        if (slot == NULL) {
++            goto done;
++        }
++    }
++
++    symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
++                               CKA_SIGN, key, NULL);
++    if (symkey == NULL)
++        goto done;
++
++    ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, symkey, &param);
++    if (ctx == NULL)
++        goto done;
++
++    s = PK11_DigestBegin(ctx);
++    if (s != SECSuccess)
++        goto done;
++
++    s = PK11_DigestOp(ctx, in->data, in->len);
++    if (s != SECSuccess)
++        goto done;
++
++    s = PK11_DigestFinal(ctx, out->buf, &out->len, sizeof(out->buf));
++    if (s != SECSuccess)
++        goto done;
++
++    ret = true;
++
++done:
++    if (ctx != NULL)
++        PK11_DestroyContext(ctx, PR_TRUE);
++    if (symkey != NULL)
++        PK11_FreeSymKey(symkey);
++    if (slot != NULL)
++        PK11_FreeSlot(slot);
++    return ret;
++}
++
++/*
++ * An implementation of HOTP (RFC 4226).
++ */
++bool hotp(const struct hotp_token *token, uint64_t counter, uint32_t *out)
++{
++    const SECItem cntr = { siBuffer, (uint8_t *) &counter, sizeof(counter) };
++    SECItem keyitm = { siBuffer, token->key.bytes, token->key.len };
++    CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC;
++    PRUint64 offset, binary, div;
++    struct digest_buffer digest;
++    int digits = token->digits;
++    int i;
++
++    /* Convert counter to network byte order. */
++    counter = PR_htonll(counter);
++
++    /* Find the mech. */
++    for (i = 0; algo2mech[i].algo; i++) {
++        if (strcasecmp(algo2mech[i].algo, token->algo) == 0) {
++            mech = algo2mech[i].mech;
++            break;
++        }
++    }
++
++    /* Create the digits divisor. */
++    for (div = 1; digits > 0; digits--) {
++        div *= 10;
++    }
++
++    /* Do the digest. */
++    if (!hmac(&keyitm, mech, &cntr, &digest)) {
++        return false;
++    }
++
++    /* Truncate. */
++    offset  = digest.buf[digest.len - 1] & 0xf;
++    binary  = (digest.buf[offset + 0] & 0x7f) << 0x18;
++    binary |= (digest.buf[offset + 1] & 0xff) << 0x10;
++    binary |= (digest.buf[offset + 2] & 0xff) << 0x08;
++    binary |= (digest.buf[offset + 3] & 0xff) << 0x00;
++    binary  = binary % div;
++
++    *out = binary;
++    return true;
++}
+diff --git a/daemons/ipa-slapi-plugins/libotp/hotp.h b/daemons/ipa-slapi-plugins/libotp/hotp.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..06ae1fdae86df4ab124839cd62b61d99d908789a
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/hotp.h
+@@ -0,0 +1,60 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#pragma once
++
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdlib.h>
++
++struct hotp_token_key {
++    uint8_t *bytes;
++    size_t len;
++};
++
++struct hotp_token {
++    struct hotp_token_key key;
++    char *algo;
++    int digits;
++};
++
++/*
++ * An implementation of HOTP (RFC 4226).
++ */
++bool hotp(const struct hotp_token *token, uint64_t counter, uint32_t *out);
+diff --git a/daemons/ipa-slapi-plugins/libotp/libotp.c b/daemons/ipa-slapi-plugins/libotp/libotp.c
+deleted file mode 100644
+index c65aef04348da5abdb1eeb6267e785f0342c7d51..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/libotp/libotp.c
++++ /dev/null
+@@ -1,573 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2013 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-#include "libotp.h"
+-#include "librfc.h"
+-
+-#include <time.h>
+-#include <errno.h>
+-
+-#define TOKEN(s) "ipaToken" s
+-#define O(s) TOKEN("OTP" s)
+-#define T(s) TOKEN("TOTP" s)
+-#define H(s) TOKEN("HOTP" s)
+-
+-#define IPA_OTP_DEFAULT_TOKEN_STEP 30
+-#define IPA_OTP_OBJCLS_FILTER \
+-    "(|(objectClass=ipaTokenTOTP)(objectClass=ipaTokenHOTP))"
+-
+-
+-enum otptoken_type {
+-    OTPTOKEN_NONE = 0,
+-    OTPTOKEN_TOTP,
+-    OTPTOKEN_HOTP,
+-};
+-
+-struct otptoken {
+-    Slapi_ComponentId *plugin_id;
+-    Slapi_DN *sdn;
+-    struct hotp_token token;
+-    enum otptoken_type type;
+-    union {
+-        struct {
+-            uint64_t watermark;
+-            unsigned int step;
+-            int offset;
+-        } totp;
+-        struct {
+-            uint64_t counter;
+-        } hotp;
+-    };
+-};
+-
+-static const char *get_basedn(Slapi_DN *dn)
+-{
+-    Slapi_DN *suffix = NULL;
+-    void *node = NULL;
+-
+-    for (suffix = slapi_get_first_suffix(&node, 0);
+-         suffix != NULL;
+-         suffix = slapi_get_next_suffix(&node, 0)) {
+-        if (slapi_sdn_issuffix(dn, suffix))
+-            return (char *) slapi_sdn_get_dn(suffix);
+-    }
+-
+-    return NULL;
+-}
+-
+-static inline bool is_algo_valid(const char *algo)
+-{
+-    static const char *valid_algos[] = { "sha1", "sha256", "sha384",
+-                                         "sha512", NULL };
+-    int i, ret;
+-
+-    for (i = 0; valid_algos[i]; i++) {
+-        ret = strcasecmp(algo, valid_algos[i]);
+-        if (ret == 0)
+-            return true;
+-    }
+-
+-    return false;
+-}
+-
+-static const struct berval *entry_attr_get_berval(const Slapi_Entry* e,
+-                                                  const char *type)
+-{
+-    Slapi_Attr* attr = NULL;
+-    Slapi_Value *v;
+-    int ret;
+-
+-    ret = slapi_entry_attr_find(e, type, &attr);
+-    if (ret != 0 || attr == NULL)
+-        return NULL;
+-
+-    ret = slapi_attr_first_value(attr, &v);
+-    if (ret < 0)
+-        return NULL;
+-
+-    return slapi_value_get_berval(v);
+-}
+-
+-static bool writeattr(const struct otptoken *token, const char *attr,
+-                      long long val)
+-{
+-    Slapi_PBlock *pb = NULL;
+-    bool success = false;
+-    char value[32];
+-    int ret;
+-
+-    LDAPMod *mods[] = {
+-        &(LDAPMod) {
+-            LDAP_MOD_REPLACE, (char *) attr,
+-            .mod_values = (char *[]) { value, NULL }
+-        },
+-        NULL
+-    };
+-
+-    snprintf(value, sizeof(value), "%lld", val);
+-
+-    pb = slapi_pblock_new();
+-    slapi_modify_internal_set_pb(pb, slapi_sdn_get_dn(token->sdn),
+-                                 mods, NULL, NULL, token->plugin_id, 0);
+-    if (slapi_modify_internal_pb(pb) != 0)
+-        goto error;
+-    if (slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret) != 0)
+-        goto error;
+-    if (ret != LDAP_SUCCESS)
+-        goto error;
+-
+-    success = true;
+-
+-error:
+-    slapi_pblock_destroy(pb);
+-    return success;
+-}
+-
+-/**
+- * Validate a token.
+- *
+- * If the second token code is specified, perform synchronization.
+- */
+-static bool validate(struct otptoken *token, time_t now, ssize_t step,
+-                     uint32_t first, const uint32_t *second)
+-{
+-    const char *attr;
+-    uint32_t tmp;
+-
+-    /* Calculate the absolute step. */
+-    switch (token->type) {
+-    case OTPTOKEN_TOTP:
+-        attr = T("watermark");
+-        step = (now + token->totp.offset) / token->totp.step + step;
+-        if (token->totp.watermark > 0 && step < token->totp.watermark)
+-            return false;
+-        break;
+-    case OTPTOKEN_HOTP:
+-        if (step < 0) /* NEVER go backwards! */
+-            return false;
+-        attr = H("counter");
+-        step = token->hotp.counter + step;
+-        break;
+-    default:
+-        return false;
+-    }
+-
+-    /* Validate the first code. */
+-    if (!hotp(&token->token, step++, &tmp))
+-        return false;
+-
+-    if (first != tmp)
+-        return false;
+-
+-    /* Validate the second code if specified. */
+-    if (second != NULL) {
+-        if (!hotp(&token->token, step++, &tmp))
+-            return false;
+-
+-        if (*second != tmp)
+-            return false;
+-    }
+-
+-    /* Write the step value. */
+-    if (!writeattr(token, attr, step))
+-        return false;
+-
+-    /* Save our modifications to the object. */
+-    switch (token->type) {
+-    case OTPTOKEN_TOTP:
+-        /* Perform optional synchronization steps. */
+-        if (second != NULL) {
+-            tmp = (step - now / token->totp.step) * token->totp.step;
+-            if (!writeattr(token, T("clockOffset"), tmp))
+-                return false;
+-            token->totp.offset = tmp;
+-        }
+-        token->totp.watermark = step;
+-        break;
+-    case OTPTOKEN_HOTP:
+-        token->hotp.counter = step;
+-        break;
+-    default:
+-        break;
+-    }
+-
+-    return true;
+-}
+-
+-
+-static void otptoken_free(struct otptoken *token)
+-{
+-    if (token == NULL)
+-        return;
+-
+-    slapi_sdn_free(&token->sdn);
+-    free(token->token.key.bytes);
+-    slapi_ch_free_string(&token->token.algo);
+-    free(token);
+-}
+-
+-void otptoken_free_array(struct otptoken **tokens)
+-{
+-    if (tokens == NULL)
+-        return;
+-
+-    for (size_t i = 0; tokens[i] != NULL; i++)
+-        otptoken_free(tokens[i]);
+-
+-    free(tokens);
+-}
+-
+-static struct otptoken *otptoken_new(Slapi_ComponentId *id, Slapi_Entry *entry)
+-{
+-    const struct berval *tmp;
+-    struct otptoken *token;
+-    char **vals;
+-
+-    token = calloc(1, sizeof(struct otptoken));
+-    if (token == NULL)
+-        return NULL;
+-    token->plugin_id = id;
+-
+-    /* Get the token type. */
+-    vals = slapi_entry_attr_get_charray(entry, "objectClass");
+-    if (vals == NULL)
+-        goto error;
+-    token->type = OTPTOKEN_NONE;
+-    for (int i = 0; vals[i] != NULL; i++) {
+-        if (strcasecmp(vals[i], "ipaTokenTOTP") == 0)
+-            token->type = OTPTOKEN_TOTP;
+-        else if (strcasecmp(vals[i], "ipaTokenHOTP") == 0)
+-            token->type = OTPTOKEN_HOTP;
+-    }
+-    slapi_ch_array_free(vals);
+-    if (token->type == OTPTOKEN_NONE)
+-        goto error;
+-
+-    /* Get SDN. */
+-    token->sdn = slapi_sdn_dup(slapi_entry_get_sdn(entry));
+-    if (token->sdn == NULL)
+-        goto error;
+-
+-    /* Get key. */
+-    tmp = entry_attr_get_berval(entry, O("key"));
+-    if (tmp == NULL)
+-        goto error;
+-    token->token.key.len = tmp->bv_len;
+-    token->token.key.bytes = malloc(token->token.key.len);
+-    if (token->token.key.bytes == NULL)
+-        goto error;
+-    memcpy(token->token.key.bytes, tmp->bv_val, token->token.key.len);
+-
+-    /* Get length. */
+-    token->token.digits = slapi_entry_attr_get_int(entry, O("digits"));
+-    if (token->token.digits != 6 && token->token.digits != 8)
+-        goto error;
+-
+-    /* Get algorithm. */
+-    token->token.algo = slapi_entry_attr_get_charptr(entry, O("algorithm"));
+-    if (token->token.algo == NULL)
+-        token->token.algo = slapi_ch_strdup("sha1");
+-    if (!is_algo_valid(token->token.algo))
+-        goto error;
+-
+-    switch (token->type) {
+-    case OTPTOKEN_TOTP:
+-        /* Get offset. */
+-        token->totp.offset = slapi_entry_attr_get_int(entry, T("clockOffset"));
+-
+-        /* Get watermark. */
+-        token->totp.watermark = slapi_entry_attr_get_int(entry, T("watermark"));
+-
+-        /* Get step. */
+-        token->totp.step = slapi_entry_attr_get_uint(entry, T("timeStep"));
+-        if (token->totp.step == 0)
+-            token->totp.step = IPA_OTP_DEFAULT_TOKEN_STEP;
+-        break;
+-    case OTPTOKEN_HOTP:
+-        /* Get counter. */
+-        token->hotp.counter = slapi_entry_attr_get_int(entry, H("counter"));
+-        break;
+-    default:
+-        break;
+-    }
+-
+-    return token;
+-
+-error:
+-    otptoken_free(token);
+-    return NULL;
+-}
+-
+-static struct otptoken **find(Slapi_ComponentId *id, const char *user_dn,
+-                              const char *token_dn, const char *intfilter,
+-                              const char *extfilter)
+-{
+-    struct otptoken **tokens = NULL;
+-    Slapi_Entry **entries = NULL;
+-    Slapi_PBlock *pb = NULL;
+-    Slapi_DN *sdn = NULL;
+-    char *filter = NULL;
+-    const char *basedn = NULL;
+-    size_t count = 0;
+-    int result = -1;
+-
+-    if (intfilter == NULL)
+-        intfilter = "";
+-
+-    if (extfilter == NULL)
+-        extfilter = "";
+-
+-    /* Create the filter. */
+-    if (user_dn == NULL) {
+-        filter = "(&" IPA_OTP_OBJCLS_FILTER "%s%s)";
+-        filter = slapi_filter_sprintf(filter, intfilter, extfilter);
+-    } else {
+-        filter = "(&" IPA_OTP_OBJCLS_FILTER "(ipatokenOwner=%s%s)%s%s)";
+-        filter = slapi_filter_sprintf(filter, ESC_AND_NORM_NEXT_VAL,
+-                                      user_dn, intfilter, extfilter);
+-    }
+-
+-    /* Create the search. */
+-    pb = slapi_pblock_new();
+-    if (token_dn != NULL) {
+-        /* Find only the token specified. */
+-        slapi_search_internal_set_pb(pb, token_dn, LDAP_SCOPE_BASE, filter,
+-                                     NULL, 0, NULL, NULL, id, 0);
+-    } else {
+-        sdn = slapi_sdn_new_dn_byval(user_dn);
+-        if (sdn == NULL)
+-            goto error;
+-
+-        basedn = get_basedn(sdn);
+-        if (basedn == NULL)
+-            goto error;
+-
+-        /* Find all user tokens. */
+-        slapi_search_internal_set_pb(pb, basedn,
+-                                     LDAP_SCOPE_SUBTREE, filter, NULL,
+-                                     0, NULL, NULL, id, 0);
+-    }
+-    slapi_search_internal_pb(pb);
+-    slapi_ch_free_string(&filter);
+-
+-    /* Get the results. */
+-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+-    if (result != LDAP_SUCCESS)
+-        goto error;
+-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+-    if (entries == NULL)
+-        goto error;
+-
+-    /* TODO: Can I get the count another way? */
+-    for (count = 0; entries[count] != NULL; count++)
+-        continue;
+-
+-    /* Create the array. */
+-    tokens = calloc(count + 1, sizeof(*tokens));
+-    if (tokens == NULL)
+-        goto error;
+-    for (count = 0; entries[count] != NULL; count++) {
+-        tokens[count] = otptoken_new(id, entries[count]);
+-        if (tokens[count] == NULL) {
+-            otptoken_free_array(tokens);
+-            tokens = NULL;
+-            goto error;
+-        }
+-    }
+-
+-error:
+-    if (sdn != NULL)
+-        slapi_sdn_free(&sdn);
+-    slapi_pblock_destroy(pb);
+-    return tokens;
+-}
+-
+-struct otptoken **otptoken_find(Slapi_ComponentId *id, const char *user_dn,
+-                                const char *token_dn, bool active,
+-                                const char *filter)
+-{
+-    static const char template[] =
+-    "(|(ipatokenNotBefore<=%04d%02d%02d%02d%02d%02dZ)(!(ipatokenNotBefore=*)))"
+-    "(|(ipatokenNotAfter>=%04d%02d%02d%02d%02d%02dZ)(!(ipatokenNotAfter=*)))"
+-    "(|(ipatokenDisabled=FALSE)(!(ipatokenDisabled=*)))";
+-    char actfilt[sizeof(template)];
+-    struct tm tm;
+-    time_t now;
+-
+-    if (!active)
+-        return find(id, user_dn, token_dn, NULL, filter);
+-
+-    /* Get the current time. */
+-    if (time(&now) == (time_t) -1)
+-        return NULL;
+-    if (gmtime_r(&now, &tm) == NULL)
+-        return NULL;
+-
+-    /* Get the current time string. */
+-    if (snprintf(actfilt, sizeof(actfilt), template,
+-                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+-                 tm.tm_hour, tm.tm_min, tm.tm_sec,
+-                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+-                 tm.tm_hour, tm.tm_min, tm.tm_sec) < 0)
+-        return NULL;
+-
+-    return find(id, user_dn, token_dn, actfilt, filter);
+-}
+-
+-int otptoken_get_digits(struct otptoken *token)
+-{
+-    return token == NULL ? 0 : token->token.digits;
+-}
+-
+-const Slapi_DN *otptoken_get_sdn(struct otptoken *token)
+-{
+-    return token->sdn;
+-}
+-
+-static bool otptoken_validate(struct otptoken *token, size_t steps,
+-                              uint32_t code)
+-{
+-    time_t now = 0;
+-
+-    if (token == NULL)
+-        return false;
+-
+-    /* We only need the local time for time-based tokens. */
+-    if (token->type == OTPTOKEN_TOTP && time(&now) == (time_t) -1)
+-        return false;
+-
+-    for (int i = 0; i <= steps; i++) {
+-        /* Validate the positive step. */
+-        if (validate(token, now, i, code, NULL))
+-            return true;
+-
+-        /* Validate the negative step. */
+-        if (validate(token, now, 0 - i, code, NULL))
+-            return true;
+-    }
+-
+-    return false;
+-}
+-
+-
+-/*
+- *  Convert code berval to decimal.
+- *
+- *  NOTE: We can't use atol() or strtoul() because:
+- *    1. If we have leading zeros, atol() fails.
+- *    2. Neither support limiting conversion by length.
+- */
+-static bool bvtod(const struct berval *code, uint32_t *out)
+-{
+-    *out = 0;
+-
+-    for (ber_len_t i = 0; i < code->bv_len; i++) {
+-        if (code->bv_val[i] < '0' || code->bv_val[i] > '9')
+-            return false;
+-        *out *= 10;
+-        *out += code->bv_val[i] - '0';
+-    }
+-
+-    return code->bv_len != 0;
+-}
+-
+-bool otptoken_validate_berval(struct otptoken *token, size_t steps,
+-                              const struct berval *code, bool tail)
+-{
+-    struct berval tmp;
+-    uint32_t otp;
+-
+-    if (token == NULL || code == NULL)
+-        return false;
+-    tmp = *code;
+-
+-    if (tmp.bv_len < token->token.digits)
+-        return false;
+-
+-    if (tail)
+-        tmp.bv_val = &tmp.bv_val[tmp.bv_len - token->token.digits];
+-    tmp.bv_len = token->token.digits;
+-
+-    if (!bvtod(&tmp, &otp))
+-        return false;
+-
+-    return otptoken_validate(token, steps, otp);
+-}
+-
+-static bool otptoken_sync(struct otptoken * const *tokens, size_t steps,
+-                          uint32_t first_code, uint32_t second_code)
+-{
+-    time_t now = 0;
+-
+-    if (tokens == NULL)
+-        return false;
+-
+-    if (time(&now) == (time_t) -1)
+-        return false;
+-
+-    for (int i = 0; i <= steps; i++) {
+-        for (int j = 0; tokens[j] != NULL; j++) {
+-            /* Validate the positive step. */
+-            if (validate(tokens[j], now, i, first_code, &second_code))
+-                return true;
+-
+-            /* Validate the negative step. */
+-            if (validate(tokens[j], now, 0 - i, first_code, &second_code))
+-                return true;
+-        }
+-    }
+-
+-    return false;
+-}
+-
+-bool otptoken_sync_berval(struct otptoken * const *tokens, size_t steps,
+-                          const struct berval *first_code,
+-                          const struct berval *second_code)
+-{
+-    uint32_t second = 0;
+-    uint32_t first = 0;
+-
+-    if (!bvtod(first_code, &first))
+-        return false;
+-
+-    if (!bvtod(second_code, &second))
+-        return false;
+-
+-    return otptoken_sync(tokens, steps, first, second);
+-}
+diff --git a/daemons/ipa-slapi-plugins/libotp/libotp.h b/daemons/ipa-slapi-plugins/libotp/libotp.h
+deleted file mode 100644
+index 24915f8667dfa13ffb1ae47d223df95d4622012e..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/libotp/libotp.h
++++ /dev/null
+@@ -1,93 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2013 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-#ifndef LIBOTP_H_
+-#define LIBOTP_H_
+-
+-#ifdef HAVE_CONFIG_H
+-#  include <config.h>
+-#endif
+-
+-#include <dirsrv/slapi-plugin.h>
+-#include <stdbool.h>
+-#include <stdlib.h>
+-
+-struct otptoken;
+-
+-/* Frees the token array. */
+-void otptoken_free_array(struct otptoken **tokens);
+-
+-/* Find tokens.
+- *
+- * All criteria below are cumulative. For example, if you specify both dn and
+- * active and the token at the dn specified isn't active, an empty array will
+- * be returned.
+- *
+- * If user_dn is not NULL, the user's tokens are returned.
+- *
+- * If token_dn is not NULL, only this specified token is returned.
+- *
+- * If active is true, only tokens that are active are returned.
+- *
+- * If filter is not NULL, the filter will be added to the search criteria.
+- *
+- * Returns NULL on error. If no tokens are found, an empty array is returned.
+- * The array is NULL terminated.
+- */
+-struct otptoken **otptoken_find(Slapi_ComponentId *id, const char *user_dn,
+-                                const char *token_dn, bool active,
+-                                const char *filter);
+-
+-/* Get the length of the token code. */
+-int otptoken_get_digits(struct otptoken *token);
+-
+-/* Get the SDN of the token. */
+-const Slapi_DN *otptoken_get_sdn(struct otptoken *token);
+-
+-/* Validate the token code within a range of steps. If tail is true,
+- * it will be assumed that the token is specified at the end of the string. */
+-bool otptoken_validate_berval(struct otptoken *token, size_t steps,
+-                              const struct berval *code, bool tail);
+-
+-/* Synchronize the token within a range of steps. */
+-bool otptoken_sync_berval(struct otptoken * const *tokens, size_t steps,
+-                          const struct berval *first_code,
+-                          const struct berval *second_code);
+-
+-#endif /* LIBOTP_H_ */
+diff --git a/daemons/ipa-slapi-plugins/libotp/librfc.c b/daemons/ipa-slapi-plugins/libotp/librfc.c
+deleted file mode 100644
+index d74820e957e3753834f376cd3ea0ae748e450243..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/libotp/librfc.c
++++ /dev/null
+@@ -1,170 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2013 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-/*
+- * This file contains an implementation of HOTP (RFC 4226) and TOTP (RFC 6238).
+- * For details of how these algorithms work, please see the relevant RFCs.
+- */
+-
+-#include "librfc.h"
+-#include <time.h>
+-
+-#include <nss.h>
+-#include <pk11pub.h>
+-#include <hasht.h>
+-#include <prnetdb.h>
+-
+-struct digest_buffer {
+-    uint8_t buf[SHA512_LENGTH];
+-    unsigned int len;
+-};
+-
+-static const struct {
+-    const char *algo;
+-    CK_MECHANISM_TYPE mech;
+-} algo2mech[] = {
+-    { "sha1",   CKM_SHA_1_HMAC },
+-    { "sha256", CKM_SHA256_HMAC },
+-    { "sha384", CKM_SHA384_HMAC },
+-    { "sha512", CKM_SHA512_HMAC },
+-    { }
+-};
+-
+-/*
+- * This code is mostly cargo-cult taken from here:
+- *   http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn5.html
+- *
+- * It should implement HMAC with the given mechanism (SHA: 1, 256, 384, 512).
+- */
+-static bool hmac(SECItem *key, CK_MECHANISM_TYPE mech, const SECItem *in,
+-                 struct digest_buffer *out)
+-{
+-    SECItem param = { siBuffer, NULL, 0 };
+-    PK11SlotInfo *slot = NULL;
+-    PK11SymKey *symkey = NULL;
+-    PK11Context *ctx = NULL;
+-    bool ret = false;
+-    SECStatus s;
+-
+-    slot = PK11_GetBestSlot(mech, NULL);
+-    if (slot == NULL) {
+-        slot = PK11_GetInternalKeySlot();
+-        if (slot == NULL) {
+-            goto done;
+-        }
+-    }
+-
+-    symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
+-                               CKA_SIGN, key, NULL);
+-    if (symkey == NULL)
+-        goto done;
+-
+-    ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, symkey, &param);
+-    if (ctx == NULL)
+-        goto done;
+-
+-    s = PK11_DigestBegin(ctx);
+-    if (s != SECSuccess)
+-        goto done;
+-
+-    s = PK11_DigestOp(ctx, in->data, in->len);
+-    if (s != SECSuccess)
+-        goto done;
+-
+-    s = PK11_DigestFinal(ctx, out->buf, &out->len, sizeof(out->buf));
+-    if (s != SECSuccess)
+-        goto done;
+-
+-    ret = true;
+-
+-done:
+-    if (ctx != NULL)
+-        PK11_DestroyContext(ctx, PR_TRUE);
+-    if (symkey != NULL)
+-        PK11_FreeSymKey(symkey);
+-    if (slot != NULL)
+-        PK11_FreeSlot(slot);
+-    return ret;
+-}
+-
+-/*
+- * An implementation of HOTP (RFC 4226).
+- */
+-bool hotp(const struct hotp_token *token, uint64_t counter, uint32_t *out)
+-{
+-    const SECItem cntr = { siBuffer, (uint8_t *) &counter, sizeof(counter) };
+-    SECItem keyitm = { siBuffer, token->key.bytes, token->key.len };
+-    CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC;
+-    PRUint64 offset, binary, div;
+-    struct digest_buffer digest;
+-    int digits = token->digits;
+-    int i;
+-
+-    /* Convert counter to network byte order. */
+-    counter = PR_htonll(counter);
+-
+-    /* Find the mech. */
+-    for (i = 0; algo2mech[i].algo; i++) {
+-        if (strcasecmp(algo2mech[i].algo, token->algo) == 0) {
+-            mech = algo2mech[i].mech;
+-            break;
+-        }
+-    }
+-
+-    /* Create the digits divisor. */
+-    for (div = 1; digits > 0; digits--) {
+-        div *= 10;
+-    }
+-
+-    /* Do the digest. */
+-    if (!hmac(&keyitm, mech, &cntr, &digest)) {
+-        return false;
+-    }
+-
+-    /* Truncate. */
+-    offset  = digest.buf[digest.len - 1] & 0xf;
+-    binary  = (digest.buf[offset + 0] & 0x7f) << 0x18;
+-    binary |= (digest.buf[offset + 1] & 0xff) << 0x10;
+-    binary |= (digest.buf[offset + 2] & 0xff) << 0x08;
+-    binary |= (digest.buf[offset + 3] & 0xff) << 0x00;
+-    binary  = binary % div;
+-
+-    *out = binary;
+-    return true;
+-}
+diff --git a/daemons/ipa-slapi-plugins/libotp/librfc.h b/daemons/ipa-slapi-plugins/libotp/librfc.h
+deleted file mode 100644
+index 04b117600fbcb03fd61258afdd892ae3d514a121..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/libotp/librfc.h
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2013 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-#ifndef LIBRFC_H_
+-#define LIBRFC_H_
+-
+-#include <stdbool.h>
+-#include <stdint.h>
+-#include <stdlib.h>
+-
+-struct hotp_token_key {
+-    uint8_t *bytes;
+-    size_t len;
+-};
+-
+-struct hotp_token {
+-    struct hotp_token_key key;
+-    char *algo;
+-    int digits;
+-};
+-
+-/*
+- * An implementation of HOTP (RFC 4226).
+- */
+-bool hotp(const struct hotp_token *token, uint64_t counter, uint32_t *out);
+-
+-#endif /* LIBRFC_H_ */
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..7860c8aba6e12e319d633ee8e165403289a7528b
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c
+@@ -0,0 +1,572 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#include "otp_token.h"
++#include "hotp.h"
++
++#include <time.h>
++#include <errno.h>
++
++#define TOKEN(s) "ipaToken" s
++#define O(s) TOKEN("OTP" s)
++#define T(s) TOKEN("TOTP" s)
++#define H(s) TOKEN("HOTP" s)
++
++#define IPA_OTP_DEFAULT_TOKEN_STEP 30
++#define IPA_OTP_OBJCLS_FILTER \
++    "(|(objectClass=ipaTokenTOTP)(objectClass=ipaTokenHOTP))"
++
++enum type {
++    TYPE_NONE = 0,
++    TYPE_TOTP,
++    TYPE_HOTP,
++};
++
++struct otp_token {
++    Slapi_ComponentId *plugin_id;
++    Slapi_DN *sdn;
++    struct hotp_token token;
++    enum type type;
++    union {
++        struct {
++            uint64_t watermark;
++            unsigned int step;
++            int offset;
++        } totp;
++        struct {
++            uint64_t counter;
++        } hotp;
++    };
++};
++
++static const char *get_basedn(Slapi_DN *dn)
++{
++    Slapi_DN *suffix = NULL;
++    void *node = NULL;
++
++    for (suffix = slapi_get_first_suffix(&node, 0);
++         suffix != NULL;
++         suffix = slapi_get_next_suffix(&node, 0)) {
++        if (slapi_sdn_issuffix(dn, suffix))
++            return (char *) slapi_sdn_get_dn(suffix);
++    }
++
++    return NULL;
++}
++
++static inline bool is_algo_valid(const char *algo)
++{
++    static const char *valid_algos[] = { "sha1", "sha256", "sha384",
++                                         "sha512", NULL };
++    int i, ret;
++
++    for (i = 0; valid_algos[i]; i++) {
++        ret = strcasecmp(algo, valid_algos[i]);
++        if (ret == 0)
++            return true;
++    }
++
++    return false;
++}
++
++static const struct berval *entry_attr_get_berval(const Slapi_Entry* e,
++                                                  const char *type)
++{
++    Slapi_Attr* attr = NULL;
++    Slapi_Value *v;
++    int ret;
++
++    ret = slapi_entry_attr_find(e, type, &attr);
++    if (ret != 0 || attr == NULL)
++        return NULL;
++
++    ret = slapi_attr_first_value(attr, &v);
++    if (ret < 0)
++        return NULL;
++
++    return slapi_value_get_berval(v);
++}
++
++static bool writeattr(const struct otp_token *token, const char *attr,
++                      long long val)
++{
++    Slapi_PBlock *pb = NULL;
++    bool success = false;
++    char value[32];
++    int ret;
++
++    LDAPMod *mods[] = {
++        &(LDAPMod) {
++            LDAP_MOD_REPLACE, (char *) attr,
++            .mod_values = (char *[]) { value, NULL }
++        },
++        NULL
++    };
++
++    snprintf(value, sizeof(value), "%lld", val);
++
++    pb = slapi_pblock_new();
++    slapi_modify_internal_set_pb(pb, slapi_sdn_get_dn(token->sdn),
++                                 mods, NULL, NULL, token->plugin_id, 0);
++    if (slapi_modify_internal_pb(pb) != 0)
++        goto error;
++    if (slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret) != 0)
++        goto error;
++    if (ret != LDAP_SUCCESS)
++        goto error;
++
++    success = true;
++
++error:
++    slapi_pblock_destroy(pb);
++    return success;
++}
++
++/**
++ * Validate a token.
++ *
++ * If the second token code is specified, perform synchronization.
++ */
++static bool validate(struct otp_token *token, time_t now, ssize_t step,
++                     uint32_t first, const uint32_t *second)
++{
++    const char *attr;
++    uint32_t tmp;
++
++    /* Calculate the absolute step. */
++    switch (token->type) {
++    case TYPE_TOTP:
++        attr = T("watermark");
++        step = (now + token->totp.offset) / token->totp.step + step;
++        if (token->totp.watermark > 0 && step < token->totp.watermark)
++            return false;
++        break;
++    case TYPE_HOTP:
++        if (step < 0) /* NEVER go backwards! */
++            return false;
++        attr = H("counter");
++        step = token->hotp.counter + step;
++        break;
++    default:
++        return false;
++    }
++
++    /* Validate the first code. */
++    if (!hotp(&token->token, step++, &tmp))
++        return false;
++
++    if (first != tmp)
++        return false;
++
++    /* Validate the second code if specified. */
++    if (second != NULL) {
++        if (!hotp(&token->token, step++, &tmp))
++            return false;
++
++        if (*second != tmp)
++            return false;
++    }
++
++    /* Write the step value. */
++    if (!writeattr(token, attr, step))
++        return false;
++
++    /* Save our modifications to the object. */
++    switch (token->type) {
++    case TYPE_TOTP:
++        /* Perform optional synchronization steps. */
++        if (second != NULL) {
++            tmp = (step - now / token->totp.step) * token->totp.step;
++            if (!writeattr(token, T("clockOffset"), tmp))
++                return false;
++            token->totp.offset = tmp;
++        }
++        token->totp.watermark = step;
++        break;
++    case TYPE_HOTP:
++        token->hotp.counter = step;
++        break;
++    default:
++        break;
++    }
++
++    return true;
++}
++
++static void otp_token_free(struct otp_token *token)
++{
++    if (token == NULL)
++        return;
++
++    slapi_sdn_free(&token->sdn);
++    free(token->token.key.bytes);
++    slapi_ch_free_string(&token->token.algo);
++    free(token);
++}
++
++void otp_token_free_array(struct otp_token **tokens)
++{
++    if (tokens == NULL)
++        return;
++
++    for (size_t i = 0; tokens[i] != NULL; i++)
++        otp_token_free(tokens[i]);
++
++    free(tokens);
++}
++
++static struct otp_token *otp_token_new(Slapi_ComponentId *id,
++                                       Slapi_Entry *entry)
++{
++    const struct berval *tmp;
++    struct otp_token *token;
++    char **vals;
++
++    token = calloc(1, sizeof(struct otp_token));
++    if (token == NULL)
++        return NULL;
++    token->plugin_id = id;
++
++    /* Get the token type. */
++    vals = slapi_entry_attr_get_charray(entry, "objectClass");
++    if (vals == NULL)
++        goto error;
++    token->type = TYPE_NONE;
++    for (int i = 0; vals[i] != NULL; i++) {
++        if (strcasecmp(vals[i], "ipaTokenTOTP") == 0)
++            token->type = TYPE_TOTP;
++        else if (strcasecmp(vals[i], "ipaTokenHOTP") == 0)
++            token->type = TYPE_HOTP;
++    }
++    slapi_ch_array_free(vals);
++    if (token->type == TYPE_NONE)
++        goto error;
++
++    /* Get SDN. */
++    token->sdn = slapi_sdn_dup(slapi_entry_get_sdn(entry));
++    if (token->sdn == NULL)
++        goto error;
++
++    /* Get key. */
++    tmp = entry_attr_get_berval(entry, O("key"));
++    if (tmp == NULL)
++        goto error;
++    token->token.key.len = tmp->bv_len;
++    token->token.key.bytes = malloc(token->token.key.len);
++    if (token->token.key.bytes == NULL)
++        goto error;
++    memcpy(token->token.key.bytes, tmp->bv_val, token->token.key.len);
++
++    /* Get length. */
++    token->token.digits = slapi_entry_attr_get_int(entry, O("digits"));
++    if (token->token.digits != 6 && token->token.digits != 8)
++        goto error;
++
++    /* Get algorithm. */
++    token->token.algo = slapi_entry_attr_get_charptr(entry, O("algorithm"));
++    if (token->token.algo == NULL)
++        token->token.algo = slapi_ch_strdup("sha1");
++    if (!is_algo_valid(token->token.algo))
++        goto error;
++
++    switch (token->type) {
++    case TYPE_TOTP:
++        /* Get offset. */
++        token->totp.offset = slapi_entry_attr_get_int(entry, T("clockOffset"));
++
++        /* Get watermark. */
++        token->totp.watermark = slapi_entry_attr_get_int(entry, T("watermark"));
++
++        /* Get step. */
++        token->totp.step = slapi_entry_attr_get_uint(entry, T("timeStep"));
++        if (token->totp.step == 0)
++            token->totp.step = IPA_OTP_DEFAULT_TOKEN_STEP;
++        break;
++    case TYPE_HOTP:
++        /* Get counter. */
++        token->hotp.counter = slapi_entry_attr_get_int(entry, H("counter"));
++        break;
++    default:
++        break;
++    }
++
++    return token;
++
++error:
++    otp_token_free(token);
++    return NULL;
++}
++
++static struct otp_token **find(Slapi_ComponentId *id, const char *user_dn,
++                               const char *token_dn, const char *intfilter,
++                               const char *extfilter)
++{
++    struct otp_token **tokens = NULL;
++    Slapi_Entry **entries = NULL;
++    Slapi_PBlock *pb = NULL;
++    Slapi_DN *sdn = NULL;
++    char *filter = NULL;
++    const char *basedn = NULL;
++    size_t count = 0;
++    int result = -1;
++
++    if (intfilter == NULL)
++        intfilter = "";
++
++    if (extfilter == NULL)
++        extfilter = "";
++
++    /* Create the filter. */
++    if (user_dn == NULL) {
++        filter = "(&" IPA_OTP_OBJCLS_FILTER "%s%s)";
++        filter = slapi_filter_sprintf(filter, intfilter, extfilter);
++    } else {
++        filter = "(&" IPA_OTP_OBJCLS_FILTER "(ipatokenOwner=%s%s)%s%s)";
++        filter = slapi_filter_sprintf(filter, ESC_AND_NORM_NEXT_VAL,
++                                      user_dn, intfilter, extfilter);
++    }
++
++    /* Create the search. */
++    pb = slapi_pblock_new();
++    if (token_dn != NULL) {
++        /* Find only the token specified. */
++        slapi_search_internal_set_pb(pb, token_dn, LDAP_SCOPE_BASE, filter,
++                                     NULL, 0, NULL, NULL, id, 0);
++    } else {
++        sdn = slapi_sdn_new_dn_byval(user_dn);
++        if (sdn == NULL)
++            goto error;
++
++        basedn = get_basedn(sdn);
++        if (basedn == NULL)
++            goto error;
++
++        /* Find all user tokens. */
++        slapi_search_internal_set_pb(pb, basedn,
++                                     LDAP_SCOPE_SUBTREE, filter, NULL,
++                                     0, NULL, NULL, id, 0);
++    }
++    slapi_search_internal_pb(pb);
++    slapi_ch_free_string(&filter);
++
++    /* Get the results. */
++    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
++    if (result != LDAP_SUCCESS)
++        goto error;
++    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
++    if (entries == NULL)
++        goto error;
++
++    /* TODO: Can I get the count another way? */
++    for (count = 0; entries[count] != NULL; count++)
++        continue;
++
++    /* Create the array. */
++    tokens = calloc(count + 1, sizeof(*tokens));
++    if (tokens == NULL)
++        goto error;
++    for (count = 0; entries[count] != NULL; count++) {
++        tokens[count] = otp_token_new(id, entries[count]);
++        if (tokens[count] == NULL) {
++            otp_token_free_array(tokens);
++            tokens = NULL;
++            goto error;
++        }
++    }
++
++error:
++    if (sdn != NULL)
++        slapi_sdn_free(&sdn);
++    slapi_pblock_destroy(pb);
++    return tokens;
++}
++
++struct otp_token **
++otp_token_find(Slapi_ComponentId *id, const char *user_dn, const char *token_dn,
++               bool active, const char *filter)
++{
++    static const char template[] =
++    "(|(ipatokenNotBefore<=%04d%02d%02d%02d%02d%02dZ)(!(ipatokenNotBefore=*)))"
++    "(|(ipatokenNotAfter>=%04d%02d%02d%02d%02d%02dZ)(!(ipatokenNotAfter=*)))"
++    "(|(ipatokenDisabled=FALSE)(!(ipatokenDisabled=*)))";
++    char actfilt[sizeof(template)];
++    struct tm tm;
++    time_t now;
++
++    if (!active)
++        return find(id, user_dn, token_dn, NULL, filter);
++
++    /* Get the current time. */
++    if (time(&now) == (time_t) -1)
++        return NULL;
++    if (gmtime_r(&now, &tm) == NULL)
++        return NULL;
++
++    /* Get the current time string. */
++    if (snprintf(actfilt, sizeof(actfilt), template,
++                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
++                 tm.tm_hour, tm.tm_min, tm.tm_sec,
++                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
++                 tm.tm_hour, tm.tm_min, tm.tm_sec) < 0)
++        return NULL;
++
++    return find(id, user_dn, token_dn, actfilt, filter);
++}
++
++int otp_token_get_digits(struct otp_token *token)
++{
++    return token == NULL ? 0 : token->token.digits;
++}
++
++const Slapi_DN *otp_token_get_sdn(struct otp_token *token)
++{
++    return token->sdn;
++}
++
++static bool otp_token_validate(struct otp_token *token, size_t steps,
++                               uint32_t code)
++{
++    time_t now = 0;
++
++    if (token == NULL)
++        return false;
++
++    /* We only need the local time for time-based tokens. */
++    if (token->type == TYPE_TOTP && time(&now) == (time_t) -1)
++        return false;
++
++    for (int i = 0; i <= steps; i++) {
++        /* Validate the positive step. */
++        if (validate(token, now, i, code, NULL))
++            return true;
++
++        /* Validate the negative step. */
++        if (validate(token, now, 0 - i, code, NULL))
++            return true;
++    }
++
++    return false;
++}
++
++
++/*
++ *  Convert code berval to decimal.
++ *
++ *  NOTE: We can't use atol() or strtoul() because:
++ *    1. If we have leading zeros, atol() fails.
++ *    2. Neither support limiting conversion by length.
++ */
++static bool bvtod(const struct berval *code, uint32_t *out)
++{
++    *out = 0;
++
++    for (ber_len_t i = 0; i < code->bv_len; i++) {
++        if (code->bv_val[i] < '0' || code->bv_val[i] > '9')
++            return false;
++        *out *= 10;
++        *out += code->bv_val[i] - '0';
++    }
++
++    return code->bv_len != 0;
++}
++
++bool otp_token_validate_berval(struct otp_token *token, size_t steps,
++                               const struct berval *code, bool tail)
++{
++    struct berval tmp;
++    uint32_t otp;
++
++    if (token == NULL || code == NULL)
++        return false;
++    tmp = *code;
++
++    if (tmp.bv_len < token->token.digits)
++        return false;
++
++    if (tail)
++        tmp.bv_val = &tmp.bv_val[tmp.bv_len - token->token.digits];
++    tmp.bv_len = token->token.digits;
++
++    if (!bvtod(&tmp, &otp))
++        return false;
++
++    return otp_token_validate(token, steps, otp);
++}
++
++static bool otp_token_sync(struct otp_token * const *tokens, size_t steps,
++                           uint32_t first_code, uint32_t second_code)
++{
++    time_t now = 0;
++
++    if (tokens == NULL)
++        return false;
++
++    if (time(&now) == (time_t) -1)
++        return false;
++
++    for (int i = 0; i <= steps; i++) {
++        for (int j = 0; tokens[j] != NULL; j++) {
++            /* Validate the positive step. */
++            if (validate(tokens[j], now, i, first_code, &second_code))
++                return true;
++
++            /* Validate the negative step. */
++            if (validate(tokens[j], now, 0 - i, first_code, &second_code))
++                return true;
++        }
++    }
++
++    return false;
++}
++
++bool otp_token_sync_berval(struct otp_token * const *tokens, size_t steps,
++                           const struct berval *first_code,
++                           const struct berval *second_code)
++{
++    uint32_t second = 0;
++    uint32_t first = 0;
++
++    if (!bvtod(first_code, &first))
++        return false;
++
++    if (!bvtod(second_code, &second))
++        return false;
++
++    return otp_token_sync(tokens, steps, first, second);
++}
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.h b/daemons/ipa-slapi-plugins/libotp/otp_token.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..2f336780682b5ea2838b558079e2ae85f6e2afba
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/otp_token.h
+@@ -0,0 +1,87 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#pragma once
++
++#include <dirsrv/slapi-plugin.h>
++#include <stdbool.h>
++#include <stdlib.h>
++
++struct otp_token;
++
++/* Frees the token array. */
++void otp_token_free_array(struct otp_token **tokens);
++
++/* Find tokens.
++ *
++ * All criteria below are cumulative. For example, if you specify both dn and
++ * active and the token at the dn specified isn't active, an empty array will
++ * be returned.
++ *
++ * If user_dn is not NULL, the user's tokens are returned.
++ *
++ * If token_dn is not NULL, only this specified token is returned.
++ *
++ * If active is true, only tokens that are active are returned.
++ *
++ * If filter is not NULL, the filter will be added to the search criteria.
++ *
++ * Returns NULL on error. If no tokens are found, an empty array is returned.
++ * The array is NULL terminated.
++ */
++struct otp_token **otp_token_find(Slapi_ComponentId *id, const char *user_dn,
++                                  const char *token_dn, bool active,
++                                  const char *filter);
++
++/* Get the length of the token code. */
++int otp_token_get_digits(struct otp_token *token);
++
++/* Get the SDN of the token. */
++const Slapi_DN *otp_token_get_sdn(struct otp_token *token);
++
++/* Validate the token code within a range of steps. If tail is true,
++ * it will be assumed that the token is specified at the end of the string. */
++bool otp_token_validate_berval(struct otp_token *token, size_t steps,
++                               const struct berval *code, bool tail);
++
++/* Synchronize the token within a range of steps. */
++bool otp_token_sync_berval(struct otp_token * const *tokens, size_t steps,
++                           const struct berval *first_code,
++                           const struct berval *second_code);
++
+diff --git a/daemons/ipa-slapi-plugins/libotp/t_hotp.c b/daemons/ipa-slapi-plugins/libotp/t_hotp.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..2e995fdaa3b2aa067790ade307792a95ded269a9
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/t_hotp.c
+@@ -0,0 +1,121 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#include "hotp.h"
++
++#include <assert.h>
++#include <stddef.h>
++#include <time.h>
++#include <string.h>
++#include <nss.h>
++
++#define KEY(s) { (uint8_t *) s, sizeof(s) - 1 }
++
++/* All HOTP test examples from RFC 4226 (Appendix D). */
++static const struct hotp_token hotp_token = {
++    KEY("12345678901234567890"),
++    "sha1",
++    6
++};
++static const uint32_t hotp_answers[] = {
++    755224,
++    287082,
++    359152,
++    969429,
++    338314,
++    254676,
++    287922,
++    162583,
++    399871,
++    520489
++};
++
++/* All TOTP test examples from RFC 6238 (Appendix B). */
++#define SHA1   { KEY("12345678901234567890"), "sha1", 8 }
++#define SHA256 { KEY("12345678901234567890123456789012"), "sha256", 8 }
++#define SHA512 { KEY("12345678901234567890123456789012" \
++                     "34567890123456789012345678901234"), "sha512", 8 }
++static const struct {
++    struct hotp_token token;
++    time_t time;
++    uint32_t answer;
++} totp_tests[] = {
++    { SHA1,            59, 94287082 },
++    { SHA256,          59, 46119246 },
++    { SHA512,          59, 90693936 },
++    { SHA1,    1111111109,  7081804 },
++    { SHA256,  1111111109, 68084774 },
++    { SHA512,  1111111109, 25091201 },
++    { SHA1,    1111111111, 14050471 },
++    { SHA256,  1111111111, 67062674 },
++    { SHA512,  1111111111, 99943326 },
++    { SHA1,    1234567890, 89005924 },
++    { SHA256,  1234567890, 91819424 },
++    { SHA512,  1234567890, 93441116 },
++    { SHA1,    2000000000, 69279037 },
++    { SHA256,  2000000000, 90698825 },
++    { SHA512,  2000000000, 38618901 },
++#ifdef _LP64 /* Only do these tests on 64-bit systems. */
++    { SHA1,   20000000000, 65353130 },
++    { SHA256, 20000000000, 77737706 },
++    { SHA512, 20000000000, 47863826 },
++#endif
++};
++
++int
++main(int argc, const char *argv[])
++{
++    uint32_t otp;
++    int i;
++
++    NSS_NoDB_Init(".");
++
++    for (i = 0; i < sizeof(hotp_answers) / sizeof(*hotp_answers); i++) {
++        assert(hotp(&hotp_token, i, &otp));
++        assert(otp == hotp_answers[i]);
++    }
++
++    for (i = 0; i < sizeof(totp_tests) / sizeof(*totp_tests); i++) {
++        assert(hotp(&totp_tests[i].token, totp_tests[i].time / 30, &otp));
++        assert(otp == totp_tests[i].answer);
++    }
++
++    NSS_Shutdown();
++    return 0;
++}
+diff --git a/daemons/ipa-slapi-plugins/libotp/t_librfc.c b/daemons/ipa-slapi-plugins/libotp/t_librfc.c
+deleted file mode 100644
+index f7eab7f78e99a825a444f8e496be924342d28b51..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/libotp/t_librfc.c
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2013 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-#include "librfc.h"
+-
+-#include <assert.h>
+-#include <stddef.h>
+-#include <time.h>
+-#include <string.h>
+-#include <nss.h>
+-
+-#define KEY(s) { (uint8_t *) s, sizeof(s) - 1 }
+-
+-/* All HOTP test examples from RFC 4226 (Appendix D). */
+-static const struct hotp_token hotp_token = {
+-    KEY("12345678901234567890"),
+-    "sha1",
+-    6
+-};
+-static const uint32_t hotp_answers[] = {
+-    755224,
+-    287082,
+-    359152,
+-    969429,
+-    338314,
+-    254676,
+-    287922,
+-    162583,
+-    399871,
+-    520489
+-};
+-
+-/* All TOTP test examples from RFC 6238 (Appendix B). */
+-#define SHA1   { KEY("12345678901234567890"), "sha1", 8 }
+-#define SHA256 { KEY("12345678901234567890123456789012"), "sha256", 8 }
+-#define SHA512 { KEY("12345678901234567890123456789012" \
+-                     "34567890123456789012345678901234"), "sha512", 8 }
+-static const struct {
+-    struct hotp_token token;
+-    time_t time;
+-    uint32_t answer;
+-} totp_tests[] = {
+-    { SHA1,            59, 94287082 },
+-    { SHA256,          59, 46119246 },
+-    { SHA512,          59, 90693936 },
+-    { SHA1,    1111111109,  7081804 },
+-    { SHA256,  1111111109, 68084774 },
+-    { SHA512,  1111111109, 25091201 },
+-    { SHA1,    1111111111, 14050471 },
+-    { SHA256,  1111111111, 67062674 },
+-    { SHA512,  1111111111, 99943326 },
+-    { SHA1,    1234567890, 89005924 },
+-    { SHA256,  1234567890, 91819424 },
+-    { SHA512,  1234567890, 93441116 },
+-    { SHA1,    2000000000, 69279037 },
+-    { SHA256,  2000000000, 90698825 },
+-    { SHA512,  2000000000, 38618901 },
+-#ifdef _LP64 /* Only do these tests on 64-bit systems. */
+-    { SHA1,   20000000000, 65353130 },
+-    { SHA256, 20000000000, 77737706 },
+-    { SHA512, 20000000000, 47863826 },
+-#endif
+-};
+-
+-int
+-main(int argc, const char *argv[])
+-{
+-    uint32_t otp;
+-    int i;
+-
+-    NSS_NoDB_Init(".");
+-
+-    for (i = 0; i < sizeof(hotp_answers) / sizeof(*hotp_answers); i++) {
+-        assert(hotp(&hotp_token, i, &otp));
+-        assert(otp == hotp_answers[i]);
+-    }
+-
+-    for (i = 0; i < sizeof(totp_tests) / sizeof(*totp_tests); i++) {
+-        assert(hotp(&totp_tests[i].token, totp_tests[i].time / 30, &otp));
+-        assert(otp == totp_tests[i].answer);
+-    }
+-
+-    NSS_Shutdown();
+-    return 0;
+-}
+-- 
+2.1.0
+
diff --git a/SOURCES/0070-ipaserver-dcerpc.py-Make-sure-trust-is-established-o.patch b/SOURCES/0070-ipaserver-dcerpc.py-Make-sure-trust-is-established-o.patch
deleted file mode 100644
index 29ca7e5..0000000
--- a/SOURCES/0070-ipaserver-dcerpc.py-Make-sure-trust-is-established-o.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 079fdf41592559de96465080e81aa91252c01a3d Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 19 Aug 2014 16:24:27 +0300
-Subject: [PATCH] ipaserver/dcerpc.py: Make sure trust is established only to
- forest root domain
-
-Part of https://fedorahosted.org/freeipa/ticket/4463
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- ipalib/errors.py    | 16 ++++++++++++++++
- ipaserver/dcerpc.py |  6 ++++++
- 2 files changed, 22 insertions(+)
-
-diff --git a/ipalib/errors.py b/ipalib/errors.py
-index 716decb2b41baf5470a1dc23c0cfb5d1c995e5ff..405c5c3bfc25d9b024189be9fcf582052dd10dd3 100644
---- a/ipalib/errors.py
-+++ b/ipalib/errors.py
-@@ -810,6 +810,22 @@ class DeprecationError(InvocationError):
-     errno = 3015
-     format = _("Command '%(name)s' has been deprecated")
- 
-+class NotAForestRootError(InvocationError):
-+    """
-+    **3016** Raised when an attempt to establish trust is done against non-root domain
-+             Forest root domain has the same name as the forest itself
-+
-+    For example:
-+
-+    >>> raise NotAForestRootError(forest='example.test', domain='jointops.test')
-+    Traceback (most recent call last):
-+      ...
-+    NotAForestRootError: Domain 'jointops.test' is not a root domain for forest 'example.test'
-+    """
-+
-+    errno = 3016
-+    format = _("Domain '%(domain)s' is not a root domain for forest '%(forest)s'")
-+
- 
- ##############################################################################
- # 4000 - 4999: Execution errors
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index fcf1e4e775868f17220cac3c0203cc67dba2f839..41f373df3cc4365727200f3ca4667faac2f9e19c 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -1143,6 +1143,9 @@ class TrustDomainJoins(object):
-                 realm_passwd
-             )
- 
-+        if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']:
-+            raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], domain=self.remote_domain.info['dns_domain'])
-+
-         if not self.remote_domain.read_only:
-             trustdom_pass = samba.generate_random_password(128, 128)
-             self.get_realmdomains()
-@@ -1159,5 +1162,8 @@ class TrustDomainJoins(object):
-         if not(isinstance(self.remote_domain, TrustDomainInstance)):
-             self.populate_remote_domain(realm, realm_server, realm_passwd=None)
- 
-+        if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']:
-+            raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], domain=self.remote_domain.info['dns_domain'])
-+
-         self.local_domain.establish_trust(self.remote_domain, trustdom_passwd)
-         return dict(local=self.local_domain, remote=self.remote_domain, verified=False)
--- 
-1.9.3
-
diff --git a/SOURCES/0071-Move-authentication-configuration-cache-into-libotp.patch b/SOURCES/0071-Move-authentication-configuration-cache-into-libotp.patch
new file mode 100644
index 0000000..0372953
--- /dev/null
+++ b/SOURCES/0071-Move-authentication-configuration-cache-into-libotp.patch
@@ -0,0 +1,1207 @@
+From d19a011c84949c323194fe389f1e84d0dcc61c70 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Mon, 10 Nov 2014 22:46:44 -0500
+Subject: [PATCH] Move authentication configuration cache into libotp
+
+This enables plugins to share authentication configuration cache code.
+
+Additionally, update the caching mechanism to be declarative and faster.
+
+Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
+---
+ .../ipa-slapi-plugins/ipa-pwd-extop/Makefile.am    |   1 -
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.c  | 280 ---------------------
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.h  |  82 ------
+ .../ipa-pwd-extop/ipa_pwd_extop.c                  |  21 +-
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c  |  50 ++--
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c  |   4 +-
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.h  |   4 +-
+ daemons/ipa-slapi-plugins/libotp/Makefile.am       |   2 +-
+ daemons/ipa-slapi-plugins/libotp/otp_config.c      | 274 ++++++++++++++++++++
+ daemons/ipa-slapi-plugins/libotp/otp_config.h      |  65 +++++
+ daemons/ipa-slapi-plugins/libotp/otp_token.c       |  58 ++---
+ daemons/ipa-slapi-plugins/libotp/otp_token.h       |  11 +-
+ 12 files changed, 395 insertions(+), 457 deletions(-)
+ delete mode 100644 daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.c
+ delete mode 100644 daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.h
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/otp_config.c
+ create mode 100644 daemons/ipa-slapi-plugins/libotp/otp_config.h
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+index eeb352611e5b67a2f6803b59414fb31c37f39f33..1ab6c6704e401810772a5ababc7cc5eec19d2c83 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+@@ -44,7 +44,6 @@ libipa_pwd_extop_la_LIBADD  = \
+ 	$(ASN1_UTIL_DIR)/libipaasn1.la  \
+ 	$(NULL)
+ libipa_pwd_extop_la_SOURCES = 		\
+-	authcfg.c			\
+ 	common.c			\
+ 	encoding.c			\
+ 	prepost.c			\
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.c
+deleted file mode 100644
+index 3ab5668edd7edcb9eaf247c18b964f6584c9d439..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.c
++++ /dev/null
+@@ -1,280 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2014 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-#include "authcfg.h"
+-#include "ipapwd.h"
+-
+-#include "pratom.h"
+-
+-static struct config {
+-    struct config *next;
+-    Slapi_DN *suffix;
+-    uint32_t config;
+-} *config;
+-
+-static uint32_t string_to_config(const char *str)
+-{
+-    static const struct {
+-        const char *string;
+-        uint32_t config;
+-    } map[] = {
+-        { "disabled", AUTHCFG_AUTH_TYPE_DISABLED },
+-        { "password", AUTHCFG_AUTH_TYPE_PASSWORD },
+-        { "otp",      AUTHCFG_AUTH_TYPE_OTP },
+-        { "pkinit",   AUTHCFG_AUTH_TYPE_PKINIT },
+-        { "radius",   AUTHCFG_AUTH_TYPE_RADIUS },
+-        {}
+-    };
+-
+-    for (uint32_t i = 0; map[i].string != NULL; i++) {
+-        if (strcasecmp(map[i].string, str) == 0)
+-            return map[i].config;
+-    }
+-
+-    return AUTHCFG_AUTH_TYPE_NONE;
+-}
+-
+-static uint32_t entry_to_config(Slapi_Entry *e)
+-{
+-    char **auth_types = NULL;
+-
+-    if (e == NULL)
+-        return AUTHCFG_AUTH_TYPE_NONE;
+-
+-    /* Fetch the auth type values from the config entry. */
+-    auth_types = slapi_entry_attr_get_charray(e, "ipaUserAuthType");
+-    if (auth_types == NULL)
+-        return AUTHCFG_AUTH_TYPE_NONE;
+-
+-    uint32_t types = AUTHCFG_AUTH_TYPE_NONE;
+-    for (uint32_t i = 0; auth_types[i] != NULL; i++)
+-        types |= string_to_config(auth_types[i]);
+-
+-    slapi_ch_array_free(auth_types);
+-
+-    return types;
+-}
+-
+-static Slapi_DN *suffix_to_config_dn(Slapi_DN *suffix)
+-{
+-    Slapi_DN *sdn = NULL;
+-    char *dn = NULL;
+-
+-    if (suffix == NULL)
+-        return NULL;
+-
+-    dn = PR_smprintf("cn=ipaConfig,cn=etc,%s", slapi_sdn_get_dn(suffix));
+-    if (dn == NULL)
+-        return NULL;
+-
+-    sdn = slapi_sdn_new_dn_byval(dn);
+-    PR_smprintf_free(dn);
+-    return sdn;
+-}
+-
+-static uint32_t suffix_to_config(Slapi_DN *suffix)
+-{
+-    static char *attrs[] = { "ipaUserAuthType", NULL };
+-    Slapi_Entry *entry = NULL;
+-    Slapi_DN *sdn = NULL;
+-    uint32_t types;
+-    int ret;
+-
+-    sdn = suffix_to_config_dn(suffix);
+-    if (sdn == NULL)
+-        return AUTHCFG_AUTH_TYPE_NONE;
+-
+-    ret = slapi_search_internal_get_entry(sdn, attrs, &entry,
+-                                          ipapwd_get_plugin_id());
+-    slapi_sdn_free(&sdn);
+-    if (ret != LDAP_SUCCESS)
+-        return AUTHCFG_AUTH_TYPE_NONE;
+-
+-    types = entry_to_config(entry);
+-    slapi_entry_free(entry);
+-
+-    return types;
+-}
+-
+-static Slapi_DN *sdn_to_suffix(Slapi_DN *sdn)
+-{
+-    Slapi_DN *suffix = NULL;
+-    void *node = NULL;
+-
+-    if (sdn == NULL)
+-        return NULL;
+-
+-    for (suffix = slapi_get_first_suffix(&node, 0); suffix != NULL;
+-         suffix = slapi_get_next_suffix(&node, 0)) {
+-        if (slapi_sdn_issuffix(sdn, suffix))
+-            return suffix;
+-    }
+-
+-    return NULL;
+-}
+-
+-static bool sdn_is_config(Slapi_DN *sdn)
+-{
+-    Slapi_DN *sfx = NULL;
+-    Slapi_DN *cfg = NULL;
+-    int cmp;
+-
+-    if (sdn == NULL)
+-        return false;
+-
+-    sfx = sdn_to_suffix(sdn);
+-    if (sfx == NULL)
+-        return false;
+-
+-    cfg = suffix_to_config_dn(sfx);
+-    if (cfg == NULL)
+-        return false;
+-
+-    cmp = slapi_sdn_compare(cfg, sdn);
+-    slapi_sdn_free(&cfg);
+-    return cmp == 0;
+-}
+-
+-void cache_free(struct config **cfg)
+-{
+-    if (cfg == NULL || *cfg == NULL)
+-        return;
+-
+-    cache_free(&(*cfg)->next);
+-    free(*cfg);
+-    *cfg = NULL;
+-}
+-
+-bool authcfg_init(void)
+-{
+-    struct config *cfg = NULL;
+-    Slapi_DN *sfx = NULL;
+-    void *node = NULL;
+-
+-    /* If we are already initialized, return true. */
+-    if (config != NULL)
+-        return true;
+-
+-    /* Look up the config for each suffix. */
+-    for (sfx = slapi_get_first_suffix(&node, 0); sfx != NULL;
+-         sfx = slapi_get_next_suffix(&node, 0)) {
+-        cfg = calloc(1, sizeof(*cfg));
+-        if (cfg == NULL) {
+-            authcfg_fini();
+-            return false;
+-        }
+-
+-        cfg->suffix = sfx;
+-        cfg->config = suffix_to_config(sfx);
+-        cfg->next = config;
+-        config = cfg;
+-    }
+-
+-    return true;
+-}
+-
+-void authcfg_fini(void)
+-{
+-    cache_free(&config);
+-}
+-
+-uint32_t authcfg_get_auth_types(Slapi_Entry *user_entry)
+-{
+-    uint32_t glbl = AUTHCFG_AUTH_TYPE_NONE;
+-    uint32_t user = AUTHCFG_AUTH_TYPE_NONE;
+-    Slapi_DN *sfx = NULL;
+-    Slapi_DN *sdn = NULL;
+-
+-    /* Find the root suffix. */
+-    sdn = slapi_entry_get_sdn(user_entry);
+-    sfx = sdn_to_suffix(sdn);
+-
+-    /* Find the global config. */
+-    if (sfx != NULL) {
+-        for (struct config *cfg = config; cfg && sfx; cfg = cfg->next) {
+-            if (slapi_sdn_compare(sfx, cfg->suffix) == 0) {
+-                glbl = PR_ATOMIC_ADD(&cfg->config, 0);
+-                break;
+-            }
+-        }
+-    }
+-
+-    /* Global disabled overrides user settings. */
+-    if (glbl & AUTHCFG_AUTH_TYPE_DISABLED)
+-        return AUTHCFG_AUTH_TYPE_DISABLED;
+-
+-    /* Get the user's config. */
+-    user = entry_to_config(user_entry);
+-
+-    if (user == AUTHCFG_AUTH_TYPE_NONE) {
+-        if (glbl == AUTHCFG_AUTH_TYPE_NONE)
+-            return AUTHCFG_AUTH_TYPE_PASSWORD;
+-        return glbl;
+-    }
+-
+-    return user & ~AUTHCFG_AUTH_TYPE_DISABLED;
+-}
+-
+-void authcfg_reload_global_config(Slapi_DN *sdn, Slapi_Entry *config_entry)
+-{
+-    uint32_t glbl = AUTHCFG_AUTH_TYPE_NONE;
+-    Slapi_DN *sfx = NULL;
+-    Slapi_DN *dest;
+-
+-    /* Get the destination DN. */
+-    dest = config_entry == NULL ? NULL : slapi_entry_get_sdn(config_entry);
+-
+-    /* Added, modified, moved into place. */
+-    if (sdn_is_config(dest)) {
+-        sfx = sdn_to_suffix(dest);
+-        glbl = entry_to_config(config_entry);
+-
+-    /* Deleted, moved out of place. */
+-    } else if (sdn_is_config(sdn)) {
+-        sfx = sdn_to_suffix(sdn);
+-    }
+-
+-    /* Reload config. */
+-    for (struct config *cfg = config; cfg && sfx; cfg = cfg->next) {
+-        if (slapi_sdn_compare(sfx, cfg->suffix) == 0) {
+-            PR_ATOMIC_SET(&cfg->config, glbl);
+-            break;
+-        }
+-    }
+-}
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.h
+deleted file mode 100644
+index c2fc24605c0f915261a57967c43c35ab6e773263..0000000000000000000000000000000000000000
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/authcfg.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/** BEGIN COPYRIGHT BLOCK
+- * 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/>.
+- *
+- * Additional permission under GPLv3 section 7:
+- *
+- * In the following paragraph, "GPL" means the GNU General Public
+- * License, version 3 or any later version, and "Non-GPL Code" means
+- * code that is governed neither by the GPL nor a license
+- * compatible with the GPL.
+- *
+- * You may link the code of this Program with Non-GPL Code and convey
+- * linked combinations including the two, provided that such Non-GPL
+- * Code only links to the code of this Program through those well
+- * defined interfaces identified in the file named EXCEPTION found in
+- * the source code files (the "Approved Interfaces"). The files of
+- * Non-GPL Code may instantiate templates or use macros or inline
+- * functions from the Approved Interfaces without causing the resulting
+- * work to be covered by the GPL. Only the copyright holders of this
+- * Program may make changes or additions to the list of Approved
+- * Interfaces.
+- *
+- * Authors:
+- * Nathaniel McCallum <npmccallum@redhat.com>
+- *
+- * Copyright (C) 2014 Red Hat, Inc.
+- * All rights reserved.
+- * END COPYRIGHT BLOCK **/
+-
+-
+-#ifndef AUTHCFG_H_
+-#define AUTHCFG_H_
+-
+-#include <dirsrv/slapi-plugin.h>
+-#include <stdbool.h>
+-
+-#define AUTHCFG_AUTH_TYPE_NONE     0
+-#define AUTHCFG_AUTH_TYPE_DISABLED 1
+-#define AUTHCFG_AUTH_TYPE_PASSWORD 2
+-#define AUTHCFG_AUTH_TYPE_OTP      4
+-#define AUTHCFG_AUTH_TYPE_PKINIT   8
+-#define AUTHCFG_AUTH_TYPE_RADIUS   16
+-
+-/* Initialize authentication configuration.
+- *
+- * Thread Safety: NO
+- */
+-bool authcfg_init(void);
+-
+-/* Free global authentication configuration resources.
+- *
+- * Thread Safety: NO
+- */
+-void authcfg_fini(void);
+-
+-/* Gets the permitted authentication types for the given user entry.
+- *
+- * The entry should be queried for the "ipaUserAuthType" attribute.
+- *
+- * Thread Safety: YES
+- */
+-uint32_t authcfg_get_auth_types(Slapi_Entry *user_entry);
+-
+-/* Reloads configuration from the specified global config entry.
+- *
+- * If the provided entry isn't a global config entry, this is a no-op.
+- *
+- * Thread Safety: YES
+- */
+-void authcfg_reload_global_config(Slapi_DN *sdn, Slapi_Entry *config_entry);
+-
+-#endif /* AUTHCFG_H_ */
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+index ceea49cab50b0836c882240f210339e60d26729b..09c877f7010d3cc252c9f38e827cd33b63dea3b6 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+@@ -39,7 +39,7 @@
+ 
+ #include "ipapwd.h"
+ #include "util.h"
+-#include "authcfg.h"
++#include "../libotp/otp_config.h"
+ #include "ipa_asn1.h"
+ 
+ /*
+@@ -89,6 +89,8 @@ Slapi_PluginDesc ipapwd_plugin_desc = {
+ void *ipapwd_plugin_id;
+ static int usetxn = 0;
+ 
++extern struct otp_config *otp_config;
++
+ void *ipapwd_get_plugin_id(void)
+ {
+     return ipapwd_plugin_id;
+@@ -1792,16 +1794,6 @@ static int ipapwd_start( Slapi_PBlock *pb )
+     Slapi_Entry *config_entry = NULL;
+     int ret;
+ 
+-    /* NOTE: We never call authcfg_fini() from a destructor. This is because
+-     *       it may race with threaded requests at shutdown. This leak should
+-     *       only occur when the DS is exiting, so it isn't a big deal.
+-     */
+-    if (!authcfg_init()) {
+-        LOG_FATAL("AuthConf initialization failed!\n");
+-        ret = LDAP_OPERATIONS_ERROR;
+-        goto done;
+-    }
+-
+     krberr = krb5_init_context(&krbctx);
+     if (krberr) {
+         LOG_FATAL("krb5_init_context failed\n");
+@@ -1871,11 +1863,16 @@ static int ipapwd_start( Slapi_PBlock *pb )
+ 
+     ret = LDAP_SUCCESS;
+ 
++    /* NOTE: We never call otp_config_fini() from a destructor. This is because
++     *       it may race with threaded requests at shutdown. This leak should
++     *       only occur when the DS is exiting, so it isn't a big deal.
++     */
++    otp_config = otp_config_init(ipapwd_plugin_id);
++
+ done:
+     free(realm);
+     krb5_free_context(krbctx);
+     if (config_entry) slapi_entry_free(config_entry);
+-    if (ret != LDAP_SUCCESS) authcfg_fini();
+     return ret;
+ }
+ 
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+index 1dff6db1a8cfcc295ba43d1c29d8887e3cf37fec..96c55f39ba2a9dc1e9fc80d5f7d46787803ece47 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+@@ -63,7 +63,6 @@
+ #include "ipapwd.h"
+ #include "util.h"
+ #include "syncreq.h"
+-#include "authcfg.h"
+ 
+ #define IPAPWD_OP_NULL 0
+ #define IPAPWD_OP_ADD 1
+@@ -75,6 +74,8 @@ extern Slapi_PluginDesc ipapwd_plugin_desc;
+ extern void *ipapwd_plugin_id;
+ extern const char *ipa_realm_tree;
+ 
++struct otp_config *otp_config = NULL;
++
+ /* structure with information for each extension */
+ struct ipapwd_op_ext {
+     char *object_name;   /* name of the object extended   */
+@@ -967,23 +968,9 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
+     return ret;
+ }
+ 
+-static int ipapwd_post_authcfg(Slapi_PBlock *pb)
++static int ipapwd_post_updatecfg(Slapi_PBlock *pb)
+ {
+-    Slapi_Entry *config_entry = NULL;
+-    Slapi_DN *sdn = NULL;
+-    int oprc = 0;
+-
+-    /* Just bail if the operation failed. */
+-    if (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0 || oprc != 0)
+-        return 0;
+-
+-    if (slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn) != 0)
+-        return 0;
+-
+-    /* Ignore the error here (delete operations). */
+-    slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &config_entry);
+-
+-    authcfg_reload_global_config(sdn, config_entry);
++    otp_config_update(otp_config, pb);
+     return 0;
+ }
+ 
+@@ -1003,8 +990,7 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
+ 
+     LOG_TRACE("=>\n");
+ 
+-    /* Ignore error when parsing configuration. */
+-    ipapwd_post_authcfg(pb);
++    otp_config_update(otp_config, pb);
+ 
+     /* time to get the operation handler */
+     ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+@@ -1144,7 +1130,7 @@ static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
+     bool success = false;
+ 
+     /* Find all of the user's active tokens. */
+-    tokens = otp_token_find(ipapwd_plugin_id, dn, NULL, true, NULL);
++    tokens = otp_token_find(otp_config, dn, NULL, true, NULL);
+     if (tokens == NULL) {
+         slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
+                         "%s: can't find tokens for '%s'.\n", __func__, dn);
+@@ -1190,11 +1176,7 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
+     uint32_t auth_types;
+ 
+     /* Get the configured authentication types. */
+-    auth_types = authcfg_get_auth_types(entry);
+-
+-    /* If global disabled flag is set, just punt. */
+-    if (auth_types & AUTHCFG_AUTH_TYPE_DISABLED)
+-        return true;
++    auth_types = otp_config_auth_types(otp_config, entry);
+ 
+     /*
+      * IMPORTANT SECTION!
+@@ -1206,14 +1188,14 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
+      * 2. If PWD is enabled or OTP succeeded, fall through to PWD validation.
+      */
+ 
+-    if (auth_types & AUTHCFG_AUTH_TYPE_OTP) {
++    if (auth_types & OTP_CONFIG_AUTH_TYPE_OTP) {
+         LOG_PLUGIN_NAME(IPAPWD_PLUGIN_NAME,
+                         "Attempting OTP authentication for '%s'.\n", bind_dn);
+         if (ipapwd_do_otp_auth(bind_dn, entry, creds))
+             return true;
+     }
+ 
+-    return auth_types & AUTHCFG_AUTH_TYPE_PASSWORD;
++    return auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD;
+ }
+ 
+ static int ipapwd_authenticate(const char *dn, Slapi_Entry *entry,
+@@ -1461,7 +1443,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
+     }
+ 
+     /* Attempt to handle a token synchronization request. */
+-    if (syncreq && !sync_request_handle(ipapwd_get_plugin_id(), pb, dn))
++    if (syncreq && !sync_request_handle(otp_config, pb, dn))
+         goto invalid_creds;
+ 
+     /* Attempt to write out kerberos keys for the user. */
+@@ -1513,9 +1495,9 @@ int ipapwd_post_init(Slapi_PBlock *pb)
+     ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
+     if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
+     if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *)ipapwd_post_modadd);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)ipapwd_post_authcfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)ipapwd_post_updatecfg);
+     if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *)ipapwd_post_modadd);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *)ipapwd_post_authcfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *)ipapwd_post_updatecfg);
+ 
+     return ret;
+ }
+@@ -1526,10 +1508,10 @@ int ipapwd_intpost_init(Slapi_PBlock *pb)
+ 
+     ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
+     if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *)ipapwd_post_authcfg);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *)ipapwd_post_authcfg);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *)ipapwd_post_authcfg);
+-    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *)ipapwd_post_authcfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *)ipapwd_post_updatecfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *)ipapwd_post_updatecfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *)ipapwd_post_updatecfg);
++    if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *)ipapwd_post_updatecfg);
+     return ret;
+ }
+ 
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+index 10c49b724ee276d2b1fb89891a6eb4ee8eaa8fab..0aef438023e7f23d7219273e9f5efd5572e73c3f 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+@@ -52,7 +52,7 @@ bool sync_request_present(Slapi_PBlock *pb)
+     return ldap_control_find(OTP_SYNC_REQUEST_OID, controls, NULL) != NULL;
+ }
+ 
+-bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
++bool sync_request_handle(const struct otp_config *cfg, Slapi_PBlock *pb,
+                          const char *user_dn)
+ {
+     struct otp_token **tokens = NULL;
+@@ -90,7 +90,7 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
+         /* Process the synchronization. */
+         success = false;
+         if (ber_scanf(ber, "}") != LBER_ERROR) {
+-            tokens = otp_token_find(plugin_id, user_dn, token_dn, true, NULL);
++            tokens = otp_token_find(cfg, user_dn, token_dn, true, NULL);
+             if (tokens != NULL) {
+                 success = otp_token_sync_berval(tokens, OTP_SYNC_MAX_STEPS, first, second);
+                 otp_token_free_array(tokens);
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.h
+index 34235901b7b2e49cc6e79423a92e0e4930c0b8cb..98a97c4c9f6d2e6bf74f97fc93053b3aebbc7821 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.h
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.h
+@@ -41,7 +41,7 @@
+ #ifndef SYNCREQ_H_
+ #define SYNCREQ_H_
+ 
+-#include <dirsrv/slapi-plugin.h>
++#include "../libotp/otp_config.h"
+ #include <stdbool.h>
+ 
+ /*
+@@ -57,7 +57,7 @@
+ 
+ bool sync_request_present(Slapi_PBlock *pb);
+ 
+-bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
++bool sync_request_handle(const struct otp_config *cfg, Slapi_PBlock *pb,
+                          const char *user_dn);
+ 
+ #endif /* SYNCREQ_H_ */
+diff --git a/daemons/ipa-slapi-plugins/libotp/Makefile.am b/daemons/ipa-slapi-plugins/libotp/Makefile.am
+index 012c8339199af5f63e6434b94109af2d93a38b45..4428f6bdc38a4e4ec224d1fa70744d8381f7e0b1 100644
+--- a/daemons/ipa-slapi-plugins/libotp/Makefile.am
++++ b/daemons/ipa-slapi-plugins/libotp/Makefile.am
+@@ -3,7 +3,7 @@ AM_CPPFLAGS = -I/usr/include/dirsrv
+ 
+ noinst_LTLIBRARIES = libhotp.la libotp.la
+ libhotp_la_SOURCES = hotp.c hotp.h
+-libotp_la_SOURCES = otp_token.c otp_token.h
++libotp_la_SOURCES = otp_config.c otp_config.h otp_token.c otp_token.h
+ libotp_la_LIBADD = libhotp.la
+ 
+ check_PROGRAMS = t_hotp
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_config.c b/daemons/ipa-slapi-plugins/libotp/otp_config.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..1b7c1e658f126e3d1e8eabd129bb69dc5c4ce970
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/otp_config.c
+@@ -0,0 +1,274 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#include "otp_config.h"
++
++#include <pratom.h>
++#include <plstr.h>
++
++#define OTP_CONFIG_AUTH_TYPE_DISABLED (1 << 31)
++
++struct spec {
++    uint32_t (*func)(Slapi_Entry *, const char *attr);
++    const char *prefix;
++    const char *attr;
++    uint32_t dflt;
++};
++
++struct record {
++    struct record *next;
++    const struct spec *spec;
++    Slapi_DN *sdn;
++    uint32_t value;
++};
++
++struct otp_config {
++    Slapi_ComponentId *plugin_id;
++    struct record *records;
++};
++
++static uint32_t string_to_types(const char *str)
++{
++    static const struct {
++        const char *string;
++        uint32_t config;
++    } map[] = {
++        { "disabled", OTP_CONFIG_AUTH_TYPE_DISABLED },
++        { "password", OTP_CONFIG_AUTH_TYPE_PASSWORD },
++        { "otp",      OTP_CONFIG_AUTH_TYPE_OTP },
++        { "pkinit",   OTP_CONFIG_AUTH_TYPE_PKINIT },
++        { "radius",   OTP_CONFIG_AUTH_TYPE_RADIUS },
++        {}
++    };
++
++    for (uint32_t i = 0; map[i].string != NULL; i++) {
++        if (strcasecmp(map[i].string, str) == 0)
++            return map[i].config;
++    }
++
++    return OTP_CONFIG_AUTH_TYPE_NONE;
++}
++
++static uint32_t entry_to_authtypes(Slapi_Entry *e, const char *attr)
++{
++    char **auth_types = NULL;
++
++    if (e == NULL)
++        return OTP_CONFIG_AUTH_TYPE_NONE;
++
++    /* Fetch the auth type values from the config entry. */
++    auth_types = slapi_entry_attr_get_charray(e, attr);
++    if (auth_types == NULL)
++        return OTP_CONFIG_AUTH_TYPE_NONE;
++
++    uint32_t types = OTP_CONFIG_AUTH_TYPE_NONE;
++    for (uint32_t i = 0; auth_types[i] != NULL; i++)
++        types |= string_to_types(auth_types[i]);
++
++    slapi_ch_array_free(auth_types);
++    return types;
++}
++
++static const struct spec authtypes = {
++    entry_to_authtypes,
++    "cn=ipaConfig,cn=etc,%s",
++    "ipaUserAuthType",
++    OTP_CONFIG_AUTH_TYPE_PASSWORD
++};
++
++static Slapi_DN *make_sdn(const char *prefix, const Slapi_DN *suffix)
++{
++    char *dn = slapi_ch_smprintf(prefix, slapi_sdn_get_dn(suffix));
++    return slapi_sdn_new_dn_passin(dn);
++}
++
++static uint32_t find_value(const struct otp_config *cfg,
++                           const Slapi_DN *suffix, const struct spec *spec)
++{
++    uint32_t value = 0;
++    Slapi_DN *sdn;
++
++    sdn = make_sdn(spec->prefix, suffix);
++    for (struct record *rec = cfg->records; rec != NULL; rec = rec->next) {
++        if (rec->spec == spec) {
++            value = PR_ATOMIC_ADD(&rec->value, 0);
++            break;
++        }
++    }
++
++    slapi_sdn_free(&sdn);
++    return value;
++}
++
++static void update(const struct otp_config *cfg, Slapi_DN *src,
++                   Slapi_Entry *entry)
++{
++    Slapi_DN *dst = entry == NULL ? NULL : slapi_entry_get_sdn(entry);
++
++    for (struct record *rec = cfg->records; rec != NULL; rec = rec->next) {
++        uint32_t val = rec->spec->dflt;
++
++        /* If added, modified or moved into place... */
++        if (dst != NULL && slapi_sdn_compare(rec->sdn, dst) == 0) {
++            Slapi_Attr *attr = NULL;
++            if (slapi_entry_attr_find(entry, rec->spec->attr, &attr) == 0)
++                val = rec->spec->func(entry, rec->spec->attr);
++
++        /* If NOT deleted or moved out of place... */
++        } else if (slapi_sdn_compare(rec->sdn, src) != 0)
++            continue;
++
++        PR_ATOMIC_SET(&rec->value, val);
++    }
++}
++
++struct otp_config *otp_config_init(Slapi_ComponentId *plugin_id)
++{
++    static const struct spec *specs[] = {
++        &authtypes,
++        NULL
++    };
++
++    struct otp_config *cfg = NULL;
++    void *node = NULL;
++
++    cfg = (typeof(cfg)) slapi_ch_calloc(1, sizeof(*cfg));
++    cfg->plugin_id = plugin_id;
++
++    /* Build the config table. */
++    for (Slapi_DN *sfx = slapi_get_first_suffix(&node, 0);
++         sfx != NULL;
++         sfx = slapi_get_next_suffix(&node, 0)) {
++        for (size_t i = 0; specs[i] != NULL; i++) {
++            Slapi_Entry *entry = NULL;
++            struct record *rec;
++
++            /* Create the config entry. */
++            rec = (typeof(rec)) slapi_ch_calloc(1, sizeof(*rec));
++            rec->spec = specs[i];
++            rec->sdn = make_sdn(rec->spec->prefix, sfx);
++
++            /* Add config to the list. */
++            rec->next = cfg->records;
++            cfg->records = rec;
++
++            /* Load the specified entry. */
++            slapi_search_internal_get_entry(rec->sdn, NULL, &entry, plugin_id);
++            update(cfg, rec->sdn, entry);
++            slapi_entry_free(entry);
++        }
++    }
++
++    return cfg;
++}
++
++static void record_fini(struct record **rec)
++{
++    if (rec == NULL || *rec == NULL)
++        return;
++
++    record_fini(&(*rec)->next);
++    slapi_sdn_free(&(*rec)->sdn);
++    slapi_ch_free((void **) rec);
++}
++
++void otp_config_fini(struct otp_config **cfg)
++{
++    if (cfg == NULL || *cfg == NULL)
++        return;
++
++    record_fini(&(*cfg)->records);
++    slapi_ch_free((void **) cfg);
++}
++
++void otp_config_update(struct otp_config *cfg, Slapi_PBlock *pb)
++{
++    Slapi_Entry *entry = NULL;
++    Slapi_DN *src = NULL;
++    int oprc = 0;
++
++    /* Just bail if the operation failed. */
++    if (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0 || oprc != 0)
++        return;
++
++    /* Get the source SDN. */
++    if (slapi_pblock_get(pb, SLAPI_TARGET_SDN, &src) != 0)
++        return;
++
++    /* Ignore the error here (delete operations). */
++    (void) slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
++
++    update(cfg, src, entry);
++}
++
++Slapi_ComponentId *otp_config_plugin_id(const struct otp_config *cfg)
++{
++    if (cfg == NULL)
++        return NULL;
++
++    return cfg->plugin_id;
++}
++
++uint32_t otp_config_auth_types(const struct otp_config *cfg,
++                               Slapi_Entry *user_entry)
++{
++    uint32_t glbl = OTP_CONFIG_AUTH_TYPE_NONE;
++    uint32_t user = OTP_CONFIG_AUTH_TYPE_NONE;
++    const Slapi_DN *sfx;
++
++    /* Load the global value. */
++    sfx = slapi_get_suffix_by_dn(slapi_entry_get_sdn(user_entry));
++    glbl = find_value(cfg, sfx, &authtypes);
++
++    /* Load the user value if not disabled. */
++    if ((glbl & OTP_CONFIG_AUTH_TYPE_DISABLED) == 0)
++        user = entry_to_authtypes(user_entry, authtypes.attr);
++
++    /* Filter out the disabled flag. */
++    glbl &= ~OTP_CONFIG_AUTH_TYPE_DISABLED;
++    user &= ~OTP_CONFIG_AUTH_TYPE_DISABLED;
++
++    if (user != OTP_CONFIG_AUTH_TYPE_NONE)
++        return user;
++
++    if (glbl != OTP_CONFIG_AUTH_TYPE_NONE)
++        return glbl;
++
++    return OTP_CONFIG_AUTH_TYPE_PASSWORD;
++}
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_config.h b/daemons/ipa-slapi-plugins/libotp/otp_config.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..bfd514bd542b7d707e9eab4a9cdf31a4f6839ae5
+--- /dev/null
++++ b/daemons/ipa-slapi-plugins/libotp/otp_config.h
+@@ -0,0 +1,65 @@
++/** BEGIN COPYRIGHT BLOCK
++ * 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/>.
++ *
++ * Additional permission under GPLv3 section 7:
++ *
++ * In the following paragraph, "GPL" means the GNU General Public
++ * License, version 3 or any later version, and "Non-GPL Code" means
++ * code that is governed neither by the GPL nor a license
++ * compatible with the GPL.
++ *
++ * You may link the code of this Program with Non-GPL Code and convey
++ * linked combinations including the two, provided that such Non-GPL
++ * Code only links to the code of this Program through those well
++ * defined interfaces identified in the file named EXCEPTION found in
++ * the source code files (the "Approved Interfaces"). The files of
++ * Non-GPL Code may instantiate templates or use macros or inline
++ * functions from the Approved Interfaces without causing the resulting
++ * work to be covered by the GPL. Only the copyright holders of this
++ * Program may make changes or additions to the list of Approved
++ * Interfaces.
++ *
++ * Authors:
++ * Nathaniel McCallum <npmccallum@redhat.com>
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ * All rights reserved.
++ * END COPYRIGHT BLOCK **/
++
++#pragma once
++
++#include <dirsrv/slapi-plugin.h>
++
++#define OTP_CONFIG_AUTH_TYPE_NONE     0
++#define OTP_CONFIG_AUTH_TYPE_PASSWORD (1 << 0)
++#define OTP_CONFIG_AUTH_TYPE_OTP      (1 << 1)
++#define OTP_CONFIG_AUTH_TYPE_PKINIT   (1 << 2)
++#define OTP_CONFIG_AUTH_TYPE_RADIUS   (1 << 3)
++
++struct otp_config;
++
++struct otp_config *otp_config_init(Slapi_ComponentId *plugin_id);
++
++void otp_config_fini(struct otp_config **cfg);
++
++void otp_config_update(struct otp_config *cfg, Slapi_PBlock *pb);
++
++Slapi_ComponentId *otp_config_plugin_id(const struct otp_config *cfg);
++
++/* Gets the permitted authentication types for the given user entry.
++ *
++ * The entry should be queried for the "ipaUserAuthType" attribute.
++ */
++uint32_t otp_config_auth_types(const struct otp_config *cfg,
++                               Slapi_Entry *user_entry);
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c
+index 7860c8aba6e12e319d633ee8e165403289a7528b..eef07268507444897d50509a54f2877866b9c07a 100644
+--- a/daemons/ipa-slapi-plugins/libotp/otp_token.c
++++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c
+@@ -59,7 +59,7 @@ enum type {
+ };
+ 
+ struct otp_token {
+-    Slapi_ComponentId *plugin_id;
++    const struct otp_config *cfg;
+     Slapi_DN *sdn;
+     struct hotp_token token;
+     enum type type;
+@@ -75,21 +75,6 @@ struct otp_token {
+     };
+ };
+ 
+-static const char *get_basedn(Slapi_DN *dn)
+-{
+-    Slapi_DN *suffix = NULL;
+-    void *node = NULL;
+-
+-    for (suffix = slapi_get_first_suffix(&node, 0);
+-         suffix != NULL;
+-         suffix = slapi_get_next_suffix(&node, 0)) {
+-        if (slapi_sdn_issuffix(dn, suffix))
+-            return (char *) slapi_sdn_get_dn(suffix);
+-    }
+-
+-    return NULL;
+-}
+-
+ static inline bool is_algo_valid(const char *algo)
+ {
+     static const char *valid_algos[] = { "sha1", "sha256", "sha384",
+@@ -142,8 +127,8 @@ static bool writeattr(const struct otp_token *token, const char *attr,
+     snprintf(value, sizeof(value), "%lld", val);
+ 
+     pb = slapi_pblock_new();
+-    slapi_modify_internal_set_pb(pb, slapi_sdn_get_dn(token->sdn),
+-                                 mods, NULL, NULL, token->plugin_id, 0);
++    slapi_modify_internal_set_pb(pb, slapi_sdn_get_dn(token->sdn), mods, NULL,
++                                 NULL, otp_config_plugin_id(token->cfg), 0);
+     if (slapi_modify_internal_pb(pb) != 0)
+         goto error;
+     if (slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret) != 0)
+@@ -251,7 +236,7 @@ void otp_token_free_array(struct otp_token **tokens)
+     free(tokens);
+ }
+ 
+-static struct otp_token *otp_token_new(Slapi_ComponentId *id,
++static struct otp_token *otp_token_new(const struct otp_config *cfg,
+                                        Slapi_Entry *entry)
+ {
+     const struct berval *tmp;
+@@ -261,7 +246,7 @@ static struct otp_token *otp_token_new(Slapi_ComponentId *id,
+     token = calloc(1, sizeof(struct otp_token));
+     if (token == NULL)
+         return NULL;
+-    token->plugin_id = id;
++    token->cfg = cfg;
+ 
+     /* Get the token type. */
+     vals = slapi_entry_attr_get_charray(entry, "objectClass");
+@@ -333,16 +318,16 @@ error:
+     return NULL;
+ }
+ 
+-static struct otp_token **find(Slapi_ComponentId *id, const char *user_dn,
++static struct otp_token **find(const struct otp_config *cfg, const char *user_dn,
+                                const char *token_dn, const char *intfilter,
+                                const char *extfilter)
+ {
+     struct otp_token **tokens = NULL;
++    const Slapi_DN *basedn = NULL;
+     Slapi_Entry **entries = NULL;
+     Slapi_PBlock *pb = NULL;
+     Slapi_DN *sdn = NULL;
+     char *filter = NULL;
+-    const char *basedn = NULL;
+     size_t count = 0;
+     int result = -1;
+ 
+@@ -367,20 +352,19 @@ static struct otp_token **find(Slapi_ComponentId *id, const char *user_dn,
+     if (token_dn != NULL) {
+         /* Find only the token specified. */
+         slapi_search_internal_set_pb(pb, token_dn, LDAP_SCOPE_BASE, filter,
+-                                     NULL, 0, NULL, NULL, id, 0);
++                                     NULL, 0, NULL, NULL,
++                                     otp_config_plugin_id(cfg), 0);
+     } else {
+         sdn = slapi_sdn_new_dn_byval(user_dn);
+-        if (sdn == NULL)
+-            goto error;
+-
+-        basedn = get_basedn(sdn);
++        basedn = slapi_get_suffix_by_dn(sdn);
++        slapi_sdn_free(&sdn);
+         if (basedn == NULL)
+             goto error;
+ 
+         /* Find all user tokens. */
+-        slapi_search_internal_set_pb(pb, basedn,
+-                                     LDAP_SCOPE_SUBTREE, filter, NULL,
+-                                     0, NULL, NULL, id, 0);
++        slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(basedn),
++                                     LDAP_SCOPE_SUBTREE, filter, NULL, 0,
++                                     NULL, NULL, otp_config_plugin_id(cfg), 0);
+     }
+     slapi_search_internal_pb(pb);
+     slapi_ch_free_string(&filter);
+@@ -402,7 +386,7 @@ static struct otp_token **find(Slapi_ComponentId *id, const char *user_dn,
+     if (tokens == NULL)
+         goto error;
+     for (count = 0; entries[count] != NULL; count++) {
+-        tokens[count] = otp_token_new(id, entries[count]);
++        tokens[count] = otp_token_new(cfg, entries[count]);
+         if (tokens[count] == NULL) {
+             otp_token_free_array(tokens);
+             tokens = NULL;
+@@ -411,15 +395,13 @@ static struct otp_token **find(Slapi_ComponentId *id, const char *user_dn,
+     }
+ 
+ error:
+-    if (sdn != NULL)
+-        slapi_sdn_free(&sdn);
+     slapi_pblock_destroy(pb);
+     return tokens;
+ }
+ 
+-struct otp_token **
+-otp_token_find(Slapi_ComponentId *id, const char *user_dn, const char *token_dn,
+-               bool active, const char *filter)
++struct otp_token **otp_token_find(const struct otp_config *cfg,
++                                  const char *user_dn, const char *token_dn,
++                                  bool active, const char *filter)
+ {
+     static const char template[] =
+     "(|(ipatokenNotBefore<=%04d%02d%02d%02d%02d%02dZ)(!(ipatokenNotBefore=*)))"
+@@ -430,7 +412,7 @@ otp_token_find(Slapi_ComponentId *id, const char *user_dn, const char *token_dn,
+     time_t now;
+ 
+     if (!active)
+-        return find(id, user_dn, token_dn, NULL, filter);
++        return find(cfg, user_dn, token_dn, NULL, filter);
+ 
+     /* Get the current time. */
+     if (time(&now) == (time_t) -1)
+@@ -446,7 +428,7 @@ otp_token_find(Slapi_ComponentId *id, const char *user_dn, const char *token_dn,
+                  tm.tm_hour, tm.tm_min, tm.tm_sec) < 0)
+         return NULL;
+ 
+-    return find(id, user_dn, token_dn, actfilt, filter);
++    return find(cfg, user_dn, token_dn, actfilt, filter);
+ }
+ 
+ int otp_token_get_digits(struct otp_token *token)
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.h b/daemons/ipa-slapi-plugins/libotp/otp_token.h
+index 2f336780682b5ea2838b558079e2ae85f6e2afba..4b159077d933555d18e804174e29e22f1e8f0110 100644
+--- a/daemons/ipa-slapi-plugins/libotp/otp_token.h
++++ b/daemons/ipa-slapi-plugins/libotp/otp_token.h
+@@ -39,14 +39,15 @@
+ 
+ #pragma once
+ 
+-#include <dirsrv/slapi-plugin.h>
++#include "otp_config.h"
+ #include <stdbool.h>
+ #include <stdlib.h>
+ 
+ struct otp_token;
+ 
+ /* Frees the token array. */
+-void otp_token_free_array(struct otp_token **tokens);
++void
++otp_token_free_array(struct otp_token **tokens);
+ 
+ /* Find tokens.
+  *
+@@ -65,9 +66,9 @@ void otp_token_free_array(struct otp_token **tokens);
+  * Returns NULL on error. If no tokens are found, an empty array is returned.
+  * The array is NULL terminated.
+  */
+-struct otp_token **otp_token_find(Slapi_ComponentId *id, const char *user_dn,
+-                                  const char *token_dn, bool active,
+-                                  const char *filter);
++struct otp_token **otp_token_find(const struct otp_config *cfg,
++                                  const char *user_dn, const char *token_dn,
++                                  bool active, const char *filter);
+ 
+ /* Get the length of the token code. */
+ int otp_token_get_digits(struct otp_token *token);
+-- 
+2.1.0
+
diff --git a/SOURCES/0071-ipaserver-dcerpc.py-Avoid-hitting-issue-with-transit.patch b/SOURCES/0071-ipaserver-dcerpc.py-Avoid-hitting-issue-with-transit.patch
deleted file mode 100644
index 565c6ec..0000000
--- a/SOURCES/0071-ipaserver-dcerpc.py-Avoid-hitting-issue-with-transit.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From ba2a63da8bada8af988d8fb8931c0cdba2c7ceee Mon Sep 17 00:00:00 2001
-From: Alexander Bokovoy <abokovoy@redhat.com>
-Date: Tue, 19 Aug 2014 16:22:54 +0300
-Subject: [PATCH] ipaserver/dcerpc.py: Avoid hitting issue with transitive
- trusts on Windows Server prior to 2012
-
-http://msdn.microsoft.com/en-us/library/2a769a08-e023-459f-aebe-4fb3f595c0b7#id83
-
-Reviewed-By: Sumit Bose <sbose@redhat.com>
----
- ipaserver/dcerpc.py | 13 ++++++++++---
- 1 file changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
-index 41f373df3cc4365727200f3ca4667faac2f9e19c..e779a12bae52ec8dac52e4a43854a8a3c601a043 100644
---- a/ipaserver/dcerpc.py
-+++ b/ipaserver/dcerpc.py
-@@ -900,7 +900,7 @@ class TrustDomainInstance(object):
-         info.sid = security.dom_sid(another_domain.info['sid'])
-         info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND
-         info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
--        info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
-+        info.trust_attributes = 0
- 
-         try:
-             dname = lsa.String()
-@@ -917,8 +917,6 @@ class TrustDomainInstance(object):
-         except RuntimeError, (num, message):
-             raise assess_dcerpc_exception(num=num, message=message)
- 
--        self.update_ftinfo(another_domain)
--
-         # We should use proper trustdom handle in order to modify the
-         # trust settings. Samba insists this has to be done with LSA
-         # OpenTrustedDomain* calls, it is not enough to have a handle
-@@ -937,6 +935,15 @@ class TrustDomainInstance(object):
-             # server as that one doesn't support AES encryption types
-             pass
- 
-+        try:
-+            info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
-+            self._pipe.SetInformationTrustedDomain(trustdom_handle, lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX, info)
-+        except RuntimeError, e:
-+            root_logger.error('unable to set trust to transitive: %s' % (str(e)))
-+            pass
-+        if self.info['is_pdc']:
-+            self.update_ftinfo(another_domain)
-+
-     def verify_trust(self, another_domain):
-         def retrieve_netlogon_info_2(domain, function_code, data):
-             try:
--- 
-1.9.3
-
diff --git a/SOURCES/0072-Enable-last-token-deletion-when-password-auth-type-i.patch b/SOURCES/0072-Enable-last-token-deletion-when-password-auth-type-i.patch
new file mode 100644
index 0000000..ab58dd6
--- /dev/null
+++ b/SOURCES/0072-Enable-last-token-deletion-when-password-auth-type-i.patch
@@ -0,0 +1,327 @@
+From 0aeae1d16bedd0f39f788644167675a99d30c3b2 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Tue, 11 Nov 2014 12:05:23 -0500
+Subject: [PATCH] Enable last token deletion when password auth type is
+ configured
+
+Also, ensure that the last token check only executes on DNs/entries that
+are tokens. This resolves a large performance issue where a query was
+being performed to load all the user's tokens on every del/mod operation.
+
+https://fedorahosted.org/freeipa/ticket/4697
+https://fedorahosted.org/freeipa/ticket/4719
+
+Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
+---
+ .../ipa-otp-lasttoken/ipa_otp_lasttoken.c          | 243 +++++++++++++++------
+ 1 file changed, 173 insertions(+), 70 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+index 19217ba7fbf562231dd74b25cfd13a0f4d930e7c..233813745795344f31a7dcf1931cf74a09f1e552 100644
+--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+@@ -46,112 +46,171 @@
+ 
+ #include "util.h"
+ 
+-#define PLUGIN_NAME               "ipa-otp-lasttoken"
+-
+-static void *plugin_id;
+-static const Slapi_PluginDesc preop_desc = {
+-    PLUGIN_NAME,
+-    "FreeIPA",
+-    "FreeIPA/1.0",
+-    "Protect the user's last active token"
+-};
+-
+-static bool
+-target_is_only_enabled_token(Slapi_PBlock *pb)
++#define PLUGIN_NAME "ipa-otp-lasttoken"
++#define OTP_CONTAINER "cn=otp,%s"
++
++static struct otp_config *otp_config;
++
++static bool entry_is_token(Slapi_Entry *entry)
+ {
+-    Slapi_DN *target_sdn = NULL;
+-    Slapi_DN *token_sdn = NULL;
+-    struct otp_token **tokens;
+-    char *user_dn = NULL;
+-    bool match;
++    char **ocls;
+ 
+-    /* Ignore internal operations. */
+-    if (slapi_op_internal(pb))
++    ocls = slapi_entry_attr_get_charray(entry, SLAPI_ATTR_OBJECTCLASS);
++    for (size_t i = 0; ocls != NULL && ocls[i] != NULL; i++) {
++        if (strcasecmp(ocls[i], "ipaToken") == 0) {
++            slapi_ch_array_free(ocls);
++            return true;
++        }
++    }
++
++    return false;
++}
++
++static bool sdn_in_otp_container(Slapi_DN *sdn)
++{
++    const Slapi_DN *base;
++    Slapi_DN *container;
++    bool result;
++    char *dn;
++
++    base = slapi_get_suffix_by_dn(sdn);
++    if (base == NULL)
+         return false;
+ 
+-    /* Get the current user's SDN. */
+-    slapi_pblock_get(pb, SLAPI_CONN_DN, &user_dn);
+-    if (user_dn == NULL)
++    dn = slapi_ch_smprintf(OTP_CONTAINER, slapi_sdn_get_dn(base));
++    if (dn == NULL)
+         return false;
+ 
+-    /* Get the SDN of the only enabled token. */
+-    tokens = otp_token_find(plugin_id, user_dn, NULL, true, NULL);
+-    if (tokens != NULL && tokens[0] != NULL && tokens[1] == NULL)
+-        token_sdn = slapi_sdn_dup(otp_token_get_sdn(tokens[0]));
++    container = slapi_sdn_new_dn_passin(dn);
++    result = slapi_sdn_issuffix(sdn, container);
++    slapi_sdn_free(&container);
++
++    return result;
++}
++
++static bool sdn_is_only_enabled_token(Slapi_DN *target_sdn, const char *user_dn)
++{
++    struct otp_token **tokens;
++    bool result = false;
++
++    tokens = otp_token_find(otp_config, user_dn, NULL, true, NULL);
++
++    if (tokens != NULL && tokens[0] != NULL && tokens[1] == NULL) {
++        const Slapi_DN *token_sdn = otp_token_get_sdn(tokens[0]);
++        if (token_sdn != NULL)
++            result = slapi_sdn_compare(token_sdn, target_sdn) == 0;
++    }
++
+     otp_token_free_array(tokens);
+-    if (token_sdn == NULL)
++    return result;
++}
++
++static bool is_pwd_enabled(const char *user_dn)
++{
++    char *attrs[] = { "ipaUserAuthType", NULL };
++    Slapi_Entry *entry = NULL;
++    uint32_t authtypes;
++    Slapi_DN *sdn;
++
++    sdn = slapi_sdn_new_dn_byval(user_dn);
++    if (sdn == NULL)
+         return false;
+ 
+-    /* Get the target SDN. */
+-    slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
+-    if (target_sdn == NULL) {
+-        slapi_sdn_free(&token_sdn);
++    slapi_search_internal_get_entry(sdn, attrs, &entry,
++                                    otp_config_plugin_id(otp_config));
++    slapi_sdn_free(&sdn);
++    if (entry == NULL)
++        return false;
++
++    authtypes = otp_config_auth_types(otp_config, entry);
++    slapi_entry_free(entry);
++
++    return authtypes & OTP_CONFIG_AUTH_TYPE_PASSWORD;
++}
++
++static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
++{
++    Slapi_DN *target_sdn = NULL;
++    const char *bind_dn;
++
++    /* Ignore internal operations. */
++    if (slapi_op_internal(pb))
++        return true;
++
++    /* Load parameters. */
++    (void) slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
++    (void) slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
++    if (target_sdn == NULL || bind_dn == NULL) {
++        LOG_FATAL("Missing parameters!\n");
+         return false;
+     }
+ 
+-    /* Does the target SDN match the only enabled token SDN? */
+-    match = slapi_sdn_compare(token_sdn, target_sdn) == 0;
+-    slapi_sdn_free(&token_sdn);
+-    return match;
++    if (entry != NULL
++            ? !entry_is_token(entry)
++            : !sdn_in_otp_container(target_sdn))
++        return true;
++
++    if (!sdn_is_only_enabled_token(target_sdn, bind_dn))
++        return true;
++
++    if (is_pwd_enabled(bind_dn))
++        return true;
++
++    return false;
+ }
+ 
+-static inline int
+-send_error(Slapi_PBlock *pb, int rc, char *errstr)
++static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr)
+ {
+-    slapi_send_ldap_result(pb, rc, NULL, errstr, 0, NULL);
++    slapi_send_ldap_result(pb, rc, NULL, (char *) errstr, 0, NULL);
+     if (slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc)) {
+         LOG_FATAL("slapi_pblock_set failed!\n");
+     }
+     return rc;
+ }
+ 
+-static int
+-preop_del(Slapi_PBlock *pb)
++static int preop_del(Slapi_PBlock *pb)
+ {
+-    if (!target_is_only_enabled_token(pb))
++    if (is_allowed(pb, NULL))
+         return 0;
+ 
+     return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
+                       "Can't delete last active token");
+ }
+ 
+-static int
+-preop_mod(Slapi_PBlock *pb)
++static int preop_mod(Slapi_PBlock *pb)
+ {
+-    LDAPMod **mods = NULL;
++    static const struct {
++        const char *attr;
++        const char *msg;
++    } errors[] = {
++        {"ipatokenDisabled",  "Can't disable last active token"},
++        {"ipatokenOwner",     "Can't change last active token's owner"},
++        {"ipatokenNotBefore", "Can't change last active token's start time"},
++        {"ipatokenNotAfter",  "Can't change last active token's end time"},
++        {}
++    };
+ 
+-    if (!target_is_only_enabled_token(pb))
+-        return 0;
++    const LDAPMod **mods = NULL;
++    Slapi_Entry *entry = NULL;
+ 
+-    /* Do not permit deactivation of the last active token. */
+-    slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
+-    for (int i = 0; mods != NULL && mods[i] != NULL; i++) {
+-        if (strcasecmp(mods[i]->mod_type, "ipatokenDisabled") == 0) {
+-            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
+-                              "Can't disable last active token");
+-        }
++    (void) slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &entry);
++    (void) slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
+ 
+-        if (strcasecmp(mods[i]->mod_type, "ipatokenOwner") == 0) {
+-            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
+-                              "Can't change last active token's owner");
+-        }
+-
+-        if (strcasecmp(mods[i]->mod_type, "ipatokenNotBefore") == 0) {
+-            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
+-                              "Can't change last active token's start time");
+-        }
++    if (is_allowed(pb, entry))
++        return 0;
+ 
+-        if (strcasecmp(mods[i]->mod_type, "ipatokenNotAfter") == 0) {
+-            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
+-                              "Can't change last active token's end time");
++    /* If a protected attribute is modified, deny. */
++    for (int i = 0; mods != NULL && mods[i] != NULL; i++) {
++        for (int j = 0; errors[j].attr != NULL; j++) {
++            if (strcasecmp(mods[i]->mod_type, errors[j].attr) == 0)
++                return send_error(pb, LDAP_UNWILLING_TO_PERFORM, errors[j].msg);
+         }
+     }
+ 
+     return 0;
+ }
+ 
+-static int
+-preop_init(Slapi_PBlock *pb)
++static int preop_init(Slapi_PBlock *pb)
+ {
+     int ret = 0;
+ 
+@@ -160,15 +219,59 @@ preop_init(Slapi_PBlock *pb)
+     return ret;
+ }
+ 
+-int
+-ipa_otp_lasttoken_init(Slapi_PBlock *pb)
++static int update_config(Slapi_PBlock *pb)
++{
++    otp_config_update(otp_config, pb);
++    return 0;
++}
++
++static int intpostop_init(Slapi_PBlock *pb)
++{
++    int ret = 0;
++
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN,    (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *) update_config);
++
++    return ret;
++}
++
++static int postop_init(Slapi_PBlock *pb)
+ {
+     int ret = 0;
+ 
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,    (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *) update_config);
++    ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *) update_config);
++
++    return ret;
++}
++
++int ipa_otp_lasttoken_init(Slapi_PBlock *pb)
++{
++    static const Slapi_PluginDesc preop_desc = {
++        PLUGIN_NAME,
++        "FreeIPA",
++        "FreeIPA/1.0",
++        "Protect the user's last active token"
++    };
++
++    Slapi_ComponentId *plugin_id = NULL;
++    int ret = 0;
++
+     ret |= slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_id);
+     ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
+     ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &preop_desc);
+     ret |= slapi_register_plugin("betxnpreoperation", 1, __func__, preop_init,
+-                                 PLUGIN_NAME, NULL, plugin_id);
++                                 PLUGIN_NAME " betxnpreoperation", NULL, plugin_id);
++    ret |= slapi_register_plugin("postoperation", 1, __func__, postop_init,
++                                 PLUGIN_NAME " postoperation", NULL, plugin_id);
++    ret |= slapi_register_plugin("internalpostoperation", 1, __func__, intpostop_init,
++                                 PLUGIN_NAME " internalpostoperation", NULL, plugin_id);
++
++    /* NOTE: leak otp_config on process exit. */
++    otp_config = otp_config_init(plugin_id);
+     return ret;
+ }
+-- 
+2.1.0
+
diff --git a/SOURCES/0073-add-hosts-and-hostgroup-options-to-allow-retrieve-ke.patch b/SOURCES/0073-add-hosts-and-hostgroup-options-to-allow-retrieve-ke.patch
new file mode 100644
index 0000000..0e544cf
--- /dev/null
+++ b/SOURCES/0073-add-hosts-and-hostgroup-options-to-allow-retrieve-ke.patch
@@ -0,0 +1,878 @@
+From 1d57cf654de99077d7ece28f9210d1a2d5dee5b7 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 1 Dec 2014 10:15:21 +0100
+Subject: [PATCH] add --hosts and --hostgroup options to allow/retrieve keytab
+ methods
+
+`--hosts` and `--hostgroup` options added to:
+* service-allow-create-keytab
+* service-allow-retrieve-keytab
+* service-disallow-create-keytab
+* service-disallow-retrieve-keytab
+* host-allow-create-keytab
+* host-allow-retrieve-keytab
+* host-disallow-create-keytab
+* host-disallow-retrieve-keytab
+
+in order to allow hosts to retrieve keytab of their services or related hosts as described on http://www.freeipa.org/page/V4/Keytab_Retrieval design page
+
+https://fedorahosted.org/freeipa/ticket/4777
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ API.txt                                     |  32 ++++++--
+ VERSION                                     |   4 +-
+ ipalib/plugins/host.py                      |  28 +++++--
+ ipalib/plugins/service.py                   |  28 +++++--
+ ipatests/test_xmlrpc/test_host_plugin.py    | 109 ++++++++++++++++++++++++++--
+ ipatests/test_xmlrpc/test_service_plugin.py |  92 ++++++++++++++++++++---
+ 6 files changed, 257 insertions(+), 36 deletions(-)
+
+diff --git a/API.txt b/API.txt
+index 2a63f1e2349f0df69433fa7cb742e269cd42d79f..e9768bf1e87d6679c439b98ed696b720937099d2 100644
+--- a/API.txt
++++ b/API.txt
+@@ -1826,10 +1826,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: host_allow_create_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -1838,10 +1840,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: host_allow_retrieve_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -1866,10 +1870,12 @@ output: Output('result', <type 'bool'>, None)
+ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+ output: PrimaryKey('value', None, None)
+ command: host_disallow_create_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -1878,10 +1884,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: host_disallow_retrieve_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -3529,10 +3537,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: service_allow_create_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -3541,10 +3551,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: service_allow_retrieve_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -3568,10 +3580,12 @@ output: Output('result', <type 'bool'>, None)
+ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+ output: PrimaryKey('value', None, None)
+ command: service_disallow_create_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+@@ -3580,10 +3594,12 @@ output: Output('completed', <type 'int'>, None)
+ output: Output('failed', <type 'dict'>, None)
+ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+ command: service_disallow_retrieve_keytab
+-args: 1,6,3
++args: 1,8,3
+ arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
++option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
++option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
+ option: Flag('no_members', autofill=True, default=False, exclude='webui')
+ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+ option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+diff --git a/VERSION b/VERSION
+index 750b5058867ca5f073a083009c4aadeeb0240c35..bfbce5604e79008afd2893e406c634718159b1e9 100644
+--- a/VERSION
++++ b/VERSION
+@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
+ #                                                      #
+ ########################################################
+ IPA_API_VERSION_MAJOR=2
+-IPA_API_VERSION_MINOR=109
+-# Last change: npmccallum - display qrcode by default
++IPA_API_VERSION_MINOR=110
++# Last change: pvoborni - allow to retrieve keytab by hosts
+diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
+index c4d4bdf6473e0f34c8c68754d6c98e93d173d8fa..39a7d3c25b9cb56fca486b2500da5fe7bd4a6fbc 100644
+--- a/ipalib/plugins/host.py
++++ b/ipalib/plugins/host.py
+@@ -211,12 +211,24 @@ host_output_params = (
+     Str('ipaallowedtoperform_read_keys_group',
+         label=_('Groups allowed to retrieve keytab'),
+     ),
++    Str('ipaallowedtoperform_read_keys_host',
++        label=_('Hosts allowed to retrieve keytab'),
++    ),
++    Str('ipaallowedtoperform_read_keys_hostgroup',
++        label=_('Host Groups allowed to retrieve keytab'),
++    ),
+     Str('ipaallowedtoperform_write_keys_user',
+         label=_('Users allowed to create keytab'),
+     ),
+     Str('ipaallowedtoperform_write_keys_group',
+         label=_('Groups allowed to create keytab'),
+     ),
++    Str('ipaallowedtoperform_write_keys_host',
++        label=_('Hosts allowed to create keytab'),
++    ),
++    Str('ipaallowedtoperform_write_keys_hostgroup',
++        label=_('Host Groups allowed to create keytab'),
++    ),
+     Str('ipaallowedtoperform_read_keys',
+         label=_('Failed allowed to retrieve keytab'),
+     ),
+@@ -284,8 +296,8 @@ class host(LDAPObject):
+         'managing': ['host'],
+         'memberofindirect': ['hostgroup', 'netgroup', 'role', 'hbacrule',
+         'sudorule'],
+-        'ipaallowedtoperform_read_keys': ['user', 'group'],
+-        'ipaallowedtoperform_write_keys': ['user', 'group'],
++        'ipaallowedtoperform_read_keys': ['user', 'group', 'host', 'hostgroup'],
++        'ipaallowedtoperform_write_keys': ['user', 'group', 'host', 'hostgroup'],
+     }
+     bindable = True
+     relationships = {
+@@ -1201,7 +1213,8 @@ class host_remove_managedby(LDAPRemoveMember):
+ 
+ @register()
+ class host_allow_retrieve_keytab(LDAPAddMember):
+-    __doc__ = _('Allow users or groups to retrieve a keytab of this host.')
++    __doc__ = _('Allow users, groups, hosts or host groups to retrieve a keytab'
++                ' of this host.')
+     member_attributes = ['ipaallowedtoperform_read_keys']
+     has_output_params = LDAPAddMember.has_output_params + host_output_params
+ 
+@@ -1219,7 +1232,8 @@ class host_allow_retrieve_keytab(LDAPAddMember):
+ 
+ @register()
+ class host_disallow_retrieve_keytab(LDAPRemoveMember):
+-    __doc__ = _('Disallow users or groups to retrieve a keytab of this host.')
++    __doc__ = _('Disallow users, groups, hosts or host groups to retrieve a '
++                'keytab of this host.')
+     member_attributes = ['ipaallowedtoperform_read_keys']
+     has_output_params = LDAPRemoveMember.has_output_params + host_output_params
+ 
+@@ -1236,7 +1250,8 @@ class host_disallow_retrieve_keytab(LDAPRemoveMember):
+ 
+ @register()
+ class host_allow_create_keytab(LDAPAddMember):
+-    __doc__ = _('Allow users or groups to create a keytab of this host.')
++    __doc__ = _('Allow users, groups, hosts or host groups to create a keytab '
++                'of this host.')
+     member_attributes = ['ipaallowedtoperform_write_keys']
+     has_output_params = LDAPAddMember.has_output_params + host_output_params
+ 
+@@ -1254,7 +1269,8 @@ class host_allow_create_keytab(LDAPAddMember):
+ 
+ @register()
+ class host_disallow_create_keytab(LDAPRemoveMember):
+-    __doc__ = _('Disallow users or groups to create a keytab of this host.')
++    __doc__ = _('Disallow users, groups, hosts or host groups to create a '
++                'keytab of this host.')
+     member_attributes = ['ipaallowedtoperform_write_keys']
+     has_output_params = LDAPRemoveMember.has_output_params + host_output_params
+ 
+diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
+index 2f703544452c6d7ee2de8eceeb5f2a26afed44f2..b37dc7b4bf56b69df204fd29e9487f1390197bbe 100644
+--- a/ipalib/plugins/service.py
++++ b/ipalib/plugins/service.py
+@@ -137,12 +137,24 @@ output_params = (
+     Str('ipaallowedtoperform_read_keys_group',
+         label=_('Groups allowed to retrieve keytab'),
+     ),
++    Str('ipaallowedtoperform_read_keys_host',
++        label=_('Hosts allowed to retrieve keytab'),
++    ),
++    Str('ipaallowedtoperform_read_keys_hostgroup',
++        label=_('Host Groups allowed to retrieve keytab'),
++    ),
+     Str('ipaallowedtoperform_write_keys_user',
+         label=_('Users allowed to create keytab'),
+     ),
+     Str('ipaallowedtoperform_write_keys_group',
+         label=_('Groups allowed to create keytab'),
+     ),
++    Str('ipaallowedtoperform_write_keys_host',
++        label=_('Hosts allowed to create keytab'),
++    ),
++    Str('ipaallowedtoperform_write_keys_hostgroup',
++        label=_('Host Groups allowed to create keytab'),
++    ),
+     Str('ipaallowedtoperform_read_keys',
+         label=_('Failed allowed to retrieve keytab'),
+     ),
+@@ -350,8 +362,8 @@ class service(LDAPObject):
+     attribute_members = {
+         'managedby': ['host'],
+         'memberof': ['role'],
+-        'ipaallowedtoperform_read_keys': ['user', 'group'],
+-        'ipaallowedtoperform_write_keys': ['user', 'group'],
++        'ipaallowedtoperform_read_keys': ['user', 'group', 'host', 'hostgroup'],
++        'ipaallowedtoperform_write_keys': ['user', 'group', 'host', 'hostgroup'],
+     }
+     bindable = True
+     relationships = {
+@@ -711,7 +723,8 @@ class service_remove_host(LDAPRemoveMember):
+ 
+ @register()
+ class service_allow_retrieve_keytab(LDAPAddMember):
+-    __doc__ = _('Allow users or groups to retrieve a keytab of this service.')
++    __doc__ = _('Allow users, groups, hosts or host groups to retrieve a keytab'
++                ' of this service.')
+     member_attributes = ['ipaallowedtoperform_read_keys']
+     has_output_params = LDAPAddMember.has_output_params + output_params
+ 
+@@ -729,7 +742,8 @@ class service_allow_retrieve_keytab(LDAPAddMember):
+ 
+ @register()
+ class service_disallow_retrieve_keytab(LDAPRemoveMember):
+-    __doc__ = _('Disallow users or groups to retrieve a keytab of this service.')
++    __doc__ = _('Disallow users, groups, hosts or host groups to retrieve a '
++                'keytab of this service.')
+     member_attributes = ['ipaallowedtoperform_read_keys']
+     has_output_params = LDAPRemoveMember.has_output_params + output_params
+ 
+@@ -746,7 +760,8 @@ class service_disallow_retrieve_keytab(LDAPRemoveMember):
+ 
+ @register()
+ class service_allow_create_keytab(LDAPAddMember):
+-    __doc__ = _('Allow users or groups to create a keytab of this service.')
++    __doc__ = _('Allow users, groups, hosts or host groups to create a keytab '
++                'of this service.')
+     member_attributes = ['ipaallowedtoperform_write_keys']
+     has_output_params = LDAPAddMember.has_output_params + output_params
+ 
+@@ -764,7 +779,8 @@ class service_allow_create_keytab(LDAPAddMember):
+ 
+ @register()
+ class service_disallow_create_keytab(LDAPRemoveMember):
+-    __doc__ = _('Disallow users or groups to create a keytab of this service.')
++    __doc__ = _('Disallow users, groups, hosts or host groups to create a '
++                'keytab of this service.')
+     member_attributes = ['ipaallowedtoperform_write_keys']
+     has_output_params = LDAPRemoveMember.has_output_params + output_params
+ 
+diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
+index 67acb765fc1716e10ac7846d8780bf031c9f079e..1c46ce9131554b799d25a15922d26ccb92763e93 100644
+--- a/ipatests/test_xmlrpc/test_host_plugin.py
++++ b/ipatests/test_xmlrpc/test_host_plugin.py
+@@ -147,6 +147,9 @@ group1 = u'group1'
+ group1_dn = get_group_dn(group1)
+ group2 = u'group2'
+ group2_dn = get_group_dn(group2)
++hostgroup1 = u'testhostgroup1'
++hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
++                    api.env.basedn)
+ 
+ class test_host(Declarative):
+ 
+@@ -1420,6 +1423,8 @@ class test_host_allowed_to(Declarative):
+         ('group_del', [group1], {}),
+         ('group_del', [group2], {}),
+         ('host_del', [fqdn1], {}),
++        ('host_del', [fqdn3], {}),
++        ('hostgroup_del', [hostgroup1], {}),
+     ]
+ 
+     tests = [
+@@ -1503,6 +1508,49 @@ class test_host_allowed_to(Declarative):
+                 ),
+             ),
+         ),
++        dict(
++            desc='Create %r' % fqdn3,
++            command=(
++                'host_add', [fqdn3],
++                dict(
++                    force=True,
++                ),
++            ),
++            expected=dict(
++                value=fqdn3,
++                summary=u'Added host "%s"' % fqdn3,
++                result=dict(
++                    dn=dn3,
++                    fqdn=[fqdn3],
++                    krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
++                    objectclass=objectclasses.host,
++                    ipauniqueid=[fuzzy_uuid],
++                    managedby_host=[fqdn3],
++                    has_keytab=False,
++                    has_password=False,
++                ),
++            ),
++        ),
++
++        dict(
++            desc='Create %r' % hostgroup1,
++            command=('hostgroup_add', [hostgroup1],
++                dict(description=u'Test hostgroup 1')
++            ),
++            expected=dict(
++                value=hostgroup1,
++                summary=u'Added hostgroup "testhostgroup1"',
++                result=dict(
++                    dn=hostgroup1_dn,
++                    cn=[hostgroup1],
++                    objectclass=objectclasses.hostgroup,
++                    description=[u'Test hostgroup 1'],
++                    ipauniqueid=[fuzzy_uuid],
++                    mepmanagedentry=[DN(('cn',hostgroup1),('cn','ng'),('cn','alt'),
++                                        api.env.basedn)],
++                ),
++            ),
++        ),
+ 
+         # verify
+         dict(
+@@ -1513,6 +1561,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -1535,6 +1585,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user1, u'This entry is already a member']],
+                     ),
+                 ),
+@@ -1553,20 +1605,25 @@ class test_host_allowed_to(Declarative):
+             desc='Allow %r, %r to a retrieve keytab of %r' % (
+                 group1, group2, fqdn1),
+             command=('host_allow_retrieve_keytab', [fqdn1],
+-                     dict(group=[group1, group2])),
++                     dict(group=[group1, group2], host=[fqdn3],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+-                completed=2,
++                completed=4,
+                 result=dict(
+                     dn=dn1,
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1, group2],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1581,6 +1638,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user2, u'This entry is not a member']],
+                     ),
+                 ),
+@@ -1590,6 +1649,8 @@ class test_host_allowed_to(Declarative):
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1, group2],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1604,6 +1665,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -1613,6 +1676,8 @@ class test_host_allowed_to(Declarative):
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1623,22 +1688,29 @@ class test_host_allowed_to(Declarative):
+             desc='Allow %r, %r to a create keytab of %r' % (
+                 group1, user1, fqdn1),
+             command=('host_allow_create_keytab', [fqdn1],
+-                     dict(group=[group1, group2], user=[user1])),
++                     dict(group=[group1, group2], user=[user1], host=[fqdn3],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+-                completed=3,
++                completed=5,
+                 result=dict(
+                     dn=dn1,
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1648,12 +1720,15 @@ class test_host_allowed_to(Declarative):
+         dict(
+             desc='Duplicate add: %r, %r' % (user1, group1),
+             command=('host_allow_create_keytab', [fqdn1],
+-                     dict(group=[group1], user=[user1])),
++                     dict(group=[group1], user=[user1], host=[fqdn3],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[[group1, u'This entry is already a member']],
++                        host=[[fqdn3, u'This entry is already a member']],
+                         user=[[user1, u'This entry is already a member']],
++                        hostgroup=[[hostgroup1, u'This entry is already a member']],
+                     ),
+                 ),
+                 completed=0,
+@@ -1662,8 +1737,12 @@ class test_host_allowed_to(Declarative):
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1678,6 +1757,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user2, u'This entry is not a member']],
+                     ),
+                 ),
+@@ -1687,8 +1768,12 @@ class test_host_allowed_to(Declarative):
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1703,6 +1788,8 @@ class test_host_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -1712,8 +1799,12 @@ class test_host_allowed_to(Declarative):
+                     fqdn=[fqdn1],
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1733,8 +1824,12 @@ class test_host_allowed_to(Declarative):
+                     has_password=False,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1756,8 +1851,12 @@ class test_host_allowed_to(Declarative):
+                     has_password=False,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn3],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn3],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                     managedby_host=[fqdn1],
+                 ),
+diff --git a/ipatests/test_xmlrpc/test_service_plugin.py b/ipatests/test_xmlrpc/test_service_plugin.py
+index 927ce73f86a0025b8384cf0126ef00be3598975a..946dc572b0d0e5b3f26cd7bfd6ad8128f113493f 100644
+--- a/ipatests/test_xmlrpc/test_service_plugin.py
++++ b/ipatests/test_xmlrpc/test_service_plugin.py
+@@ -54,6 +54,9 @@ group1 = u'group1'
+ group1_dn = get_group_dn(group1)
+ group2 = u'group2'
+ group2_dn = get_group_dn(group2)
++hostgroup1 = u'testhostgroup1'
++hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
++                    api.env.basedn)
+ 
+ class test_service(Declarative):
+ 
+@@ -770,6 +773,7 @@ class test_service_allowed_to(Declarative):
+         ('group_del', [group2], {}),
+         ('host_del', [fqdn1], {}),
+         ('service_del', [service1], {}),
++        ('hostgroup_del', [hostgroup1], {}),
+     ]
+ 
+     tests = [
+@@ -858,6 +862,25 @@ class test_service_allowed_to(Declarative):
+             ),
+         ),
+         dict(
++            desc='Create %r' % hostgroup1,
++            command=('hostgroup_add', [hostgroup1],
++                dict(description=u'Test hostgroup 1')
++            ),
++            expected=dict(
++                value=hostgroup1,
++                summary=u'Added hostgroup "testhostgroup1"',
++                result=dict(
++                    dn=hostgroup1_dn,
++                    cn=[hostgroup1],
++                    objectclass=objectclasses.hostgroup,
++                    description=[u'Test hostgroup 1'],
++                    ipauniqueid=[fuzzy_uuid],
++                    mepmanagedentry=[DN(('cn',hostgroup1),('cn','ng'),('cn','alt'),
++                                        api.env.basedn)],
++                ),
++            ),
++        ),
++        dict(
+             desc='Create %r' % service1,
+             command=('service_add', [service1_no_realm], dict(force=True)),
+             expected=dict(
+@@ -882,6 +905,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -903,6 +928,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user1, u'This entry is already a member']],
+                     ),
+                 ),
+@@ -917,22 +944,27 @@ class test_service_allowed_to(Declarative):
+         ),
+ 
+         dict(
+-            desc='Allow %r, %r to a retrieve keytab of %r' % (
+-                group1, group2, service1),
++            desc='Allow %r, %r, %r to a retrieve keytab of %r' % (
++                group1, group2, fqdn1, service1),
+             command=('service_allow_retrieve_keytab', [service1],
+-                     dict(group=[group1, group2])),
++                     dict(group=[group1, group2], host=[fqdn1],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+-                completed=2,
++                completed=4,
+                 result=dict(
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1, group2],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -947,6 +979,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user2, u'This entry is not a member']],
+                     ),
+                 ),
+@@ -955,6 +989,8 @@ class test_service_allowed_to(Declarative):
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1, group2],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -969,6 +1005,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_read_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -977,6 +1015,8 @@ class test_service_allowed_to(Declarative):
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -984,24 +1024,31 @@ class test_service_allowed_to(Declarative):
+         ),
+ 
+         dict(
+-            desc='Allow %r, %r to a create keytab of %r' % (
+-                group1, user1, service1),
++            desc='Allow %r, %r, %r to a create keytab of %r' % (
++                group1, user1, fqdn1, service1),
+             command=('service_allow_create_keytab', [service1],
+-                     dict(group=[group1, group2], user=[user1])),
++                     dict(group=[group1, group2], user=[user1], host=[fqdn1],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+-                completed=3,
++                completed=5,
+                 result=dict(
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1011,12 +1058,15 @@ class test_service_allowed_to(Declarative):
+         dict(
+             desc='Duplicate add: %r, %r' % (user1, group1),
+             command=('service_allow_create_keytab', [service1],
+-                     dict(group=[group1], user=[user1])),
++                     dict(group=[group1], user=[user1], host=[fqdn1],
++                          hostgroup=[hostgroup1])),
+             expected=dict(
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[[group1, u'This entry is already a member']],
++                        host=[[fqdn1, u'This entry is already a member']],
+                         user=[[user1, u'This entry is already a member']],
++                        hostgroup=[[hostgroup1, u'This entry is already a member']],
+                     ),
+                 ),
+                 completed=0,
+@@ -1024,8 +1074,12 @@ class test_service_allowed_to(Declarative):
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1040,6 +1094,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[[user2, u'This entry is not a member']],
+                     ),
+                 ),
+@@ -1048,8 +1104,12 @@ class test_service_allowed_to(Declarative):
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1, group2],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1064,6 +1124,8 @@ class test_service_allowed_to(Declarative):
+                 failed=dict(
+                     ipaallowedtoperform_write_keys=dict(
+                         group=[],
++                        host=[],
++                        hostgroup=[],
+                         user=[],
+                     ),
+                 ),
+@@ -1072,8 +1134,12 @@ class test_service_allowed_to(Declarative):
+                     dn=service1dn,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1091,8 +1157,12 @@ class test_service_allowed_to(Declarative):
+                     has_keytab=False,
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     krbprincipalname=[service1],
+                     managedby_host=[fqdn1],
+                 ),
+@@ -1110,8 +1180,12 @@ class test_service_allowed_to(Declarative):
+                 result=dict(
+                     ipaallowedtoperform_read_keys_user=[user1],
+                     ipaallowedtoperform_read_keys_group=[group1],
++                    ipaallowedtoperform_read_keys_host=[fqdn1],
++                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
+                     ipaallowedtoperform_write_keys_user=[user1],
+                     ipaallowedtoperform_write_keys_group=[group1],
++                    ipaallowedtoperform_write_keys_host=[fqdn1],
++                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
+                     ipakrbokasdelegate=True,
+                     krbprincipalname=[service1],
+                     krbticketflags=[u'1048704'],
+-- 
+2.1.0
+
diff --git a/SOURCES/0074-hosts-Display-assigned-ID-view-by-default-in-host-fi.patch b/SOURCES/0074-hosts-Display-assigned-ID-view-by-default-in-host-fi.patch
new file mode 100644
index 0000000..906a2dc
--- /dev/null
+++ b/SOURCES/0074-hosts-Display-assigned-ID-view-by-default-in-host-fi.patch
@@ -0,0 +1,152 @@
+From 4acf45785f917bb52382202279d5931469198f26 Mon Sep 17 00:00:00 2001
+From: Tomas Babej <tbabej@redhat.com>
+Date: Tue, 2 Dec 2014 15:40:40 +0100
+Subject: [PATCH] hosts: Display assigned ID view by default in host-find and
+ show commands
+
+Makes ipaassignedidview a default attribute and takes care about the
+conversion from the DN to the proper ID view name.
+
+https://fedorahosted.org/freeipa/ticket/4774
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ API.txt                        |  6 +++---
+ VERSION                        |  4 ++--
+ install/ui/src/freeipa/host.js |  1 -
+ ipalib/plugins/host.py         | 21 ++++++++++++++++++---
+ 4 files changed, 23 insertions(+), 9 deletions(-)
+
+diff --git a/API.txt b/API.txt
+index e9768bf1e87d6679c439b98ed696b720937099d2..7949c49f9fb9e3cd7eceb64a05dd8e550eb48f8b 100644
+--- a/API.txt
++++ b/API.txt
+@@ -1793,7 +1793,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui
+ option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
+ option: Flag('force', autofill=True, default=False)
+ option: Str('ip_address?')
+-option: DNParam('ipaassignedidview', attribute=True, cli_name='ipaassignedidview', multivalue=False, required=False)
++option: Str('ipaassignedidview', attribute=True, cli_name='ipaassignedidview', multivalue=False, required=False)
+ option: Bool('ipakrbokasdelegate', attribute=False, cli_name='ok_as_delegate', multivalue=False, required=False)
+ option: Bool('ipakrbrequirespreauth', attribute=False, cli_name='requires_pre_auth', multivalue=False, required=False)
+ option: Str('ipasshpubkey', attribute=True, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
+@@ -1909,7 +1909,7 @@ option: Str('in_hostgroup*', cli_name='in_hostgroups', csv=True)
+ option: Str('in_netgroup*', cli_name='in_netgroups', csv=True)
+ option: Str('in_role*', cli_name='in_roles', csv=True)
+ option: Str('in_sudorule*', cli_name='in_sudorules', csv=True)
+-option: DNParam('ipaassignedidview', attribute=True, autofill=False, cli_name='ipaassignedidview', multivalue=False, query=True, required=False)
++option: Str('ipaassignedidview', attribute=True, autofill=False, cli_name='ipaassignedidview', multivalue=False, query=True, required=False)
+ option: Str('l', attribute=True, autofill=False, cli_name='locality', multivalue=False, query=True, required=False)
+ option: Str('macaddress', attribute=True, autofill=False, cli_name='macaddress', csv=True, multivalue=True, pattern='^([a-fA-F0-9]{2}[:|\\-]?){5}[a-fA-F0-9]{2}$', query=True, required=False)
+ option: Str('man_by_host*', cli_name='man_by_hosts', csv=True)
+@@ -1945,7 +1945,7 @@ option: Str('addattr*', cli_name='addattr', exclude='webui')
+ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+ option: Str('delattr*', cli_name='delattr', exclude='webui')
+ option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
+-option: DNParam('ipaassignedidview', attribute=True, autofill=False, cli_name='ipaassignedidview', multivalue=False, required=False)
++option: Str('ipaassignedidview', attribute=True, autofill=False, cli_name='ipaassignedidview', multivalue=False, required=False)
+ option: Bool('ipakrbokasdelegate', attribute=False, autofill=False, cli_name='ok_as_delegate', multivalue=False, required=False)
+ option: Bool('ipakrbrequirespreauth', attribute=False, autofill=False, cli_name='requires_pre_auth', multivalue=False, required=False)
+ option: Str('ipasshpubkey', attribute=True, autofill=False, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
+diff --git a/VERSION b/VERSION
+index bfbce5604e79008afd2893e406c634718159b1e9..196be85e83de96f501352ca93f2c7ed6876ea641 100644
+--- a/VERSION
++++ b/VERSION
+@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
+ #                                                      #
+ ########################################################
+ IPA_API_VERSION_MAJOR=2
+-IPA_API_VERSION_MINOR=110
+-# Last change: pvoborni - allow to retrieve keytab by hosts
++IPA_API_VERSION_MINOR=112
++# Last change: tbabej - change ipaassignedidview to Str
+diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js
+index 455ff8f50ec58104d4e046ec0fabf2a7e89eeeb2..1120c82e708f20081ee9ec5f5c1b4c349d101b15 100644
+--- a/install/ui/src/freeipa/host.js
++++ b/install/ui/src/freeipa/host.js
+@@ -117,7 +117,6 @@ return {
+                             name: 'ipaassignedidview',
+                             $type: 'link',
+                             label: '@i18n:objects.idview.ipaassignedidview',
+-                            ui_formatter: 'dn',
+                             other_entity: 'idview'
+                         }
+                     ]
+diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
+index 39a7d3c25b9cb56fca486b2500da5fe7bd4a6fbc..41710f3b87b5f60ac6e9b0765a25562b7074e2e8 100644
+--- a/ipalib/plugins/host.py
++++ b/ipalib/plugins/host.py
+@@ -22,7 +22,7 @@ from nss.error import NSPRError
+ import string
+ 
+ from ipalib import api, errors, util
+-from ipalib import Str, Flag, Bytes, DNParam
++from ipalib import Str, Flag, Bytes
+ from ipalib.plugable import Registry
+ from ipalib.plugins.baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
+                                      LDAPDelete, LDAPUpdate, LDAPSearch,
+@@ -162,6 +162,17 @@ def update_sshfp_record(zone, record, entry_attrs):
+     except errors.EmptyModlist:
+         pass
+ 
++
++def convert_ipaassignedidview_post(entry_attrs, options):
++    """
++    Converts the ID View DN to its name for the better looking output.
++    """
++
++    if 'ipaassignedidview' in entry_attrs and not options.get('raw'):
++        idview_name = entry_attrs.single_value['ipaassignedidview'][0].value
++        entry_attrs.single_value['ipaassignedidview'] = idview_name
++
++
+ host_output_params = (
+     Flag('has_keytab',
+         label=_('Keytab'),
+@@ -286,7 +297,7 @@ class host(LDAPObject):
+         'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
+         'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof',
+         'managedby', 'memberindirect', 'memberofindirect', 'macaddress',
+-        'userclass', 'ipaallowedtoperform'
++        'userclass', 'ipaallowedtoperform', 'ipaassignedidview',
+     ]
+     uuid_attribute = 'ipauniqueid'
+     attribute_members = {
+@@ -513,7 +524,8 @@ class host(LDAPObject):
+             doc=_('Host category (semantics placed on this attribute are for '
+                   'local interpretation)'),
+         ),
+-        DNParam('ipaassignedidview?',
++        Str('ipaassignedidview?',
++            label=_('Assigned ID View'),
+             flags=['no_option'],
+         ),
+     ) + ticket_flags_params
+@@ -949,6 +961,7 @@ class host_mod(LDAPUpdate):
+         self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
+ 
+         convert_sshpubkey_post(ldap, dn, entry_attrs)
++        convert_ipaassignedidview_post(entry_attrs, options)
+ 
+         return dn
+ 
+@@ -1035,6 +1048,7 @@ class host_find(LDAPSearch):
+                 entry_attrs['managing'] = self.obj.get_managed_hosts(entry_attrs.dn)
+ 
+             convert_sshpubkey_post(ldap, entry_attrs.dn, entry_attrs)
++            convert_ipaassignedidview_post(entry_attrs, options)
+ 
+         return truncated
+ 
+@@ -1070,6 +1084,7 @@ class host_show(LDAPRetrieve):
+         self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
+ 
+         convert_sshpubkey_post(ldap, dn, entry_attrs)
++        convert_ipaassignedidview_post(entry_attrs, options)
+ 
+         return dn
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0075-Prefer-TCP-connections-to-UDP-in-krb5-clients.patch b/SOURCES/0075-Prefer-TCP-connections-to-UDP-in-krb5-clients.patch
new file mode 100644
index 0000000..42e9d66
--- /dev/null
+++ b/SOURCES/0075-Prefer-TCP-connections-to-UDP-in-krb5-clients.patch
@@ -0,0 +1,61 @@
+From 0538c3040f65dea97a8e98eab7be2c8fc8ff17a9 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Fri, 5 Dec 2014 11:18:55 -0500
+Subject: [PATCH] Prefer TCP connections to UDP in krb5 clients
+
+In general, TCP is a better fit for FreeIPA due to large packet sizes.
+
+However, there is also a specific need for TCP when using OTP. If a UDP
+packet is delivered to the server and the server takes longer to process
+it than the client timeout (likely), the OTP value will be resent.
+Unfortunately, this will cause failures or even lockouts. Switching to
+TCP avoids this problem altogether.
+
+https://fedorahosted.org/freeipa/ticket/4725
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ install/share/krb5.conf.template          | 1 +
+ install/tools/ipa-replica-conncheck       | 1 +
+ ipa-client/ipa-install/ipa-client-install | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/install/share/krb5.conf.template b/install/share/krb5.conf.template
+index 7c82083e3331cfacccc1995cd9dfa6ddd88edd1f..6cb5ee34704cd6158e882bfa89fc597f3ff1bb0f 100644
+--- a/install/share/krb5.conf.template
++++ b/install/share/krb5.conf.template
+@@ -12,6 +12,7 @@ includedir /var/lib/sss/pubconf/krb5.include.d/
+  rdns = false
+  ticket_lifetime = 24h
+  forwardable = yes
++ udp_preference_limit = 0
+ $OTHER_LIBDEFAULTS
+ [realms]
+  $REALM = {
+diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
+index 88e42bafbc600fb7c36b7727c770e75edccd2196..22348fc2158e59afc2e1aa51e3d3f51e90b99e39 100755
+--- a/install/tools/ipa-replica-conncheck
++++ b/install/tools/ipa-replica-conncheck
+@@ -208,6 +208,7 @@ def configure_krb5_conf(realm, kdc, filename):
+     libdefaults.append({'name':'rdns', 'type':'option', 'value':'false'})
+     libdefaults.append({'name':'ticket_lifetime', 'type':'option', 'value':'24h'})
+     libdefaults.append({'name':'forwardable', 'type':'option', 'value':'yes'})
++    libdefaults.append({'name':'udp_preference_limit', 'type':'option', 'value':'0'})
+ 
+     opts.append({'name':'libdefaults', 'type':'section', 'value': libdefaults})
+     opts.append({'name':'empty', 'type':'empty'})
+diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
+index 7b1e2f8b0b873375c14d02558dce65b68a5ad173..75a1711a7e1fdc9359ad02d55ad94d65af51ea93 100755
+--- a/ipa-client/ipa-install/ipa-client-install
++++ b/ipa-client/ipa-install/ipa-client-install
+@@ -1047,6 +1047,7 @@ def configure_krb5_conf(cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
+     libopts.append({'name':'rdns', 'type':'option', 'value':'false'})
+     libopts.append({'name':'ticket_lifetime', 'type':'option', 'value':'24h'})
+     libopts.append({'name':'forwardable', 'type':'option', 'value':'yes'})
++    libopts.append({'name':'udp_preference_limit', 'type':'option', 'value':'0'})
+ 
+     # Configure KEYRING CCACHE if supported
+     if kernel_keyring.is_persistent_keyring_supported():
+-- 
+2.1.0
+
diff --git a/SOURCES/0076-webui-fix-service-unprovisioning.patch b/SOURCES/0076-webui-fix-service-unprovisioning.patch
new file mode 100644
index 0000000..89d44ef
--- /dev/null
+++ b/SOURCES/0076-webui-fix-service-unprovisioning.patch
@@ -0,0 +1,30 @@
+From e70d7becc295aacdc1c90f64fe65266a8c0d0205 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 27 Nov 2014 12:47:42 +0100
+Subject: [PATCH] webui: fix service unprovisioning
+
+Missed part of field refactoring caused that service could not be unprovisioned.
+
+https://fedorahosted.org/freeipa/ticket/4770
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ install/ui/src/freeipa/service.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
+index 3e47981bdbda9cd076eab75da0f5133503af6f3d..94842a912c77a55acad9d2f0881f3ad23915f700 100644
+--- a/install/ui/src/freeipa/service.js
++++ b/install/ui/src/freeipa/service.js
+@@ -467,7 +467,7 @@ IPA.service.unprovision_dialog = function(spec) {
+     that.unprovision = function() {
+ 
+         var principal_f  = that.facet.fields.get_field('krbprincipalname');
+-        var pkey = principal_f.values[0];
++        var pkey = principal_f.get_value()[0];
+ 
+         rpc.command({
+             entity: that.entity.name,
+-- 
+2.1.0
+
diff --git a/SOURCES/0077-webui-increase-duration-of-notification-messages.patch b/SOURCES/0077-webui-increase-duration-of-notification-messages.patch
new file mode 100644
index 0000000..7c49e9f
--- /dev/null
+++ b/SOURCES/0077-webui-increase-duration-of-notification-messages.patch
@@ -0,0 +1,30 @@
+From d6f71c1fc95f4d266d15e2f5e516f2947da97a25 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Fri, 5 Dec 2014 16:21:19 +0100
+Subject: [PATCH] webui: increase duration of notification messages
+
+by 66%
+
+https://fedorahosted.org/freeipa/ticket/4792
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ install/ui/src/freeipa/ipa.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js
+index 137f11e832ff8d0b6dd1b50060f8537c7b117616..a78d1f0638ec5d750b5aee52197c5b04feae3f94 100644
+--- a/install/ui/src/freeipa/ipa.js
++++ b/install/ui/src/freeipa/ipa.js
+@@ -1198,7 +1198,7 @@ IPA.get_succeeded = function(data) {
+  */
+ IPA.config = {
+     default_priority: 500,
+-    message_timeout: 3000, // [ms]
++    message_timeout: 5000, // [ms]
+     message_timeout_length: 50 // [chars]
+ };
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0078-Fix-automatic-CA-cert-renewal-endless-loop-in-dogtag.patch b/SOURCES/0078-Fix-automatic-CA-cert-renewal-endless-loop-in-dogtag.patch
new file mode 100644
index 0000000..797a2fa
--- /dev/null
+++ b/SOURCES/0078-Fix-automatic-CA-cert-renewal-endless-loop-in-dogtag.patch
@@ -0,0 +1,34 @@
+From 90fde5a437f23cac0534f66bc3564c9c676010ab Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 3 Dec 2014 07:43:15 +0000
+Subject: [PATCH] Fix automatic CA cert renewal endless loop in
+ dogtag-ipa-ca-renew-agent
+
+Reset profile name after requesting the CA cert from Dogtag to prevent the
+automatic renewal request from being restarted in subsequent calls.
+
+https://fedorahosted.org/freeipa/ticket/4765
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/certmonger/dogtag-ipa-ca-renew-agent-submit | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index 0a2cff148810e4800c02121afc68911c221d34d7..e0dd33fda6036ed2fb003a89c35eacb1784a5e25 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -408,8 +408,10 @@ def renew_ca_cert():
+                           "IPA CA certificate is about to expire, "
+                           "use ipa-cacert-manage to renew it")
+     elif state == 'request':
++        profile = os.environ['CERTMONGER_CA_PROFILE']
+         os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
+         result = call_handler(request_and_store_cert)
++        os.environ['CERTMONGER_CA_PROFILE'] = profile
+ 
+     if result[0] == WAIT:
+         return (result[0], '%s:%s' % (state, result[1]))
+-- 
+2.1.0
+
diff --git a/SOURCES/0079-Do-not-renew-the-IPA-CA-cert-by-serial-number-in-dog.patch b/SOURCES/0079-Do-not-renew-the-IPA-CA-cert-by-serial-number-in-dog.patch
new file mode 100644
index 0000000..c7adb92
--- /dev/null
+++ b/SOURCES/0079-Do-not-renew-the-IPA-CA-cert-by-serial-number-in-dog.patch
@@ -0,0 +1,34 @@
+From a292db4ee5cc30161948d8e71f3b998f978ae7f9 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 4 Dec 2014 15:34:55 +0000
+Subject: [PATCH] Do not renew the IPA CA cert by serial number in
+ dogtag-ipa-ca-renew-agent
+
+Always use the full CSR when renewing the IPA CA certificate with Dogtag. The
+IPA CA certificate may be issued by an external CA, in which case renewal by
+serial number does not make sense and will fail if the IPA CA was initially
+installed as a subordinate of an external CA.
+
+https://fedorahosted.org/freeipa/ticket/4784
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/certmonger/dogtag-ipa-ca-renew-agent-submit | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index e0dd33fda6036ed2fb003a89c35eacb1784a5e25..c63c0c2c5f863e05cafad293a60d9157c732e7ad 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -147,7 +147,7 @@ def request_cert():
+     path = paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT
+     args = [path] + sys.argv[1:]
+     if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert':
+-        args += ['-O', 'bypassCAnotafter=true']
++        args += ['-N', '-O', 'bypassCAnotafter=true']
+     stdout, stderr, rc = ipautil.run(args, raiseonerr=False, env=os.environ)
+     sys.stderr.write(stderr)
+     sys.stderr.flush()
+-- 
+2.1.0
+
diff --git a/SOURCES/0080-Improve-validation-of-instance-and-backend-options-i.patch b/SOURCES/0080-Improve-validation-of-instance-and-backend-options-i.patch
new file mode 100644
index 0000000..f8e9fd5
--- /dev/null
+++ b/SOURCES/0080-Improve-validation-of-instance-and-backend-options-i.patch
@@ -0,0 +1,169 @@
+From cc256391c89c9d8d7c8ae9e1ce647396cded0674 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 1 Dec 2014 12:12:15 +0000
+Subject: [PATCH] Improve validation of --instance and --backend options in
+ ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4744
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipaplatform/base/paths.py        |  2 +-
+ ipaserver/install/ipa_backup.py  |  2 +-
+ ipaserver/install/ipa_restore.py | 73 ++++++++++++++++++++++++----------------
+ 3 files changed, 46 insertions(+), 31 deletions(-)
+
+diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
+index e28147ab4aa1faa3859c38665a83f57fb67e96b2..8bfab1bc92f79b5e76555b35a8b646e1ff56f84b 100644
+--- a/ipaplatform/base/paths.py
++++ b/ipaplatform/base/paths.py
+@@ -261,7 +261,7 @@ class BasePathNamespace(object):
+     VAR_LIB_DIRSRV_INSTANCE_SCRIPTS_TEMPLATE = "/var/lib/dirsrv/scripts-%s"
+     VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s"
+     SLAPD_INSTANCE_BACKUP_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/bak/%s"
+-    IPACA_DIRSRV_INSTANCE_DB_TEMPLATE = "/var/lib/dirsrv/slapd-%s/db/ipaca"
++    SLAPD_INSTANCE_DB_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/db/%s"
+     SLAPD_INSTANCE_LDIF_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/ldif"
+     VAR_LIB_SLAPD_PKI_IPA_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-PKI-IPA"
+     VAR_LIB_IPA = "/var/lib/ipa"
+diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
+index 5d583f7e9186f20ebe8187ba70db28de0c255ae7..72d1475d6db92b6b9e715afdae85d169a036c085 100644
+--- a/ipaserver/install/ipa_backup.py
++++ b/ipaserver/install/ipa_backup.py
+@@ -292,7 +292,7 @@ class Backup(admintool.AdminTool):
+ 
+             for instance in [realm_to_serverid(api.env.realm), 'PKI-IPA']:
+                 if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance):
+-                    if os.path.exists(paths.IPACA_DIRSRV_INSTANCE_DB_TEMPLATE % instance):
++                    if os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE % (instance, 'ipaca')):
+                         self.db2ldif(instance, 'ipaca', online=options.online)
+                     self.db2ldif(instance, 'userRoot', online=options.online)
+                     self.db2bak(instance, online=options.online)
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 9cb978a516f4f85307735b7428f6053461061022..097703938a7ba3820f4acae2148760146464fa08 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -188,15 +188,35 @@ class Restore(admintool.AdminTool):
+         self.log.info("Preparing restore from %s on %s",
+             self.backup_dir, api.env.host)
+ 
+-        if not options.instance:
+-            instances = []
+-            for instance in [realm_to_serverid(api.env.realm), 'PKI-IPA']:
+-                if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance):
+-                    instances.append(instance)
++        if options.instance and options.backend:
++            database = (options.instance, options.backend)
++            if not os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
++                                  database):
++                raise admintool.ScriptError(
++                    "Instance %s with backend %s does not exist" % database)
++
++            databases = [database]
+         else:
+-            instances = [options.instance]
+-        if options.data_only and not instances:
+-            raise admintool.ScriptError('No instances to restore to')
++            if options.instance:
++                instances = [options.instance]
++            else:
++                instances = [realm_to_serverid(api.env.realm), 'PKI-IPA']
++
++            if options.backend:
++                backends = [options.backend]
++            else:
++                backends = ['userRoot', 'ipaca']
++
++            databases = []
++            for instance in instances:
++                for backend in backends:
++                    database = (instance, backend)
++                    if os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
++                                      database):
++                        databases.append(database)
++
++            if options.data_only and not databases:
++                raise admintool.ScriptError('No instances to restore to')
+ 
+         create_ds_user()
+         pent = pwd.getpwnam(DS_USER)
+@@ -223,7 +243,7 @@ class Restore(admintool.AdminTool):
+             # These two checks would normally be in the validate method but
+             # we need to know the type of backup we're dealing with.
+             if (self.backup_type != 'FULL' and not options.data_only and
+-                not instances):
++                not databases):
+                 raise admintool.ScriptError('Cannot restore a data backup into an empty system')
+             if (self.backup_type == 'FULL' and not options.data_only and
+                 (options.instance or options.backend)):
+@@ -244,6 +264,15 @@ class Restore(admintool.AdminTool):
+                     not user_input("Continue to restore?", False)):
+                     raise admintool.ScriptError("Aborted")
+ 
++            self.extract_backup(options.gpg_keyring)
++
++            for database in databases:
++                ldifname = '%s-%s.ldif' % database
++                ldiffile = os.path.join(self.dir, ldifname)
++                if not os.path.exists(ldiffile):
++                    raise admintool.ScriptError(
++                        "Instance %s with backend %s not in backup" % database)
++
+             # Big fat warning
+             if  (not options.unattended and
+                 not user_input("Restoring data will overwrite existing live data. Continue to restore?", False)):
+@@ -261,7 +290,6 @@ class Restore(admintool.AdminTool):
+             self.log.info("Disabling all replication.")
+             self.disable_agreements()
+ 
+-            self.extract_backup(options.gpg_keyring)
+             if options.data_only:
+                 if not options.online:
+                     self.log.info('Stopping Directory Server')
+@@ -295,16 +323,8 @@ class Restore(admintool.AdminTool):
+             # userRoot backend in it and the main IPA instance. If we
+             # have a unified instance we need to restore both userRoot and
+             # ipaca.
+-            for instance in instances:
+-                if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance):
+-                    if options.backend is None:
+-                        self.ldif2db(instance, 'userRoot', online=options.online)
+-                        if os.path.exists(paths.IPACA_DIRSRV_INSTANCE_DB_TEMPLATE % instance):
+-                            self.ldif2db(instance, 'ipaca', online=options.online)
+-                    else:
+-                        self.ldif2db(instance, options.backend, online=options.online)
+-                else:
+-                    raise admintool.ScriptError('389-ds instance %s does not exist' % instance)
++            for instance, backend in databases:
++                self.ldif2db(instance, backend, online=options.online)
+ 
+             if options.data_only:
+                 if not options.online:
+@@ -447,20 +467,15 @@ class Restore(admintool.AdminTool):
+             try:
+                 conn.add_entry(ent)
+             except Exception, e:
+-                raise admintool.ScriptError(
+-                    'Unable to bind to LDAP server: %s' % e)
++                self.log.error("Unable to bind to LDAP server: %s" % e)
++                return
+ 
+             self.log.info("Waiting for LDIF to finish")
+             wait_for_task(conn, dn)
+         else:
+             args = ['%s/ldif2db' % self.__find_scripts_dir(instance),
+-                    '-i', ldiffile]
+-            if backend is not None:
+-                args.append('-n')
+-                args.append(backend)
+-            else:
+-                args.append('-n')
+-                args.append('userRoot')
++                    '-i', ldiffile,
++                    '-n', backend]
+             (stdout, stderr, rc) = run(args, raiseonerr=False)
+             if rc != 0:
+                 self.log.critical("ldif2db failed: %s" % stderr)
+-- 
+2.1.0
+
diff --git a/SOURCES/0081-revert-removal-of-cn-attribute-from-idnsRecord.patch b/SOURCES/0081-revert-removal-of-cn-attribute-from-idnsRecord.patch
new file mode 100644
index 0000000..d619512
--- /dev/null
+++ b/SOURCES/0081-revert-removal-of-cn-attribute-from-idnsRecord.patch
@@ -0,0 +1,31 @@
+From a34f3eeb1f4501a43e978ddafdd50d46fa77a3b5 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 4 Dec 2014 17:30:20 +0100
+Subject: [PATCH] revert removal of cn attribute from idnsRecord
+
+The removal, which was done in IPA-3.2, causes replication issues between IPA < 3.2 and IPA 4.1. Because IPA 4.1 adds two more attributes.
+
+https://fedorahosted.org/freeipa/ticket/4794
+
+Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ install/share/60ipadns.ldif | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/share/60ipadns.ldif b/install/share/60ipadns.ldif
+index 678a5b483f7abbd0df2907513577573109297943..8fd0bb9e7c10f56c1d1c45b6ec9e8f1f9f7e7cef 100644
+--- a/install/share/60ipadns.ldif
++++ b/install/share/60ipadns.ldif
+@@ -63,7 +63,7 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.25 NAME 'idnsSecKeyRevoke' DESC 'DNSKE
+ attributeTypes: ( 2.16.840.1.113730.3.8.5.26 NAME 'idnsSecKeySep' DESC 'DNSKEY SEP flag (equivalent to bit 15): RFC 4035' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v4.1' )
+ attributeTypes: ( 2.16.840.1.113730.3.8.5.27 NAME 'idnsSecAlgorithm' DESC 'DNSKEY algorithm: string used as mnemonic' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'IPA v4.1' )
+ attributeTypes: ( 2.16.840.1.113730.3.8.5.28 NAME 'idnsSecKeyRef' DESC 'PKCS#11 URI of the key' EQUALITY caseExactMatch SINGLE-VALUE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v4.1' )
+-objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord ) )
++objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( cn $ idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord ) )
+ objectClasses: ( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $ idnsSOAmName $ idnsSOArName $ idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $ idnsSOAminimum ) MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $ idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $ idnsSecInlineSigning $ nSEC3PARAMRecord ) )
+ objectClasses: ( 2.16.840.1.113730.3.8.6.2 NAME 'idnsConfigObject' DESC 'DNS global config options' STRUCTURAL MAY ( idnsForwardPolicy $ idnsForwarders $ idnsAllowSyncPTR $ idnsZoneRefresh $ idnsPersistentSearch ) )
+ objectClasses: ( 2.16.840.1.113730.3.8.12.18 NAME 'ipaDNSZone' SUP top AUXILIARY MUST idnsName MAY managedBy X-ORIGIN 'IPA v3' )
+-- 
+2.1.0
+
diff --git a/SOURCES/0082-Check-subject-name-encoding-in-ipa-cacert-manage-ren.patch b/SOURCES/0082-Check-subject-name-encoding-in-ipa-cacert-manage-ren.patch
new file mode 100644
index 0000000..efe906b
--- /dev/null
+++ b/SOURCES/0082-Check-subject-name-encoding-in-ipa-cacert-manage-ren.patch
@@ -0,0 +1,51 @@
+From c39b8f8c8fd3af8e4587cd1c454a87c7fefb6490 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 4 Dec 2014 08:15:46 +0000
+Subject: [PATCH] Check subject name encoding in ipa-cacert-manage renew
+
+https://fedorahosted.org/freeipa/ticket/4781
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipaserver/install/ipa_cacert_manage.py | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
+index 2a8d95fdbebecf543a05afd47275c32684cad970..8fda6a263454e8a4046baa1da069cdcddeb177a9 100644
+--- a/ipaserver/install/ipa_cacert_manage.py
++++ b/ipaserver/install/ipa_cacert_manage.py
+@@ -213,18 +213,21 @@ class CACertManage(admintool.AdminTool):
+         try:
+             nss_cert = x509.load_certificate(old_cert, x509.DER)
+             subject = nss_cert.subject
++            der_subject = x509.get_der_subject(old_cert, x509.DER)
+             #pylint: disable=E1101
+             pkinfo = nss_cert.subject_public_key_info.format()
+             #pylint: enable=E1101
+ 
+             nss_cert = x509.load_certificate_from_file(cert_file.name)
++            cert = nss_cert.der_data
+             if nss_cert.subject != subject:
+                 raise admintool.ScriptError("Subject name mismatch")
++            if x509.get_der_subject(cert, x509.DER) != der_subject:
++                raise admintool.ScriptError("Subject name encoding mismatch")
+             #pylint: disable=E1101
+             if nss_cert.subject_public_key_info.format() != pkinfo:
+                 raise admintool.ScriptError("Subject public key info mismatch")
+             #pylint: enable=E1101
+-            cert = nss_cert.der_data
+         finally:
+             del nss_cert
+             nss.nss_shutdown()
+@@ -238,7 +241,7 @@ class CACertManage(admintool.AdminTool):
+                 tmpdb.add_cert(cert, 'IPA CA', 'C,,')
+             except ipautil.CalledProcessError, e:
+                 raise admintool.ScriptError(
+-                    "Not compatible with the current CA certificate: %s", e)
++                    "Not compatible with the current CA certificate: %s" % e)
+ 
+             ca_certs = x509.load_certificate_list_from_file(ca_file.name)
+             for ca_cert in ca_certs:
+-- 
+2.1.0
+
diff --git a/SOURCES/0083-Refer-the-user-to-freeipa.org-when-something-goes-wr.patch b/SOURCES/0083-Refer-the-user-to-freeipa.org-when-something-goes-wr.patch
new file mode 100644
index 0000000..7c26966
--- /dev/null
+++ b/SOURCES/0083-Refer-the-user-to-freeipa.org-when-something-goes-wr.patch
@@ -0,0 +1,68 @@
+From 675251b626028e8eb9b869ba661f919cec16da3c Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 9 Dec 2014 12:47:58 +0000
+Subject: [PATCH] Refer the user to freeipa.org when something goes wrong in
+ ipa-cacert-manage
+
+https://fedorahosted.org/freeipa/ticket/4781
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ ipaserver/install/ipa_cacert_manage.py | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
+index 8fda6a263454e8a4046baa1da069cdcddeb177a9..e074601692207253671ad4be6bca35458793625e 100644
+--- a/ipaserver/install/ipa_cacert_manage.py
++++ b/ipaserver/install/ipa_cacert_manage.py
+@@ -221,12 +221,21 @@ class CACertManage(admintool.AdminTool):
+             nss_cert = x509.load_certificate_from_file(cert_file.name)
+             cert = nss_cert.der_data
+             if nss_cert.subject != subject:
+-                raise admintool.ScriptError("Subject name mismatch")
++                raise admintool.ScriptError(
++                    "Subject name mismatch (visit "
++                    "http://www.freeipa.org/page/Troubleshooting for "
++                    "troubleshooting guide)")
+             if x509.get_der_subject(cert, x509.DER) != der_subject:
+-                raise admintool.ScriptError("Subject name encoding mismatch")
++                raise admintool.ScriptError(
++                    "Subject name encoding mismatch (visit "
++                    "http://www.freeipa.org/page/Troubleshooting for "
++                    "troubleshooting guide)")
+             #pylint: disable=E1101
+             if nss_cert.subject_public_key_info.format() != pkinfo:
+-                raise admintool.ScriptError("Subject public key info mismatch")
++                raise admintool.ScriptError(
++                    "Subject public key info mismatch (visit "
++                    "http://www.freeipa.org/page/Troubleshooting for "
++                    "troubleshooting guide)")
+             #pylint: enable=E1101
+         finally:
+             del nss_cert
+@@ -253,7 +262,9 @@ class CACertManage(admintool.AdminTool):
+                 tmpdb.verify_ca_cert_validity('IPA CA')
+             except ValueError, e:
+                 raise admintool.ScriptError(
+-                    "Not a valid CA certificate: %s" % e)
++                    "Not a valid CA certificate: %s (visit "
++                    "http://www.freeipa.org/page/Troubleshooting for "
++                    "troubleshooting guide)" % e)
+ 
+             trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
+             for nickname in trust_chain:
+@@ -340,7 +351,9 @@ class CACertManage(admintool.AdminTool):
+                 tmpdb.verify_ca_cert_validity(nickname)
+             except ValueError, e:
+                 raise admintool.ScriptError(
+-                    "Not a valid CA certificate: %s" % e)
++                    "Not a valid CA certificate: %s (visit "
++                    "http://www.freeipa.org/page/Troubleshooting for "
++                    "troubleshooting guide)" % e)
+ 
+         trust_flags = options.trust_flags
+         if ((set(trust_flags) - set(',CPTcgpuw')) or
+-- 
+2.1.0
+
diff --git a/SOURCES/0084-Show-SSHFP-record-containing-space-in-fingerprint.patch b/SOURCES/0084-Show-SSHFP-record-containing-space-in-fingerprint.patch
new file mode 100644
index 0000000..9379cb0
--- /dev/null
+++ b/SOURCES/0084-Show-SSHFP-record-containing-space-in-fingerprint.patch
@@ -0,0 +1,37 @@
+From 208c877a8d9981d11d90fc6599e15f5f40bd3168 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Thu, 4 Dec 2014 15:11:00 +0100
+Subject: [PATCH] Show SSHFP record containing space in fingerprint
+
+SSHFP records added by nsupdate contains extra space (valid), framework
+couldn't handle it.
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4790
+Ticket: https://fedorahosted.org/freeipa/ticket/4789
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/plugins/dns.py | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
+index c5d96a8c4fcdf101254ecefb60cb83d63bee6310..34afc189866993481229bb68a5edd77e0a4eaff3 100644
+--- a/ipalib/plugins/dns.py
++++ b/ipalib/plugins/dns.py
+@@ -1437,6 +1437,14 @@ class SSHFPRecord(DNSRecord):
+         ),
+     )
+ 
++    def _get_part_values(self, value):
++        # fingerprint part can contain space in LDAP, return it as one part
++        values = value.split(None, 2)
++        if len(values) != len(self.parts):
++            return None
++        return tuple(values)
++
++
+ class TARecord(DNSRecord):
+     rrtype = 'TA'
+     supported = False
+-- 
+2.1.0
+
diff --git a/SOURCES/0085-Always-add-etc-hosts-record-when-DNS-is-being-config.patch b/SOURCES/0085-Always-add-etc-hosts-record-when-DNS-is-being-config.patch
new file mode 100644
index 0000000..fced922
--- /dev/null
+++ b/SOURCES/0085-Always-add-etc-hosts-record-when-DNS-is-being-config.patch
@@ -0,0 +1,31 @@
+From 51aa38b3b2c851a5f745dadafcd8accb078fec13 Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Tue, 16 Dec 2014 20:35:05 -0500
+Subject: [PATCH] Always add /etc/hosts record when DNS is being configured.
+
+This was done previosly but accidentally removed when later with patch for
+ticket #3575.
+
+https://fedorahosted.org/freeipa/ticket/4817
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ ipaserver/install/installutils.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
+index b05b1550a3b7c33a939b4173e57bf1329581d58a..0ab09abea03c8b317e7d00466e127cda00ed17d9 100644
+--- a/ipaserver/install/installutils.py
++++ b/ipaserver/install/installutils.py
+@@ -494,7 +494,7 @@ def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses
+         hosts_record = record_in_hosts(str(ip_address))
+ 
+         if hosts_record is None:
+-            if ip_add_to_hosts:
++            if ip_add_to_hosts or setup_dns:
+                 print "Adding ["+str(ip_address)+" "+host_name+"] to your /etc/hosts file"
+                 fstore.backup_file(paths.HOSTS)
+                 add_record_to_hosts(str(ip_address), host_name)
+-- 
+2.1.0
+
diff --git a/SOURCES/0086-Avoid-calling-ldap-functions-without-a-context.patch b/SOURCES/0086-Avoid-calling-ldap-functions-without-a-context.patch
new file mode 100644
index 0000000..103cc3d
--- /dev/null
+++ b/SOURCES/0086-Avoid-calling-ldap-functions-without-a-context.patch
@@ -0,0 +1,61 @@
+From 1a4a6e0350e1b95e4c5185fdd299f2c1a2273a94 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Fri, 12 Dec 2014 13:56:51 -0500
+Subject: [PATCH] Avoid calling ldap functions without a context
+
+We need to make sure we have a ld context before we can load the
+configuration, otherwise ldap APIs will abort crashing the KDC.
+
+If we have an issue connecting to LDAP the lcontext will be NULL, but
+we are not checking that condition when we try to refresh the global
+configuration.
+
+https://fedorahosted.org/freeipa/ticket/4810
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ daemons/ipa-kdb/ipa_kdb.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
+index e5101bdd0ad880888fd58fd93a5ca8133868db98..d20b6a1f4666a40f1f0523c5ee9b729e27b666ad 100644
+--- a/daemons/ipa-kdb/ipa_kdb.c
++++ b/daemons/ipa-kdb/ipa_kdb.c
+@@ -224,6 +224,10 @@ static int ipadb_load_global_config(struct ipadb_context *ipactx)
+     int ret;
+     char **authz_data_list;
+ 
++    if (!ipactx || !ipactx->lcontext) {
++        return EINVAL;
++    }
++
+     ret = asprintf(&base, "cn=ipaConfig,cn=etc,%s", ipactx->base);
+     if (ret == -1) {
+         ret = ENOMEM;
+@@ -295,10 +299,19 @@ const struct ipadb_global_config *
+ ipadb_get_global_config(struct ipadb_context *ipactx)
+ {
+     time_t now = 0;
++    int ret;
+ 
+-    if (time(&now) != (time_t)-1
+-        && now - ipactx->config.last_update > IPADB_GLOBAL_CONFIG_CACHE_TIME)
+-        ipadb_load_global_config(ipactx);
++    if (time(&now) != (time_t)-1 &&
++        now - ipactx->config.last_update > IPADB_GLOBAL_CONFIG_CACHE_TIME) {
++        if (!ipactx->lcontext) {
++            ret = ipadb_get_connection(ipactx);
++            if (ret != 0)
++                return NULL;
++        }
++        ret = ipadb_load_global_config(ipactx);
++        if (ret != 0)
++            return NULL;
++    }
+ 
+     return &ipactx->config;
+ }
+-- 
+2.1.0
+
diff --git a/SOURCES/0087-Remove-the-removal-of-the-ccache.patch b/SOURCES/0087-Remove-the-removal-of-the-ccache.patch
new file mode 100644
index 0000000..0a025b1
--- /dev/null
+++ b/SOURCES/0087-Remove-the-removal-of-the-ccache.patch
@@ -0,0 +1,38 @@
+From 86509bce6c14f4b7c791e0de2494c3df2f0aba2d Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 16 Dec 2014 14:47:42 -0500
+Subject: [PATCH] Remove the removal of the ccache
+
+It is not necessary to remove the ccache on upgrades on modern IPA
+servers, even if the ccache contains stale data either it is re-initialized by
+mod_auth_kerb or a new ccache collection is created (if completely unrelated
+credentials were present), at least when using DIR or keyring ccaches.
+
+This line causes wrong SELinux labels to be set in the kernel keyring on
+uprades, which the cause the apache server to fail to use th ccache.
+
+https://fedorahosted.org/freeipa/ticket/4815
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ install/tools/ipa-upgradeconfig | 1 -
+ 1 file changed, 1 deletion(-)
+ mode change 100644 => 100755 install/tools/ipa-upgradeconfig
+
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+old mode 100644
+new mode 100755
+index 6b687fbd73d01f6574cd8ea3193cedba4d5c0e67..005f3a72df115e63c81a7ca8825fb12cac0a5f81
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -1382,7 +1382,6 @@ def main():
+         fstore.restore_file(removed_sysconfig_file)
+ 
+     http = httpinstance.HTTPInstance(fstore)
+-    http.remove_httpd_ccache()
+     http.configure_selinux_for_httpd()
+     http.change_mod_nss_port_from_http()
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0088-Fix-Upgrade-forwardzones-zones-after-adding-newer-re.patch b/SOURCES/0088-Fix-Upgrade-forwardzones-zones-after-adding-newer-re.patch
new file mode 100644
index 0000000..0c36e4f
--- /dev/null
+++ b/SOURCES/0088-Fix-Upgrade-forwardzones-zones-after-adding-newer-re.patch
@@ -0,0 +1,145 @@
+From c04aa879436f190f82265b87255e2a7a27939975 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Tue, 6 Jan 2015 10:36:06 +0100
+Subject: [PATCH] Fix: Upgrade forwardzones zones after adding newer replica
+
+Patch fixes issue, when forwardzones has not been upgraded after adding
+replica >=4.0 into topology with IPA 3.x servers.
+
+Ticket: https://fedorahosted.org/freeipa/ticket/4818
+Reviewed-By: Petr Spacek <pspacek@redhat.com>
+---
+ install/share/dns.ldif           |  2 ++
+ install/updates/40-dns.update    |  1 +
+ ipaserver/install/plugins/dns.py | 65 +++++++++++++++++++++-------------------
+ 3 files changed, 37 insertions(+), 31 deletions(-)
+
+diff --git a/install/share/dns.ldif b/install/share/dns.ldif
+index 2c6050f8598b82e3f0e476d5bff5522f4b54e521..05f5684c385db653a049a15bf490efe0d95e4a38 100644
+--- a/install/share/dns.ldif
++++ b/install/share/dns.ldif
+@@ -2,8 +2,10 @@ dn: cn=dns,$SUFFIX
+ changetype: add
+ objectClass: idnsConfigObject
+ objectClass: nsContainer
++objectClass: ipaConfigObject
+ objectClass: top
+ cn: dns
++ipaConfigString: DNSVersion 1
+ aci: (targetattr = "*")(version 3.0; acl "Allow read access"; allow (read,search,compare) groupdn = "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX" or userattr = "parent[0,1].managedby#GROUPDN";)
+ aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Add DNS entries in a zone";allow (add) userattr = "parent[1].managedby#GROUPDN";)
+ aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Remove DNS entries from a zone";allow (delete) userattr = "parent[1].managedby#GROUPDN";)
+diff --git a/install/updates/40-dns.update b/install/updates/40-dns.update
+index 00fc97fcafc98ee6ef6e0c36b2005635867287b2..251df5907217344fb7bda3adcdef0d5c79c449ab 100644
+--- a/install/updates/40-dns.update
++++ b/install/updates/40-dns.update
+@@ -2,6 +2,7 @@
+ # update DNS container
+ dn: cn=dns, $SUFFIX
+ addifexist: objectClass: idnsConfigObject
++addifexist: objectClass: ipaConfigObject
+ addifexist: aci:'(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Add DNS entries in a zone";allow (add) userattr = "parent[1].managedby#GROUPDN";)'
+ addifexist: aci:'(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Remove DNS entries from a zone";allow (delete) userattr = "parent[1].managedby#GROUPDN";)'
+ addifexist: aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord || tlsarecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)'
+diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py
+index 62cf588d27155acb03026f69ea09ff15582d26dc..ea4aec9741e4714cacdb677bd850730462623fa7 100644
+--- a/ipaserver/install/plugins/dns.py
++++ b/ipaserver/install/plugins/dns.py
+@@ -18,6 +18,7 @@
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+ import ldap as _ldap
++import re
+ import traceback
+ import time
+ 
+@@ -144,32 +145,6 @@ class update_dns_limits(PostUpdate):
+ api.register(update_dns_limits)
+ 
+ 
+-class update_check_forwardzones(PreSchemaUpdate):
+-    """
+-    Check if the idnsforwardzone objectclass is in LDAP schema.
+-    If not update is required (update_to_forward_zones), set sysupgrade state
+-    'update_to_forward_zones' to True
+-    """
+-
+-    def execute(self, **options):
+-        state = sysupgrade.get_upgrade_state('dns', 'update_to_forward_zones')
+-        if state is False:
+-            # no upgrade is needed
+-            return (False, False, [])
+-        ldap = self.obj.backend
+-        if not dns_container_exists(ldap):  # No DNS installed
+-            return (False, False, [])
+-        result = ldap.schema.get_obj(_ldap.schema.models.ObjectClass, 'idnsforwardzone')
+-        if result is None:
+-            sysupgrade.set_upgrade_state('dns', 'update_to_forward_zones', True)
+-            self.log.info('Prepared upgrade to forward zones')
+-        else:
+-            sysupgrade.set_upgrade_state('dns', 'update_to_forward_zones', False)
+-        return (False, False, [])
+-
+-api.register(update_check_forwardzones)
+-
+-
+ class update_master_to_dnsforwardzones(PostUpdate):
+     """
+     Update all zones to meet requirements in the new FreeIPA versions
+@@ -188,10 +163,41 @@ class update_master_to_dnsforwardzones(PostUpdate):
+ 
+     def execute(self, **options):
+         ldap = self.obj.backend
+-        if not sysupgrade.get_upgrade_state('dns', 'update_to_forward_zones'):
+-            # forward zones was tranformed before, nothing to do
++        # check LDAP if forwardzones already uses new semantics
++        dns_container_dn = DN(api.env.container_dns, api.env.basedn)
++        try:
++            container_entry = ldap.get_entry(dns_container_dn)
++        except errors.NotFound:
++            # DNS container not found, nothing to upgrade
+             return (False, False, [])
+ 
++        for config_option in container_entry.get("ipaConfigString", []):
++            matched = re.match("^DNSVersion\s+(?P<version>\d+)$",
++                               config_option, flags=re.I)
++            if matched and int(matched.group("version")) >= 1:
++                # forwardzones already uses new semantics,
++                # no upgrade is required
++                return (False, False, [])
++
++        self.log.info('Updating forward zones')
++        # update the DNSVersion, following upgrade can be executed only once
++        container_entry.setdefault(
++            'ipaConfigString', []).append(u"DNSVersion 1")
++        ldap.update_entry(container_entry)
++
++        # Updater in IPA version from 4.0 to 4.1.2 doesn't work well, this
++        # should detect if update in past has been executed, and set proper
++        # DNSVersion into LDAP
++        try:
++            fwzones = api.Command.dnsforwardzone_find()['result']
++        except errors.NotFound:
++            # No forwardzones found, update probably has not been executed yet
++            pass
++        else:
++            if fwzones:
++                # fwzones exist, do not execute upgrade again
++                return (False, False, [])
++
+         try:
+             # raw values are required to store into ldif
+             zones = api.Command.dnszone_find(all=True,
+@@ -345,9 +351,6 @@ class update_master_to_dnsforwardzones(PostUpdate):
+                 self.log.info('Zone %s was sucessfully transformed to forward zone',
+                               zone['idnsname'][0])
+ 
+-
+-        sysupgrade.set_upgrade_state('dns', 'update_to_forward_zones', False)
+-
+         return (False, False, [])
+ 
+ api.register(update_master_to_dnsforwardzones)
+-- 
+2.1.0
+
diff --git a/SOURCES/0089-Fix-zone-find-during-forwardzone-upgrade.patch b/SOURCES/0089-Fix-zone-find-during-forwardzone-upgrade.patch
new file mode 100644
index 0000000..327daa9
--- /dev/null
+++ b/SOURCES/0089-Fix-zone-find-during-forwardzone-upgrade.patch
@@ -0,0 +1,36 @@
+From 1f1c7156564e7d7c2183e54811c69bc74ff21a98 Mon Sep 17 00:00:00 2001
+From: Martin Basti <mbasti@redhat.com>
+Date: Wed, 7 Jan 2015 13:21:04 +0100
+Subject: [PATCH] Fix zone find during forwardzone upgrade
+
+https://fedorahosted.org/freeipa/ticket/4818
+
+Reviewed-By: Petr Spacek <pspacek@redhat.com>
+---
+ ipaserver/install/plugins/dns.py | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py
+index ea4aec9741e4714cacdb677bd850730462623fa7..aa7bf5f0bbc0db6f10f047f390246cfbfda32b73 100644
+--- a/ipaserver/install/plugins/dns.py
++++ b/ipaserver/install/plugins/dns.py
+@@ -198,12 +198,16 @@ class update_master_to_dnsforwardzones(PostUpdate):
+                 # fwzones exist, do not execute upgrade again
+                 return (False, False, [])
+ 
++        zones = []
+         try:
+             # raw values are required to store into ldif
+             zones = api.Command.dnszone_find(all=True,
+                                              raw=True,
+                                              sizelimit=0)['result']
+         except errors.NotFound:
++            pass
++
++        if not zones:
+             self.log.info('No DNS zone to update found')
+             return (False, False, [])
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0090-migrate-ds-fix-compat-plugin-check.patch b/SOURCES/0090-migrate-ds-fix-compat-plugin-check.patch
new file mode 100644
index 0000000..79e57f9
--- /dev/null
+++ b/SOURCES/0090-migrate-ds-fix-compat-plugin-check.patch
@@ -0,0 +1,44 @@
+From b196396dad7ef31d98d2937f80b629ecf9489c38 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 12 Jan 2015 13:08:11 +0100
+Subject: [PATCH] migrate-ds: fix compat plugin check
+
+After ACI refactoring, admin cannot read Schema Compatibility plugin configuration and therefore migrade-ds won't find if compat plugin is enabled.
+
+Now the check si done by looking if cn=compat subtree is present.
+
+https://fedorahosted.org/freeipa/ticket/4825
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/plugins/migration.py | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
+index fa3d512bf1434c7d349713f78c292b481021303a..cd1fa73f8f514fa5441bea482199291450c87008 100644
+--- a/ipalib/plugins/migration.py
++++ b/ipalib/plugins/migration.py
+@@ -140,7 +140,6 @@ _dn_err_msg = _('Malformed DN')
+ 
+ _supported_schemas = (u'RFC2307bis', u'RFC2307')
+ 
+-_compat_dn = DN(('cn', 'Schema Compatibility'), ('cn', 'plugins'), ('cn', 'config'))
+ 
+ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs):
+     assert isinstance(dn, DN)
+@@ -879,10 +878,8 @@ can use their Kerberos accounts.''')
+         #check whether the compat plugin is enabled
+         if not options.get('compat'):
+             try:
+-                check_compat = ldap.get_entry(_compat_dn)
+-                if check_compat is not None and \
+-                        check_compat.get('nsslapd-pluginenabled', [''])[0].lower() == 'on':
+-                    return dict(result={}, failed={}, enabled=True, compat=False)
++                ldap.get_entry(DN(('cn', 'compat'), (api.env.basedn)))
++                return dict(result={}, failed={}, enabled=True, compat=False)
+             except errors.NotFound:
+                 pass
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0091-rpcclient-use-json_encode_binary-for-verbose-output.patch b/SOURCES/0091-rpcclient-use-json_encode_binary-for-verbose-output.patch
new file mode 100644
index 0000000..d9a2916
--- /dev/null
+++ b/SOURCES/0091-rpcclient-use-json_encode_binary-for-verbose-output.patch
@@ -0,0 +1,52 @@
+From 83caef88e10d30e001506c3792852b42ad97e8ab Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 12 Jan 2015 14:18:49 +0100
+Subject: [PATCH] rpcclient: use json_encode_binary for verbose output
+
+`json.dumps` is not able to process some IPA's object types and therefore requires to preprocess it with `json_encode_binary` call. This step was not used in  rpcclient's verbose output.
+
+https://fedorahosted.org/freeipa/ticket/4773
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ ipalib/rpc.py | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/ipalib/rpc.py b/ipalib/rpc.py
+index 806f6bb9adf004660c9cb285cf31b09a988afa93..05ef3143324b0f6d260678ad354464511f907eac 100644
+--- a/ipalib/rpc.py
++++ b/ipalib/rpc.py
+@@ -967,6 +967,7 @@ class JSONServerProxy(object):
+     def __request(self, name, args):
+         payload = {'method': unicode(name), 'params': args, 'id': 0}
+         version = args[1].get('version', VERSION_WITHOUT_CAPABILITIES)
++        payload = json_encode_binary(payload, version)
+ 
+         if self.__verbose >= 2:
+             root_logger.info('Request: %s',
+@@ -975,7 +976,7 @@ class JSONServerProxy(object):
+         response = self.__transport.request(
+             self.__host,
+             self.__handler,
+-            json.dumps(json_encode_binary(payload, version)),
++            json.dumps(payload),
+             verbose=self.__verbose >= 3,
+         )
+ 
+@@ -985,8 +986,11 @@ class JSONServerProxy(object):
+             raise JSONError(str(e))
+ 
+         if self.__verbose >= 2:
+-            root_logger.info('Response: %s',
+-                             json.dumps(response, sort_keys=True, indent=4))
++            root_logger.info(
++                'Response: %s',
++                json.dumps(json_encode_binary(response, version),
++                           sort_keys=True, indent=4)
++            )
+         error = response.get('error')
+         if error:
+             try:
+-- 
+2.1.0
+
diff --git a/SOURCES/0092-Remove-ipanttrustauthincoming-ipanttrustauthoutgoing.patch b/SOURCES/0092-Remove-ipanttrustauthincoming-ipanttrustauthoutgoing.patch
new file mode 100644
index 0000000..f06b63a
--- /dev/null
+++ b/SOURCES/0092-Remove-ipanttrustauthincoming-ipanttrustauthoutgoing.patch
@@ -0,0 +1,29 @@
+From 6fdff1b5891c9e8984dcaa265491c3cc9600aa0d Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Tue, 13 Jan 2015 13:23:16 +0100
+Subject: [PATCH] Remove ipanttrustauthincoming/ipanttrustauthoutgoing from ipa
+ trust-add output.
+
+https://fedorahosted.org/freeipa/ticket/4787
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipalib/plugins/trust.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
+index 736cb6f573f9a18eca882db136133205c583b67d..22fbb9c7cb1d3a71f65e24d8d3bc27f62d5a44a5 100644
+--- a/ipalib/plugins/trust.py
++++ b/ipalib/plugins/trust.py
+@@ -508,6 +508,8 @@ sides.
+             result['verified'])]
+ 
+         del result['verified']
++        result['result'].pop('ipanttrustauthoutgoing', None)
++        result['result'].pop('ipanttrustauthincoming', None)
+ 
+         return result
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0093-Abort-backup-restoration-on-not-matching-host.patch b/SOURCES/0093-Abort-backup-restoration-on-not-matching-host.patch
new file mode 100644
index 0000000..e479b01
--- /dev/null
+++ b/SOURCES/0093-Abort-backup-restoration-on-not-matching-host.patch
@@ -0,0 +1,36 @@
+From fe282611598ebdd97e9ca64d4da43c8916b5eb4a Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Sun, 11 Jan 2015 18:45:11 -0500
+Subject: [PATCH] Abort backup restoration on not matching host.
+
+When restoring backup on master other than it was created there is high risk
+of unexpected and hard-to-debug behavior. Refuse such restore.
+
+https://fedorahosted.org/freeipa/ticket/4823
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 097703938a7ba3820f4acae2148760146464fa08..3b4cf6a7c05245076abde7a9c13e53bc9636b69a 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -249,11 +249,9 @@ class Restore(admintool.AdminTool):
+                 (options.instance or options.backend)):
+                 raise admintool.ScriptError('Restore must be in data-only mode when restoring a specific instance or backend.')
+             if self.backup_host != api.env.host:
+-                self.log.warning('Host name %s does not match backup name %s' %
++                raise admintool.ScriptError(
++                    'Host name %s does not match backup name %s' %
+                     (api.env.host, self.backup_host))
+-                if (not options.unattended and
+-                    not user_input("Continue to restore?", False)):
+-                    raise admintool.ScriptError("Aborted")
+             if self.backup_ipa_version != str(version.VERSION):
+                 self.log.warning(
+                     "Restoring data from a different release of IPA.\n"
+-- 
+2.1.0
+
diff --git a/SOURCES/0094-Fix-ipa-restore-on-systems-without-IPA-installed.patch b/SOURCES/0094-Fix-ipa-restore-on-systems-without-IPA-installed.patch
new file mode 100644
index 0000000..a95caa7
--- /dev/null
+++ b/SOURCES/0094-Fix-ipa-restore-on-systems-without-IPA-installed.patch
@@ -0,0 +1,34 @@
+From ce55779854e90bb03230dc010092dddf1e9fde67 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 12 Jan 2015 17:03:22 +0000
+Subject: [PATCH] Fix ipa-restore on systems without IPA installed
+
+https://fedorahosted.org/freeipa/ticket/4824
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 3b4cf6a7c05245076abde7a9c13e53bc9636b69a..f3a60fcc7a60c38c0d2ae1e52fc4fe7712411ec1 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -692,8 +692,12 @@ class Restore(admintool.AdminTool):
+         cainstance.stop_tracking_certificates(
+             dogtag.configured_constants())
+         httpinstance.HTTPInstance().stop_tracking_certificates()
+-        dsinstance.DsInstance().stop_tracking_certificates(
+-            realm_to_serverid(api.env.realm))
++        try:
++            dsinstance.DsInstance().stop_tracking_certificates(
++                realm_to_serverid(api.env.realm))
++        except OSError:
++            # When IPA is not installed, DS NSS DB does not exist
++            pass
+ 
+         for basename in ('cert8.db', 'key3.db', 'secmod.db', 'pwdfile.txt'):
+             filename = os.path.join(paths.IPA_NSSDB_DIR, basename)
+-- 
+2.1.0
+
diff --git a/SOURCES/0095-Remove-RUV-from-LDIF-files-before-using-them-in-ipa-.patch b/SOURCES/0095-Remove-RUV-from-LDIF-files-before-using-them-in-ipa-.patch
new file mode 100644
index 0000000..28976ce
--- /dev/null
+++ b/SOURCES/0095-Remove-RUV-from-LDIF-files-before-using-them-in-ipa-.patch
@@ -0,0 +1,76 @@
+From 761257efc18f9f5efedae110ba8cfa5feeb9f8f7 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 12 Jan 2015 15:37:33 +0000
+Subject: [PATCH] Remove RUV from LDIF files before using them in ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4822
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 36 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index f3a60fcc7a60c38c0d2ae1e52fc4fe7712411ec1..cd98d07f5f7c7b2ea1b1fef9a272229475efcdc9 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -24,6 +24,7 @@ import tempfile
+ import time
+ import pwd
+ from ConfigParser import SafeConfigParser
++import ldif
+ 
+ from ipalib import api, errors
+ from ipapython import version, ipautil, certdb, dogtag
+@@ -94,6 +95,32 @@ def decrypt_file(tmpdir, filename, keyring):
+     return dest
+ 
+ 
++class RemoveRUVParser(ldif.LDIFParser):
++    def __init__(self, input_file, writer, logger):
++        ldif.LDIFParser.__init__(self, input_file)
++        self.writer = writer
++        self.log = logger
++
++    def handle(self, dn, entry):
++        objectclass = None
++        nsuniqueid = None
++
++        for name, value in entry.iteritems():
++            name = name.lower()
++            if name == 'objectclass':
++                objectclass = [x.lower() for x in value]
++            elif name == 'nsuniqueid':
++                nsuniqueid = [x.lower() for x in value]
++
++        if (objectclass and nsuniqueid and
++            'nstombstone' in objectclass and
++            'ffffffff-ffffffff-ffffffff-ffffffff' in nsuniqueid):
++            self.log.debug("Removing RUV entry %s", dn)
++            return
++
++        self.writer.unparse(dn, entry)
++
++
+ class Restore(admintool.AdminTool):
+     command_name = 'ipa-restore'
+     log_file_name = paths.IPARESTORE_LOG
+@@ -447,7 +474,14 @@ class Restore(admintool.AdminTool):
+         dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))
+ 
+         ldifname = '%s-%s.ldif' % (instance, backend)
+-        ldiffile = os.path.join(self.dir, ldifname)
++        srcldiffile = os.path.join(self.dir, ldifname)
++        ldiffile = '%s.noruv' % srcldiffile
++
++        with open(ldiffile, 'wb') as out_file:
++            ldif_writer = ldif.LDIFWriter(out_file)
++            with open(srcldiffile, 'rb') as in_file:
++                ldif_parser = RemoveRUVParser(in_file, ldif_writer, self.log)
++                ldif_parser.parse()
+ 
+         if online:
+             conn = self.get_connection()
+-- 
+2.1.0
+
diff --git a/SOURCES/0096-Fix-CA-certificate-renewal-syslog-alert.patch b/SOURCES/0096-Fix-CA-certificate-renewal-syslog-alert.patch
new file mode 100644
index 0000000..b1e3792
--- /dev/null
+++ b/SOURCES/0096-Fix-CA-certificate-renewal-syslog-alert.patch
@@ -0,0 +1,28 @@
+From 88ec82165561af0d14ec07a82f37156c5d2fa0da Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 8 Jan 2015 16:01:42 +0000
+Subject: [PATCH] Fix CA certificate renewal syslog alert
+
+https://fedorahosted.org/freeipa/ticket/4820
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/certmonger/dogtag-ipa-ca-renew-agent-submit | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index c63c0c2c5f863e05cafad293a60d9157c732e7ad..3c6e8175c337f65046f8631f4393aecfbf207f4d 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -403,7 +403,7 @@ def renew_ca_cert():
+ 
+     if state == 'retrieve':
+         result = call_handler(retrieve_cert)
+-        if result[0] == WAIT_WITH_DELAY and not is_self_signed:
++        if result[0] == REJECTED and not is_self_signed:
+             syslog.syslog(syslog.LOG_ALERT,
+                           "IPA CA certificate is about to expire, "
+                           "use ipa-cacert-manage to renew it")
+-- 
+2.1.0
+
diff --git a/SOURCES/0097-Do-not-crash-on-unknown-services-in-installutils.sto.patch b/SOURCES/0097-Do-not-crash-on-unknown-services-in-installutils.sto.patch
new file mode 100644
index 0000000..f876241
--- /dev/null
+++ b/SOURCES/0097-Do-not-crash-on-unknown-services-in-installutils.sto.patch
@@ -0,0 +1,46 @@
+From 3229a4c7ae1167103e954d5101bac1d56b28ce0d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 13 Jan 2015 10:59:08 +0000
+Subject: [PATCH] Do not crash on unknown services in
+ installutils.stopped_service
+
+https://fedorahosted.org/freeipa/ticket/4835
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipaserver/install/installutils.py | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
+index 0ab09abea03c8b317e7d00466e127cda00ed17d9..e40535d4822f603ea432094c85396c59222dbe5c 100644
+--- a/ipaserver/install/installutils.py
++++ b/ipaserver/install/installutils.py
+@@ -870,20 +870,22 @@ def stopped_service(service, instance_name=""):
+                       'the next set of commands is being executed.', service,
+                       log_instance_name)
+ 
++    service_obj = services.service(service)
++
+     # Figure out if the service is running, if not, yield
+-    if not services.knownservices[service].is_running(instance_name):
++    if not service_obj.is_running(instance_name):
+         root_logger.debug('Service %s%s is not running, continue.', service,
+                           log_instance_name)
+         yield
+     else:
+         # Stop the service, do the required stuff and start it again
+         root_logger.debug('Stopping %s%s.', service, log_instance_name)
+-        services.knownservices[service].stop(instance_name)
++        service_obj.stop(instance_name)
+         try:
+             yield
+         finally:
+             root_logger.debug('Starting %s%s.', service, log_instance_name)
+-            services.knownservices[service].start(instance_name)
++            service_obj.start(instance_name)
+ 
+ def check_entropy():
+     '''
+-- 
+2.1.0
+
diff --git a/SOURCES/0098-Restart-dogtag-when-its-server-certificate-is-renewe.patch b/SOURCES/0098-Restart-dogtag-when-its-server-certificate-is-renewe.patch
new file mode 100644
index 0000000..e8be4da
--- /dev/null
+++ b/SOURCES/0098-Restart-dogtag-when-its-server-certificate-is-renewe.patch
@@ -0,0 +1,65 @@
+From 19494c2409d40fc25387ddafe94c59ef09f68a86 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 6 Jan 2015 13:08:54 +0000
+Subject: [PATCH] Restart dogtag when its server certificate is renewed
+
+https://fedorahosted.org/freeipa/ticket/4803
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/tools/ipa-upgradeconfig | 6 +++---
+ ipaserver/install/cainstance.py | 7 ++++---
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index 005f3a72df115e63c81a7ca8825fb12cac0a5f81..b00161d58418d6205c0ba0db0260af272ec96130 100755
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -778,7 +778,7 @@ def certificate_renewal_update(ca):
+     dogtag_constants = dogtag.configured_constants()
+ 
+     # bump version when requests is changed
+-    version = 2
++    version = 3
+     requests = (
+         (
+             dogtag_constants.ALIAS_DIR,
+@@ -824,8 +824,8 @@ def certificate_renewal_update(ca):
+             dogtag_constants.ALIAS_DIR,
+             'Server-Cert cert-pki-ca',
+             'dogtag-ipa-renew-agent',
+-            None,
+-            None,
++            'stop_pkicad',
++            'renew_ca_cert',
+             None,
+         ),
+     )
+diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
+index ac494917744ce0fa2d8e38ce5ce9dab6b24bdebf..aac7f4c7ccbad5a68bfd9756c7f7638416e3f6a0 100644
+--- a/ipaserver/install/cainstance.py
++++ b/ipaserver/install/cainstance.py
+@@ -1534,16 +1534,17 @@ class CAInstance(service.Service):
+         done by the renewal script, renew_ca_cert once all the subsystem
+         certificates are renewed.
+         """
++        nickname = 'Server-Cert cert-pki-ca'
+         pin = self.__get_ca_pin()
+         try:
+             certmonger.dogtag_start_tracking(
+                 ca='dogtag-ipa-renew-agent',
+-                nickname='Server-Cert cert-pki-ca',
++                nickname=nickname,
+                 pin=pin,
+                 pinfile=None,
+                 secdir=self.dogtag_constants.ALIAS_DIR,
+-                pre_command=None,
+-                post_command=None)
++                pre_command='stop_pkicad',
++                post_command='renew_ca_cert "%s"' % nickname)
+         except RuntimeError, e:
+             root_logger.error(
+                 "certmonger failed to start tracking certificate: %s" % e)
+-- 
+2.1.0
+
diff --git a/SOURCES/0099-Make-certificate-renewal-process-synchronized.patch b/SOURCES/0099-Make-certificate-renewal-process-synchronized.patch
new file mode 100644
index 0000000..3275e64
--- /dev/null
+++ b/SOURCES/0099-Make-certificate-renewal-process-synchronized.patch
@@ -0,0 +1,581 @@
+From c0d13f5e58cb84eb3162aec1c2202329230c120d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Thu, 8 Jan 2015 09:06:46 +0000
+Subject: [PATCH] Make certificate renewal process synchronized
+
+Synchronization is achieved using a global renewal lock.
+
+https://fedorahosted.org/freeipa/ticket/4803
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ freeipa.spec.in                                    |   1 +
+ install/certmonger/Makefile.am                     |   1 +
+ .../certmonger/dogtag-ipa-ca-renew-agent-submit    |   4 +-
+ install/certmonger/ipa-server-guard                |  55 +++++++++++
+ install/restart_scripts/renew_ca_cert              |  11 ++-
+ install/restart_scripts/renew_ra_cert              |  11 ++-
+ install/restart_scripts/restart_dirsrv             |  10 +-
+ install/restart_scripts/restart_httpd              |  10 +-
+ install/restart_scripts/stop_pkicad                |   4 +
+ install/tools/ipa-upgradeconfig                    |   3 +
+ ipaplatform/base/paths.py                          |   2 +
+ ipaserver/install/cainstance.py                    |  38 ++++++++
+ ipaserver/install/certs.py                         | 104 +++++++++++++++++++++
+ ipaserver/install/httpinstance.py                  |  42 +++++++++
+ 14 files changed, 290 insertions(+), 6 deletions(-)
+ create mode 100755 install/certmonger/ipa-server-guard
+
+diff --git a/freeipa.spec.in b/freeipa.spec.in
+index 1c975b3912d0a7470a32f1b7e314cfde74446e85..b72d05a4c16d58144207233f2078a336b087604d 100644
+--- a/freeipa.spec.in
++++ b/freeipa.spec.in
+@@ -650,6 +650,7 @@ fi
+ %{_sbindir}/ipa-advise
+ %{_sbindir}/ipa-cacert-manage
+ %{_libexecdir}/certmonger/dogtag-ipa-ca-renew-agent-submit
++%{_libexecdir}/certmonger/ipa-server-guard
+ %{_libexecdir}/ipa-otpd
+ %dir %{_libexecdir}/ipa
+ %{_libexecdir}/ipa/ipa-dnskeysyncd
+diff --git a/install/certmonger/Makefile.am b/install/certmonger/Makefile.am
+index ef6a0a635eed77a582bf0c43b40593678326c8eb..2dc476f188cb284f60a284a6cf90cf3c1ee8692f 100644
+--- a/install/certmonger/Makefile.am
++++ b/install/certmonger/Makefile.am
+@@ -3,6 +3,7 @@ NULL =
+ appdir = $(libexecdir)/certmonger/
+ app_SCRIPTS =					\
+ 	dogtag-ipa-ca-renew-agent-submit	\
++	ipa-server-guard			\
+ 	$(NULL)
+ 
+ EXTRA_DIST =				\
+diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+index 3c6e8175c337f65046f8631f4393aecfbf207f4d..7b91fc61148912c77d0ae962b3847d73e8d0720e 100755
+--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
++++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+@@ -38,7 +38,7 @@ from ipapython.dn import DN
+ from ipalib import api, errors, pkcs10, x509
+ from ipaplatform.paths import paths
+ from ipaserver.plugins.ldap2 import ldap2
+-from ipaserver.install import cainstance
++from ipaserver.install import cainstance, certs
+ 
+ # This is a certmonger CA helper script for IPA CA subsystem cert renewal. See
+ # https://git.fedorahosted.org/cgit/certmonger.git/tree/doc/submit.txt for more
+@@ -437,6 +437,7 @@ def main():
+         return OPERATION_NOT_SUPPORTED_BY_HELPER
+ 
+     tmpdir = tempfile.mkdtemp(prefix="tmp-")
++    certs.renewal_lock.acquire()
+     try:
+         principal = str('host/%s@%s' % (api.env.host, api.env.realm))
+         ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir, principal)
+@@ -456,6 +457,7 @@ def main():
+             print item
+         return res[0]
+     finally:
++        certs.renewal_lock.release()
+         shutil.rmtree(tmpdir)
+ 
+ try:
+diff --git a/install/certmonger/ipa-server-guard b/install/certmonger/ipa-server-guard
+new file mode 100755
+index 0000000000000000000000000000000000000000..5e31d89b7731a2bafb85cd7fed4a4b9bd6709a2a
+--- /dev/null
++++ b/install/certmonger/ipa-server-guard
+@@ -0,0 +1,55 @@
++#!/usr/bin/python2 -E
++#
++# Authors:
++#   Jan Cholasta <jcholast@redhat.com>
++#
++# Copyright (C) 2015  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 os
++# Prevent garbage from readline on standard output
++# (see https://fedorahosted.org/freeipa/ticket/4064)
++if not os.isatty(1):
++    os.environ['TERM'] = 'dumb'
++import sys
++import syslog
++import traceback
++
++from ipapython import ipautil
++from ipaserver.install import certs
++
++
++def main():
++    if len(sys.argv) < 2:
++        raise RuntimeError("Not enough arguments")
++
++    with certs.renewal_lock:
++        stdout, stderr, rc = ipautil.run(sys.argv[1:], raiseonerr=False,
++                                         env=os.environ)
++        sys.stdout.write(stdout)
++        sys.stdout.flush()
++        sys.stderr.write(stderr)
++        sys.stderr.flush()
++
++    return rc
++
++
++try:
++    sys.exit(main())
++except Exception, e:
++    syslog.syslog(syslog.LOG_ERR, traceback.format_exc())
++    print "Internal error"
++    sys.exit(3)
+diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert
+index 2ad2038703a74fe3549708549091633b35695907..261c424381d8246ab2ca6da2689a7f90010b2a97 100644
+--- a/install/restart_scripts/renew_ca_cert
++++ b/install/restart_scripts/renew_ca_cert
+@@ -35,7 +35,8 @@ from ipaserver.plugins.ldap2 import ldap2
+ from ipaplatform import services
+ from ipaplatform.paths import paths
+ 
+-def main():
++
++def _main():
+     nickname = sys.argv[1]
+ 
+     api.bootstrap(context='restart')
+@@ -209,6 +210,14 @@ def main():
+         syslog.syslog(
+             syslog.LOG_NOTICE, "Started %s" % dogtag_service.service_name)
+ 
++
++def main():
++    try:
++        _main()
++    finally:
++        certs.renewal_lock.release('renew_ca_cert')
++
++
+ try:
+     main()
+ except Exception:
+diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert
+index 6d4b81a5393dcaced56a8335cd0ec6b7a994acdc..7dae3562380e919b2cc5f53825820291fc93fdc5 100644
+--- a/install/restart_scripts/renew_ra_cert
++++ b/install/restart_scripts/renew_ra_cert
+@@ -32,9 +32,10 @@ from ipaserver.install import certs, cainstance
+ from ipaplatform import services
+ from ipaplatform.paths import paths
+ 
+-nickname = 'ipaCert'
+ 
+-def main():
++def _main():
++    nickname = 'ipaCert'
++
+     api.bootstrap(context='restart')
+     api.finalize()
+ 
+@@ -68,6 +69,12 @@ def main():
+     else:
+         syslog.syslog(syslog.LOG_NOTICE, "Restarted httpd")
+ 
++
++def main():
++    with certs.renewal_lock:
++        _main()
++
++
+ try:
+     main()
+ except Exception:
+diff --git a/install/restart_scripts/restart_dirsrv b/install/restart_scripts/restart_dirsrv
+index 837378191765babbcb4b09afec37ab82cb675e28..723644215cb76aa83b2d8eee70070b979986c0cc 100644
+--- a/install/restart_scripts/restart_dirsrv
++++ b/install/restart_scripts/restart_dirsrv
+@@ -24,8 +24,10 @@ import syslog
+ import traceback
+ from ipalib import api
+ from ipaplatform import services
++from ipaserver.install import certs
+ 
+-def main():
++
++def _main():
+     try:
+         instance = sys.argv[1]
+     except IndexError:
+@@ -41,6 +43,12 @@ def main():
+     except Exception, e:
+         syslog.syslog(syslog.LOG_ERR, "Cannot restart dirsrv (instance: '%s'): %s" % (instance, str(e)))
+ 
++
++def main():
++    with certs.renewal_lock:
++        _main()
++
++
+ try:
+     main()
+ except Exception:
+diff --git a/install/restart_scripts/restart_httpd b/install/restart_scripts/restart_httpd
+index e3ef73c4fad29bd0ca4dda167352ad023d5ff31f..f060a3091d439b7811d680b75d9995f5cc391e53 100644
+--- a/install/restart_scripts/restart_httpd
++++ b/install/restart_scripts/restart_httpd
+@@ -22,8 +22,10 @@
+ import syslog
+ import traceback
+ from ipaplatform import services
++from ipaserver.install import certs
+ 
+-def main():
++
++def _main():
+     syslog.syslog(syslog.LOG_NOTICE, 'certmonger restarted httpd')
+ 
+     try:
+@@ -31,6 +33,12 @@ def main():
+     except Exception, e:
+         syslog.syslog(syslog.LOG_ERR, "Cannot restart httpd: %s" % str(e))
+ 
++
++def main():
++    with certs.renewal_lock:
++        _main()
++
++
+ try:
+     main()
+ except Exception:
+diff --git a/install/restart_scripts/stop_pkicad b/install/restart_scripts/stop_pkicad
+index b8866f16edbec8c58327616324357f7f23ba368a..871e5e7616701ef6925fa2725cb1a90ad0aae512 100644
+--- a/install/restart_scripts/stop_pkicad
++++ b/install/restart_scripts/stop_pkicad
+@@ -25,6 +25,8 @@ import traceback
+ from ipapython import dogtag
+ from ipalib import api
+ from ipaplatform import services
++from ipaserver.install import certs
++
+ 
+ def main():
+     api.bootstrap(context='restart')
+@@ -34,6 +36,8 @@ def main():
+     dogtag_service = services.knownservices[configured_constants.SERVICE_NAME]
+     dogtag_instance = configured_constants.PKI_INSTANCE_NAME
+ 
++    certs.renewal_lock.acquire('renew_ca_cert')
++
+     syslog.syslog(syslog.LOG_NOTICE, "Stopping %s" % dogtag_service.service_name)
+     try:
+         dogtag_service.stop(dogtag_instance)
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index b00161d58418d6205c0ba0db0260af272ec96130..3f671c3bd5ebb643201b13b2024447bb1273c292 100755
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -1372,6 +1372,8 @@ def main():
+             )
+         upgrade_pki(ca, fstore)
+ 
++    ca.configure_certmonger_renewal_guard()
++
+     update_dbmodules(api.env.realm)
+     uninstall_ipa_kpasswd()
+ 
+@@ -1384,6 +1386,7 @@ def main():
+     http = httpinstance.HTTPInstance(fstore)
+     http.configure_selinux_for_httpd()
+     http.change_mod_nss_port_from_http()
++    http.configure_certmonger_renewal_guard()
+ 
+     http.stop()
+     update_mod_nss_protocol(http)
+diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
+index 8bfab1bc92f79b5e76555b35a8b646e1ff56f84b..f78c1f940a101038226ff98e229df775028e3bf1 100644
+--- a/ipaplatform/base/paths.py
++++ b/ipaplatform/base/paths.py
+@@ -204,6 +204,7 @@ class BasePathNamespace(object):
+     LIBSOFTHSM2_SO_64 = "/usr/lib64/pkcs11/libsofthsm2.so"
+     DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT = "/usr/libexec/certmonger/dogtag-ipa-ca-renew-agent-submit"
+     DOGTAG_IPA_RENEW_AGENT_SUBMIT = "/usr/libexec/certmonger/dogtag-ipa-renew-agent-submit"
++    IPA_SERVER_GUARD = "/usr/libexec/certmonger/ipa-server-guard"
+     IPA_DNSKEYSYNCD_REPLICA = "/usr/libexec/ipa/ipa-dnskeysync-replica"
+     IPA_DNSKEYSYNCD = "/usr/libexec/ipa/ipa-dnskeysyncd"
+     IPA_ODS_EXPORTER = "/usr/libexec/ipa/ipa-ods-exporter"
+@@ -320,6 +321,7 @@ class BasePathNamespace(object):
+     VAR_OPENDNSSEC_DIR = "/var/opendnssec"
+     OPENDNSSEC_KASP_DB = "/var/opendnssec/kasp.db"
+     VAR_RUN_DIRSRV_DIR = "/var/run/dirsrv"
++    IPA_RENEWAL_LOCK = "/var/run/ipa/renewal.lock"
+     SVC_LIST_FILE = "/var/run/ipa/services.list"
+     IPA_MEMCACHED_DIR = "/var/run/ipa_memcached"
+     VAR_RUN_IPA_MEMCACHED = "/var/run/ipa_memcached/ipa_memcached"
+diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
+index aac7f4c7ccbad5a68bfd9756c7f7638416e3f6a0..13a75bbb568a25d155325e7084406eb19e8ffc92 100644
+--- a/ipaserver/install/cainstance.py
++++ b/ipaserver/install/cainstance.py
+@@ -37,6 +37,8 @@ import stat
+ import syslog
+ import ConfigParser
+ import dbus
++import shlex
++import pipes
+ 
+ from ipapython import dogtag
+ from ipapython.certdb import get_ca_nickname
+@@ -1422,6 +1424,16 @@ class CAInstance(service.Service):
+         if path:
+             iface.remove_known_ca(path)
+ 
++        helper = self.restore_state('certmonger_dogtag_helper')
++        if helper:
++            path = iface.find_ca_by_nickname('dogtag-ipa-renew-agent')
++            if path:
++                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
++                ca_iface = dbus.Interface(ca_obj,
++                                          'org.freedesktop.DBus.Properties')
++                ca_iface.Set('org.fedorahosted.certmonger.ca',
++                             'external-helper', helper)
++
+         cmonger.stop()
+ 
+         # remove CRL files
+@@ -1481,6 +1493,32 @@ class CAInstance(service.Service):
+                 'dogtag-ipa-ca-renew-agent',
+                 paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT, [])
+ 
++        self.configure_certmonger_renewal_guard()
++
++    def configure_certmonger_renewal_guard(self):
++        if not self.is_configured():
++            return
++
++        bus = dbus.SystemBus()
++        obj = bus.get_object('org.fedorahosted.certmonger',
++                             '/org/fedorahosted/certmonger')
++        iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
++        path = iface.find_ca_by_nickname('dogtag-ipa-renew-agent')
++        if path:
++            ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
++            ca_iface = dbus.Interface(ca_obj,
++                                      'org.freedesktop.DBus.Properties')
++            helper = ca_iface.Get('org.fedorahosted.certmonger.ca',
++                                  'external-helper')
++            if helper:
++                args = shlex.split(helper)
++                if args[0] != paths.IPA_SERVER_GUARD:
++                    self.backup_state('certmonger_dogtag_helper', helper)
++                    args = [paths.IPA_SERVER_GUARD] + args
++                    helper = ' '.join(pipes.quote(a) for a in args)
++                    ca_iface.Set('org.fedorahosted.certmonger.ca',
++                                 'external-helper', helper)
++
+     def configure_agent_renewal(self):
+         try:
+             certmonger.dogtag_start_tracking(
+diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
+index 7292cbbe3574f57d32daa6f1e310669486fa5eff..bc7dccf805386e9fa84b58d2ff9346085e1b93b1 100644
+--- a/ipaserver/install/certs.py
++++ b/ipaserver/install/certs.py
+@@ -26,6 +26,10 @@ import xml.dom.minidom
+ import pwd
+ import base64
+ from hashlib import sha1
++import fcntl
++import time
++import datetime
++import ConfigParser as configparser
+ 
+ from ipapython.ipa_log_manager import root_logger
+ from ipapython import dogtag
+@@ -647,3 +651,103 @@ class CertDB(object):
+ 
+     def export_pem_cert(self, nickname, location):
+         return self.nssdb.export_pem_cert(nickname, location)
++
++
++class _CrossProcessLock(object):
++    _DATETIME_FORMAT = '%Y%m%d%H%M%S%f'
++
++    def __init__(self, filename):
++        self._filename = filename
++
++    def __enter__(self):
++        self.acquire()
++
++    def __exit__(self, exc_type, exc_value, traceback):
++        self.release()
++
++    def acquire(self, owner=None):
++        self._do(self._acquire, owner)
++
++    def release(self, owner=None):
++        self._do(self._release, owner)
++
++    def _acquire(self, owner):
++        now = datetime.datetime.utcnow()
++
++        if self._locked and now >= self._expire:
++            self._locked = False
++
++        if self._locked:
++            return False
++
++        self._locked = True
++        self._owner = owner
++        self._expire = now + datetime.timedelta(hours=1)
++
++        return True
++
++    def _release(self, owner):
++        if not self._locked or self._owner != owner:
++            raise RuntimeError("lock not acquired by %s" % owner)
++
++        self._locked = False
++        self._owner = None
++        self._expire = None
++
++        return True
++
++    def _do(self, func, owner):
++        if owner is None:
++            owner = '%s[%s]' % (os.path.basename(sys.argv[0]), os.getpid())
++
++        while True:
++            with open(self._filename, 'a+') as f:
++                fcntl.flock(f, fcntl.LOCK_EX)
++
++                f.seek(0)
++                self._read(f)
++
++                if func(owner):
++                    f.seek(0)
++                    f.truncate()
++                    self._write(f)
++                    return
++
++            time.sleep(10)
++
++    def _read(self, fileobj):
++        p = configparser.RawConfigParser()
++        p.readfp(fileobj)
++
++        try:
++            self._locked = p.getboolean('lock', 'locked')
++
++            if self._locked:
++                self._owner = p.get('lock', 'owner')
++
++                expire = p.get('lock', 'expire')
++                try:
++                    self._expire = datetime.datetime.strptime(
++                        expire, self._DATETIME_FORMAT)
++                except ValueError:
++                    raise configparser.Error
++        except configparser.Error:
++            self._locked = False
++            self._owner = None
++            self._expire = None
++
++    def _write(self, fileobj):
++        p = configparser.RawConfigParser()
++        p.add_section('lock')
++
++        locked = '1' if self._locked else '0'
++        p.set('lock', 'locked', locked)
++
++        if self._locked:
++            expire = self._expire.strftime(self._DATETIME_FORMAT)
++            p.set('lock', 'owner', self._owner)
++            p.set('lock', 'expire', expire)
++
++        p.write(fileobj)
++
++renewal_lock = _CrossProcessLock(paths.IPA_RENEWAL_LOCK)
+diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
+index f9e020039734c7ff61e06ead0e30fb28701d6fc8..2fb315b6b822343860a9c31b016d6a0a22388488 100644
+--- a/ipaserver/install/httpinstance.py
++++ b/ipaserver/install/httpinstance.py
+@@ -23,6 +23,9 @@ import tempfile
+ import pwd
+ import shutil
+ import re
++import dbus
++import shlex
++import pipes
+ 
+ import service
+ import certs
+@@ -121,6 +124,9 @@ class HTTPInstance(service.Service):
+         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
+         self.step("adding URL rewriting rules", self.__add_include)
+         self.step("configuring httpd", self.__configure_http)
++        if self.ca_is_configured:
++            self.step("configure certmonger for renewals",
++                      self.configure_certmonger_renewal_guard)
+         self.step("setting up ssl", self.__setup_ssl)
+         self.step("importing CA certificates from LDAP", self.__import_ca_certs)
+         if autoconfig:
+@@ -221,6 +227,27 @@ class HTTPInstance(service.Service):
+         if installutils.update_file(paths.HTTPD_NSS_CONF, '</VirtualHost>', 'Include conf.d/ipa-rewrite.conf\n</VirtualHost>') != 0:
+             print "Adding Include conf.d/ipa-rewrite to %s failed." % paths.HTTPD_NSS_CONF
+ 
++    def configure_certmonger_renewal_guard(self):
++        bus = dbus.SystemBus()
++        obj = bus.get_object('org.fedorahosted.certmonger',
++                             '/org/fedorahosted/certmonger')
++        iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
++        path = iface.find_ca_by_nickname('IPA')
++        if path:
++            ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
++            ca_iface = dbus.Interface(ca_obj,
++                                      'org.freedesktop.DBus.Properties')
++            helper = ca_iface.Get('org.fedorahosted.certmonger.ca',
++                                  'external-helper')
++            if helper:
++                args = shlex.split(helper)
++                if args[0] != paths.IPA_SERVER_GUARD:
++                    self.backup_state('certmonger_ipa_helper', helper)
++                    args = [paths.IPA_SERVER_GUARD] + args
++                    helper = ' '.join(pipes.quote(a) for a in args)
++                    ca_iface.Set('org.fedorahosted.certmonger.ca',
++                                 'external-helper', helper)
++
+     def __setup_ssl(self):
+         fqdn = self.fqdn
+ 
+@@ -355,6 +382,21 @@ class HTTPInstance(service.Service):
+             self.stop()
+ 
+         self.stop_tracking_certificates()
++
++        helper = self.restore_state('certmonger_ipa_helper')
++        if helper:
++            bus = dbus.SystemBus()
++            obj = bus.get_object('org.fedorahosted.certmonger',
++                                 '/org/fedorahosted/certmonger')
++            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
++            path = iface.find_ca_by_nickname('IPA')
++            if path:
++                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
++                ca_iface = dbus.Interface(ca_obj,
++                                          'org.freedesktop.DBus.Properties')
++                ca_iface.Set('org.fedorahosted.certmonger.ca',
++                             'external-helper', helper)
++
+         if not enabled is None and not enabled:
+             self.disable()
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0100-Fix-validation-of-ipa-restore-options.patch b/SOURCES/0100-Fix-validation-of-ipa-restore-options.patch
new file mode 100644
index 0000000..c0ee533
--- /dev/null
+++ b/SOURCES/0100-Fix-validation-of-ipa-restore-options.patch
@@ -0,0 +1,313 @@
+From 5ec39e80a626e833d8fec24b1797b9c25c072784 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 12 Jan 2015 12:44:21 +0000
+Subject: [PATCH] Fix validation of ipa-restore options
+
+Fix restore mode checks. Do some of the existing checks earlier to make them
+effective. Check if --instance and --backend exist both in the filesystem and
+in the backup.
+
+Log backup type and restore mode before performing restore.
+
+Update ipa-restore man page.
+
+https://fedorahosted.org/freeipa/ticket/4797
+
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ install/tools/man/ipa-restore.1  |  10 +--
+ ipaserver/install/ipa_restore.py | 175 +++++++++++++++++++++++----------------
+ 2 files changed, 108 insertions(+), 77 deletions(-)
+
+diff --git a/install/tools/man/ipa-restore.1 b/install/tools/man/ipa-restore.1
+index 31734b259524e4b07312a4009184e725aafc3728..98242e246ab888f326af5ccfa6420fc080261891 100644
+--- a/install/tools/man/ipa-restore.1
++++ b/install/tools/man/ipa-restore.1
+@@ -64,17 +64,17 @@ Restore the data only. The default is to restore everything in the backup.
+ The full path to a GPG keyring. The keyring consists of two files, a public and a private key (.sec and .pub respectively). Specify the path without an extension.
+ .TP
+ \fB\-\-no\-logs\fR
+-Exclude the IPA service log files in the backup (if they were backed up). Applicable only with a full backup.
++Exclude the IPA service log files in the backup (if they were backed up).
+ .TP
+ \fB\-\-online\fR
+-Perform the restore on\-line. Requires the \-\-data option.
++Perform the restore on\-line. Requires data\-only backup or the \-\-data option.
+ .TP
+ \fB\-\-instance\fR=\fIINSTANCE\fR
+-The backend to restore within an instance or instances.
+-.TP
+-Restore only the databases in this 389\-ds instance. The default is to restore all found (at most this is the IPA REALM instance and the PKI\-IPA instance).
++Restore only the databases in this 389\-ds instance. The default is to restore all found (at most this is the IPA REALM instance and the PKI\-IPA instance). Requires data\-only backup or the \-\-data option.
+ .TP
+ \fB\-\-backend\fR=\fIBACKEND\fR
++The backend to restore within an instance or instances. Requires data\-only backup or the \-\-data option.
++.TP
+ \fB\-\-v\fR, \fB\-\-verbose\fR
+ Print debugging information
+ .TP
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index cd98d07f5f7c7b2ea1b1fef9a272229475efcdc9..be487166d9b2319aeee5fcb54bf4779afcac5afa 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -25,6 +25,7 @@ import time
+ import pwd
+ from ConfigParser import SafeConfigParser
+ import ldif
++import itertools
+ 
+ from ipalib import api, errors
+ from ipapython import version, ipautil, certdb, dogtag
+@@ -161,32 +162,25 @@ class Restore(admintool.AdminTool):
+ 
+ 
+     def validate_options(self):
++        parser = self.option_parser
+         options = self.options
+         super(Restore, self).validate_options(needs_root=True)
+-        if options.data_only:
+-            installutils.check_server_configuration()
+ 
+         if len(self.args) < 1:
+-            self.option_parser.error(
+-                "must provide the backup to restore")
++            parser.error("must provide the backup to restore")
+         elif len(self.args) > 1:
+-            self.option_parser.error(
+-                "must provide exactly one name for the backup")
++            parser.error("must provide exactly one name for the backup")
+ 
+         dirname = self.args[0]
+         if not os.path.isabs(dirname):
+-            self.backup_dir = os.path.join(BACKUP_DIR, dirname)
+-        else:
+-            self.backup_dir = dirname
+-
++            dirname = os.path.join(BACKUP_DIR, dirname)
+         if not os.path.isdir(dirname):
+-            raise self.option_parser.error("must provide path to backup directory")
++            parser.error("must provide path to backup directory")
+ 
+         if options.gpg_keyring:
+             if (not os.path.exists(options.gpg_keyring + '.pub') or
+-               not os.path.exists(options.gpg_keyring + '.sec')):
+-                raise admintool.ScriptError('No such key %s' %
+-                    options.gpg_keyring)
++                    not os.path.exists(options.gpg_keyring + '.sec')):
++                parser.error("no such key %s" % options.gpg_keyring)
+ 
+ 
+     def ask_for_options(self):
+@@ -212,38 +206,88 @@ class Restore(admintool.AdminTool):
+         api.bootstrap(in_server=False, context='restore')
+         api.finalize()
+ 
++        self.backup_dir = self.args[0]
++        if not os.path.isabs(self.backup_dir):
++            self.backup_dir = os.path.join(BACKUP_DIR, self.backup_dir)
++
+         self.log.info("Preparing restore from %s on %s",
+-            self.backup_dir, api.env.host)
++                      self.backup_dir, api.env.host)
+ 
+-        if options.instance and options.backend:
+-            database = (options.instance, options.backend)
+-            if not os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
+-                                  database):
+-                raise admintool.ScriptError(
+-                    "Instance %s with backend %s does not exist" % database)
++        self.header = os.path.join(self.backup_dir, 'header')
++
++        try:
++            self.read_header()
++        except IOError as e:
++            raise admintool.ScriptError("Cannot read backup metadata: %s" % e)
++
++        if options.data_only:
++            restore_type = 'DATA'
++        else:
++            restore_type = self.backup_type
++
++        instances = [realm_to_serverid(api.env.realm), 'PKI-IPA']
++        backends = ['userRoot', 'ipaca']
+ 
+-            databases = [database]
++        # These checks would normally be in the validate method but
++        # we need to know the type of backup we're dealing with.
++        if restore_type == 'FULL':
++            if options.online:
++                raise admintool.ScriptError(
++                    "File restoration cannot be done online")
++            if options.instance or options.backend:
++                raise admintool.ScriptError(
++                    "Restore must be in data-only mode when restoring a "
++                    "specific instance or backend")
+         else:
++            installutils.check_server_configuration()
++
+             if options.instance:
++                instance_dir = (paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
++                                options.instance)
++                if not os.path.exists(instance_dir):
++                    raise admintool.ScriptError(
++                        "Instance %s does not exist" % options.instance)
++
+                 instances = [options.instance]
+-            else:
+-                instances = [realm_to_serverid(api.env.realm), 'PKI-IPA']
+ 
+             if options.backend:
++                for instance in instances:
++                    db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
++                              (instance, options.backend))
++                    if os.path.exists(db_dir):
++                        break
++                else:
++                    raise admintool.ScriptError(
++                        "Backend %s does not exist" % options.backend)
++
+                 backends = [options.backend]
++
++            for instance, backend in itertools.product(instances, backends):
++                db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
++                          (instance, backend))
++                if os.path.exists(db_dir):
++                    break
+             else:
+-                backends = ['userRoot', 'ipaca']
++                raise admintool.ScriptError(
++                    "Cannot restore a data backup into an empty system")
+ 
+-            databases = []
+-            for instance in instances:
+-                for backend in backends:
+-                    database = (instance, backend)
+-                    if os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
+-                                      database):
+-                        databases.append(database)
++        self.log.info("Performing %s restore from %s backup" %
++                      (restore_type, self.backup_type))
+ 
+-            if options.data_only and not databases:
+-                raise admintool.ScriptError('No instances to restore to')
++        if self.backup_host != api.env.host:
++            raise admintool.ScriptError(
++                "Host name %s does not match backup name %s" %
++                (api.env.host, self.backup_host))
++
++        if self.backup_ipa_version != str(version.VERSION):
++            self.log.warning(
++                "Restoring data from a different release of IPA.\n"
++                "Data is version %s.\n"
++                "Server is running %s." %
++                (self.backup_ipa_version, str(version.VERSION)))
++            if (not options.unattended and
++                    not user_input("Continue to restore?", False)):
++                raise admintool.ScriptError("Aborted")
+ 
+         create_ds_user()
+         pent = pwd.getpwnam(DS_USER)
+@@ -257,46 +301,35 @@ class Restore(admintool.AdminTool):
+ 
+         os.chown(self.dir, pent.pw_uid, pent.pw_gid)
+ 
+-        self.header = os.path.join(self.backup_dir, 'header')
+-
+         cwd = os.getcwd()
+         try:
+             dirsrv = services.knownservices.dirsrv
+ 
+-            try:
+-                self.read_header()
+-            except IOError as e:
+-                raise admintool.ScriptError('Cannot read backup metadata: %s' % e)
+-            # These two checks would normally be in the validate method but
+-            # we need to know the type of backup we're dealing with.
+-            if (self.backup_type != 'FULL' and not options.data_only and
+-                not databases):
+-                raise admintool.ScriptError('Cannot restore a data backup into an empty system')
+-            if (self.backup_type == 'FULL' and not options.data_only and
+-                (options.instance or options.backend)):
+-                raise admintool.ScriptError('Restore must be in data-only mode when restoring a specific instance or backend.')
+-            if self.backup_host != api.env.host:
+-                raise admintool.ScriptError(
+-                    'Host name %s does not match backup name %s' %
+-                    (api.env.host, self.backup_host))
+-            if self.backup_ipa_version != str(version.VERSION):
+-                self.log.warning(
+-                    "Restoring data from a different release of IPA.\n"
+-                    "Data is version %s.\n"
+-                    "Server is running %s." %
+-                    (self.backup_ipa_version, str(version.VERSION)))
+-                if (not options.unattended and
+-                    not user_input("Continue to restore?", False)):
+-                    raise admintool.ScriptError("Aborted")
+-
+             self.extract_backup(options.gpg_keyring)
+ 
+-            for database in databases:
+-                ldifname = '%s-%s.ldif' % database
+-                ldiffile = os.path.join(self.dir, ldifname)
+-                if not os.path.exists(ldiffile):
++            databases = []
++            for instance in instances:
++                for backend in backends:
++                    database = (instance, backend)
++                    ldiffile = os.path.join(self.dir, '%s-%s.ldif' % database)
++                    if os.path.exists(ldiffile):
++                        databases.append(database)
++
++            if options.instance:
++                for instance, backend in databases:
++                    if instance == options.instance:
++                        break
++                else:
++                    raise admintool.ScriptError(
++                        "Instance %s not found in backup" % options.instance)
++
++            if options.backend:
++                for instance, backend in databases:
++                    if backend == options.backend:
++                        break
++                else:
+                     raise admintool.ScriptError(
+-                        "Instance %s with backend %s not in backup" % database)
++                        "Backend %s not found in backup" % options.backend)
+ 
+             # Big fat warning
+             if  (not options.unattended and
+@@ -315,7 +348,7 @@ class Restore(admintool.AdminTool):
+             self.log.info("Disabling all replication.")
+             self.disable_agreements()
+ 
+-            if options.data_only:
++            if restore_type != 'FULL':
+                 if not options.online:
+                     self.log.info('Stopping Directory Server')
+                     dirsrv.stop(capture_output=False)
+@@ -332,11 +365,9 @@ class Restore(admintool.AdminTool):
+ 
+ 
+             # We do either a full file restore or we restore data.
+-            if self.backup_type == 'FULL' and not options.data_only:
++            if restore_type == 'FULL':
+                 if 'CA' in self.backup_services:
+                     create_ca_user()
+-                if options.online:
+-                    raise admintool.ScriptError('File restoration cannot be done online.')
+                 self.cert_restore_prepare()
+                 self.file_restore(options.no_logs)
+                 self.cert_restore()
+@@ -351,7 +382,7 @@ class Restore(admintool.AdminTool):
+             for instance, backend in databases:
+                 self.ldif2db(instance, backend, online=options.online)
+ 
+-            if options.data_only:
++            if restore_type != 'FULL':
+                 if not options.online:
+                     self.log.info('Starting Directory Server')
+                     dirsrv.start(capture_output=False)
+-- 
+2.1.0
+
diff --git a/SOURCES/0101-Allow-PassSync-user-to-locate-and-update-NT-users.patch b/SOURCES/0101-Allow-PassSync-user-to-locate-and-update-NT-users.patch
new file mode 100644
index 0000000..bddc767
--- /dev/null
+++ b/SOURCES/0101-Allow-PassSync-user-to-locate-and-update-NT-users.patch
@@ -0,0 +1,284 @@
+From 3998814d3abb5143f06479d2dbf93bf28285a66e Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Tue, 13 Jan 2015 18:09:17 +0100
+Subject: [PATCH] Allow PassSync user to locate and update NT users
+
+Add new PassSync Service privilege that have sufficient access to
+let AD PassSync service search for NT users and update the password.
+To make sure existing PassSync user keeps working, it is added as
+a member of the new privilege.
+
+New update plugin is added to add link to the new privilege to the
+potentially existing PassSync user to avoid breaking the PassSync
+service.
+
+https://fedorahosted.org/freeipa/ticket/4837
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ACI.txt                                      |  2 +
+ install/updates/40-delegation.update         | 30 +++++++++++
+ ipalib/plugins/user.py                       | 12 +++++
+ ipaserver/install/plugins/Makefile.am        |  1 +
+ ipaserver/install/plugins/update_passsync.py | 78 ++++++++++++++++++++++++++++
+ ipaserver/install/replication.py             | 54 ++++++++++---------
+ 6 files changed, 152 insertions(+), 25 deletions(-)
+ create mode 100644 ipaserver/install/plugins/update_passsync.py
+
+diff --git a/ACI.txt b/ACI.txt
+index 6680f658ee1aa0f961b2681f700557ce6b9238f8..fe45d063e7d48c487e380ca3568b0f9368762c6d 100644
+--- a/ACI.txt
++++ b/ACI.txt
+@@ -267,6 +267,8 @@ aci: (targetattr = "krblastadminunlock || krblastfailedauth || krblastpwdchange
+ dn: cn=users,cn=accounts,dc=ipa,dc=example
+ aci: (targetattr = "memberof")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User Membership";allow (compare,read,search) userdn = "ldap:///all";)
+ dn: cn=users,cn=accounts,dc=ipa,dc=example
++aci: (targetattr = "ntuniqueid || ntuseracctexpires || ntusercodepage || ntuserdeleteaccount || ntuserdomainid || ntuserlastlogoff || ntuserlastlogon")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User NT Attributes";allow (compare,read,search) groupdn = "ldap:///cn=System: Read User NT Attributes,cn=permissions,cn=pbac,dc=ipa,dc=example";)
++dn: cn=users,cn=accounts,dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || description || displayname || entryusn || gecos || gidnumber || givenname || homedirectory || initials || ipantsecurityidentifier || loginshell || manager || modifytimestamp || objectclass || sn || title || uid || uidnumber")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User Standard Attributes";allow (compare,read,search) userdn = "ldap:///anyone";)
+ dn: dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || entryusn || gecos || gidnumber || homedirectory || loginshell || modifytimestamp || objectclass || uid || uidnumber")(target = "ldap:///cn=users,cn=*,cn=views,cn=compat,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read User Views Compat Tree";allow (compare,read,search) userdn = "ldap:///anyone";)
+diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update
+index 988de5e1962fabc6787f5914522b8f133e71a8ff..a79f906ea3e29b8b6755a62ac84d318d6abdd6cc 100644
+--- a/install/updates/40-delegation.update
++++ b/install/updates/40-delegation.update
+@@ -184,3 +184,33 @@ default:description: Read list of IPA masters
+ dn: cn=masters,cn=ipa,cn=etc,$SUFFIX
+ add:aci:'(targetfilter = "(objectClass=nsContainer)")(targetattr = "cn || objectClass || ipaConfigString")(version 3.0; acl "Read IPA Masters"; allow (read, search, compare) userdn = "ldap:///fqdn=$FQDN,cn=computers,cn=accounts,$SUFFIX";)'
+ add:aci:'(targetfilter = "(objectClass=nsContainer)")(targetattr = "ipaConfigString")(version 3.0; acl "Modify IPA Masters"; allow (write) userdn = "ldap:///fqdn=$FQDN,cn=computers,cn=accounts,$SUFFIX";)'
++
++# PassSync
++dn: cn=PassSync Service,cn=privileges,cn=pbac,$SUFFIX
++default:objectClass: nestedgroup
++default:objectClass: groupofnames
++default:objectClass: top
++default:cn: PassSync Service
++default:description: PassSync Service
++
++dn: cn=Read PassSync Managers Configuration,cn=permissions,cn=pbac,$SUFFIX
++default:objectClass: groupofnames
++default:objectClass: ipapermission
++default:objectClass: top
++default:cn: Read PassSync Managers Configuration
++default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
++default:ipapermissiontype: SYSTEM
++
++dn: cn=config
++add:aci: '(targetattr = "cn || createtimestamp || entryusn || modifytimestamp || objectclass || passsyncmanagersdns*")(target = "ldap:///cn=ipa_pwd_extop,cn=plugins,cn=config")(version 3.0;acl "permission:Read PassSync Managers Configuration";allow (compare,read,search) groupdn = "ldap:///cn=Read PassSync Managers Configuration,cn=permissions,cn=pbac,$SUFFIX";)'
++
++dn: cn=Modify PassSync Managers Configuration,cn=permissions,cn=pbac,$SUFFIX
++default:objectClass: groupofnames
++default:objectClass: ipapermission
++default:objectClass: top
++default:cn: Modify PassSync Managers Configuration
++default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
++default:ipapermissiontype: SYSTEM
++
++dn: cn=config
++add:aci: '(targetattr = "passsyncmanagersdns*")(target = "ldap:///cn=ipa_pwd_extop,cn=plugins,cn=config")(version 3.0;acl "permission:Modify PassSync Managers Configuration";allow (write) groupdn = "ldap:///cn=Modify PassSync Managers Configuration,cn=permissions,cn=pbac,$SUFFIX";)'
+diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
+index e206289248dfe9ae79bd87271ff2c7672fb98b4f..56585b9f86593c0c5879139103bc71707b88e15f 100644
+--- a/ipalib/plugins/user.py
++++ b/ipalib/plugins/user.py
+@@ -373,10 +373,12 @@ class user(LDAPObject):
+             'replaces': [
+                 '(target = "ldap:///uid=*,cn=users,cn=accounts,$SUFFIX")(targetattr = "userpassword || krbprincipalkey || sambalmpassword || sambantpassword || passwordhistory")(version 3.0;acl "permission:Change a user password";allow (write) groupdn = "ldap:///cn=Change a user password,cn=permissions,cn=pbac,$SUFFIX";)',
+                 '(targetfilter = "(!(memberOf=cn=admins,cn=groups,cn=accounts,$SUFFIX))")(target = "ldap:///uid=*,cn=users,cn=accounts,$SUFFIX")(targetattr = "userpassword || krbprincipalkey || sambalmpassword || sambantpassword || passwordhistory")(version 3.0;acl "permission:Change a user password";allow (write) groupdn = "ldap:///cn=Change a user password,cn=permissions,cn=pbac,$SUFFIX";)',
++                '(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Windows PassSync service can write passwords"; allow (write) userdn="ldap:///uid=passsync,cn=sysaccounts,cn=etc,$SUFFIX";)',
+             ],
+             'default_privileges': {
+                 'User Administrators',
+                 'Modify Users and Reset passwords',
++                'PassSync Service',
+             },
+         },
+         'System: Manage User SSH Public Keys': {
+@@ -446,6 +448,16 @@ class user(LDAPObject):
+                 'homedirectory', 'loginshell',
+             },
+         },
++        'System: Read User NT Attributes': {
++            'ipapermbindruletype': 'permission',
++            'ipapermright': {'read', 'search', 'compare'},
++            'ipapermdefaultattr': {
++                'ntuserdomainid', 'ntuniqueid', 'ntuseracctexpires',
++                'ntusercodepage', 'ntuserdeleteaccount', 'ntuserlastlogoff',
++                'ntuserlastlogon',
++            },
++            'default_privileges': {'PassSync Service'},
++        },
+     }
+ 
+     label = _('Users')
+diff --git a/ipaserver/install/plugins/Makefile.am b/ipaserver/install/plugins/Makefile.am
+index d651297ac141b0f05831e7fabbb9b561cdd239c7..ead1d8f7d972c1b016bac8f2b8f7fd1f9a71b563 100644
+--- a/ipaserver/install/plugins/Makefile.am
++++ b/ipaserver/install/plugins/Makefile.am
+@@ -14,6 +14,7 @@ app_PYTHON = 			\
+ 	update_referint.py	\
+ 	ca_renewal_master.py	\
+ 	update_uniqueness.py	\
++	update_passsync.py	\
+ 	$(NULL)
+ 
+ EXTRA_DIST =			\
+diff --git a/ipaserver/install/plugins/update_passsync.py b/ipaserver/install/plugins/update_passsync.py
+new file mode 100644
+index 0000000000000000000000000000000000000000..d6595a06f4deb62b853d716012a8c594c6a76451
+--- /dev/null
++++ b/ipaserver/install/plugins/update_passsync.py
+@@ -0,0 +1,78 @@
++#
++# Copyright (C) 2014  FreeIPA Contributors see COPYING for license
++#
++
++from ipaserver.install.plugins import MIDDLE, LAST
++from ipaserver.install.plugins.baseupdate import PreUpdate, PostUpdate
++from ipalib import api, errors
++from ipapython.dn import DN
++from ipapython.ipa_log_manager import root_logger
++from ipaserver.install import sysupgrade
++
++class update_passync_privilege_check(PreUpdate):
++    order = MIDDLE
++
++    def execute(self, **options):
++        update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
++        if update_done:
++            root_logger.debug("PassSync privilege update pre-check not needed")
++            return False, False, []
++
++        root_logger.debug("Check if there is existing PassSync privilege")
++
++        passsync_privilege_dn = DN(('cn','PassSync Service'),
++                self.api.env.container_privilege,
++                self.api.env.basedn)
++
++        ldap = self.obj.backend
++        try:
++            ldap.get_entry(passsync_privilege_dn, [''])
++        except errors.NotFound:
++            root_logger.debug("PassSync privilege not found, this is a new update")
++            sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', False)
++        else:
++            root_logger.debug("PassSync privilege found, skip updating PassSync")
++            sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
++
++        return False, False, []
++
++api.register(update_passync_privilege_check)
++
++class update_passync_privilege_update(PostUpdate):
++    """
++        Add PassSync user as a member of PassSync privilege, if it exists
++    """
++
++    order = LAST
++
++    def execute(self, **options):
++        update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
++        if update_done:
++            root_logger.debug("PassSync privilege update not needed")
++            return False, False, []
++
++        root_logger.debug("Add PassSync user as a member of PassSync privilege")
++        ldap = self.obj.backend
++        passsync_dn = DN(('uid','passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'),
++            api.env.basedn)
++        passsync_privilege_dn = DN(('cn','PassSync Service'),
++                self.api.env.container_privilege,
++                self.api.env.basedn)
++
++        try:
++            entry = ldap.get_entry(passsync_dn, [''])
++        except errors.NotFound:
++            root_logger.debug("PassSync user not found, no update needed")
++            sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
++            return False, False, []
++        else:
++            root_logger.debug("PassSync user found, do update")
++
++        update = {'dn': passsync_privilege_dn,
++                  'updates': ["add:member:'%s'" % passsync_dn]}
++        updates = {passsync_privilege_dn: update}
++
++        sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
++        return (False, True, [updates])
++
++api.register(update_passync_privilege_update)
+diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
+index 5778cab036ad87ccb5b69254aa307a6bc8dec871..66764c22f69328942fe2e4581cfafb3806438d7c 100644
+--- a/ipaserver/install/replication.py
++++ b/ipaserver/install/replication.py
+@@ -528,39 +528,43 @@ class ReplicationManager(object):
+         print "The user for the Windows PassSync service is %s" % pass_dn
+         try:
+             conn.get_entry(pass_dn)
+-            print "Windows PassSync entry exists, not resetting password"
+-            return
++            print "Windows PassSync system account exists, not resetting password"
+         except errors.NotFound:
+-            pass
+-
+-        # The user doesn't exist, add it
+-        entry = conn.make_entry(
+-            pass_dn,
+-            objectclass=["account", "simplesecurityobject"],
+-            uid=["passsync"],
+-            userPassword=[password],
+-        )
+-        conn.add_entry(entry)
++            # The user doesn't exist, add it
++            print "Adding Windows PassSync system account"
++            entry = conn.make_entry(
++                pass_dn,
++                objectclass=["account", "simplesecurityobject"],
++                uid=["passsync"],
++                userPassword=[password],
++            )
++            conn.add_entry(entry)
+ 
+-        # Add it to the list of users allowed to bypass password policy
++        # Add the user to the list of users allowed to bypass password policy
+         extop_dn = DN(('cn', 'ipa_pwd_extop'), ('cn', 'plugins'), ('cn', 'config'))
+         entry = conn.get_entry(extop_dn)
+-        pass_mgrs = entry.get('passSyncManagersDNs')
+-        if not pass_mgrs:
+-            pass_mgrs = []
+-        if not isinstance(pass_mgrs, list):
+-            pass_mgrs = [pass_mgrs]
++        pass_mgrs = entry.get('passSyncManagersDNs', [])
+         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)
++            conn.modify_s(extop_dn, mod)
++        except ldap.TYPE_OR_VALUE_EXISTS:
++            root_logger.debug("Plugin '%s' already '%s' in passSyncManagersDNs",
++                    extop_dn, pass_dn)
++
++        # And finally add it is a member of PassSync privilege to allow
++        # displaying user NT attributes and reset passwords
++        passsync_privilege_dn = DN(('cn','PassSync Service'),
++                api.env.container_privilege,
++                api.env.basedn)
++        members = entry.get('member', [])
++        members.append(pass_dn)
++        mod = [(ldap.MOD_REPLACE, 'member', members)]
++        try:
++            conn.modify_s(passsync_privilege_dn, mod)
+         except ldap.TYPE_OR_VALUE_EXISTS:
+-            root_logger.debug("passsync aci already exists in suffix %s on %s" % (self.suffix, conn.host))
++            root_logger.debug("PassSync service '%s' already have '%s' as member",
++                    passsync_privilege_dn, pass_dn)
+ 
+     def setup_winsync_agmt(self, entry, win_subtree=None):
+         if win_subtree is None:
+-- 
+2.1.0
+
diff --git a/SOURCES/0102-Allow-Replication-Administrators-manipulate-Winsync-.patch b/SOURCES/0102-Allow-Replication-Administrators-manipulate-Winsync-.patch
new file mode 100644
index 0000000..627f6e6
--- /dev/null
+++ b/SOURCES/0102-Allow-Replication-Administrators-manipulate-Winsync-.patch
@@ -0,0 +1,68 @@
+From 18e8a2c23dd05724867cd5da82f5fe20936e3df2 Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Wed, 14 Jan 2015 16:36:16 +0100
+Subject: [PATCH] Allow Replication Administrators manipulate Winsync
+ Agreements
+
+Replication Administrators members were not able to set up changelog5
+entry in cn=config or list winsync agreements.
+
+To allow reading winsync replicas, the original deny ACI cn=replica
+had to be removed as it prevented admins from reading the entries,
+but just anonymous/authenticated users.
+
+https://fedorahosted.org/freeipa/ticket/4836
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ install/updates/20-aci.update        |  2 +-
+ install/updates/40-delegation.update | 23 +++++++++++++++++++++++
+ 2 files changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
+index 9bbb7e4bb8d51b3d957d1f63d2c889e793276598..b920ef83d8580911d9a9c577e3ed6a9356da69e2 100644
+--- a/install/updates/20-aci.update
++++ b/install/updates/20-aci.update
+@@ -26,7 +26,7 @@ dn: $SUFFIX
+ add:aci:'(targetfilter="(&(objectclass=nsContainer)(!(objectclass=krbPwdPolicy)))")(target!="ldap:///cn=masters,cn=ipa,cn=etc,$SUFFIX")(targetattr="objectclass || cn")(version 3.0; acl "Anonymous read access to containers"; allow(read, search, compare) userdn = "ldap:///anyone";)'
+ 
+ dn: cn=replicas,cn=ipa,cn=etc,$SUFFIX
+-add:aci:'(targetfilter="(objectclass=nsContainer)")(version 3.0; acl "Deny read access to replica configuration"; deny(read, search, compare) userdn = "ldap:///anyone";)'
++remove:aci:'(targetfilter="(objectclass=nsContainer)")(version 3.0; acl "Deny read access to replica configuration"; deny(read, search, compare) userdn = "ldap:///anyone";)'
+ 
+ # Read access to masters and their services
+ dn: cn=masters,cn=ipa,cn=etc,$SUFFIX
+diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update
+index a79f906ea3e29b8b6755a62ac84d318d6abdd6cc..32af498190a23ddfd202a5cad75409f60a70d78b 100644
+--- a/install/updates/40-delegation.update
++++ b/install/updates/40-delegation.update
+@@ -214,3 +214,26 @@ default:ipapermissiontype: SYSTEM
+ 
+ dn: cn=config
+ add:aci: '(targetattr = "passsyncmanagersdns*")(target = "ldap:///cn=ipa_pwd_extop,cn=plugins,cn=config")(version 3.0;acl "permission:Modify PassSync Managers Configuration";allow (write) groupdn = "ldap:///cn=Modify PassSync Managers Configuration,cn=permissions,cn=pbac,$SUFFIX";)'
++
++# Replication Administrators
++dn: cn=Read LDBM Database Configuration,cn=permissions,cn=pbac,$SUFFIX
++default:objectClass: groupofnames
++default:objectClass: ipapermission
++default:objectClass: top
++default:cn: Read LDBM Database Configuration
++default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
++default:ipapermissiontype: SYSTEM
++
++dn: cn=config
++add:aci: '(targetattr = "cn || createtimestamp || entryusn || modifytimestamp || nsslapd-directory* || objectclass")(target = "ldap:///cn=config,cn=ldbm database,cn=plugins,cn=config")(version 3.0;acl "permission:Read LDBM Database Configuration";allow (compare,read,search) groupdn = "ldap:///cn=Read LDBM Database Configuration,cn=permissions,cn=pbac,$SUFFIX";)'
++
++dn: cn=Add Configuration Sub-Entries,cn=permissions,cn=pbac,$SUFFIX
++default:objectClass: groupofnames
++default:objectClass: ipapermission
++default:objectClass: top
++default:cn: Add Configuration Sub-Entries
++default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
++default:ipapermissiontype: SYSTEM
++
++dn: cn=config
++add:aci: '(version 3.0;acl "permission:Add Configuration Sub-Entries";allow (add) groupdn = "ldap:///cn=Add Configuration Sub-Entries,cn=permissions,cn=pbac,$SUFFIX";)'
+-- 
+2.1.0
+
diff --git a/SOURCES/0103-Do-not-assume-certmonger-is-running-in-httpinstance.patch b/SOURCES/0103-Do-not-assume-certmonger-is-running-in-httpinstance.patch
new file mode 100644
index 0000000..af80ec4
--- /dev/null
+++ b/SOURCES/0103-Do-not-assume-certmonger-is-running-in-httpinstance.patch
@@ -0,0 +1,81 @@
+From 13fec89bb4a2ddfda7d1ad0da18c6c4be77373d6 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 20 Jan 2015 09:38:43 +0000
+Subject: [PATCH] Do not assume certmonger is running in httpinstance
+
+https://fedorahosted.org/freeipa/ticket/4835
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+---
+ ipaserver/install/httpinstance.py | 48 +++++++++++++++++++++++----------------
+ 1 file changed, 29 insertions(+), 19 deletions(-)
+
+diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
+index 2fb315b6b822343860a9c31b016d6a0a22388488..cda85ab02b8054748e671935fcfbc3993257c53e 100644
+--- a/ipaserver/install/httpinstance.py
++++ b/ipaserver/install/httpinstance.py
+@@ -39,6 +39,7 @@ from ipaserver.install import sysupgrade
+ from ipalib import api
+ from ipaplatform.tasks import tasks
+ from ipaplatform.paths import paths
++from ipaplatform import services
+ 
+ 
+ SELINUX_BOOLEAN_SETTINGS = dict(
+@@ -228,25 +229,34 @@ class HTTPInstance(service.Service):
+             print "Adding Include conf.d/ipa-rewrite to %s failed." % paths.HTTPD_NSS_CONF
+ 
+     def configure_certmonger_renewal_guard(self):
+-        bus = dbus.SystemBus()
+-        obj = bus.get_object('org.fedorahosted.certmonger',
+-                             '/org/fedorahosted/certmonger')
+-        iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
+-        path = iface.find_ca_by_nickname('IPA')
+-        if path:
+-            ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
+-            ca_iface = dbus.Interface(ca_obj,
+-                                      'org.freedesktop.DBus.Properties')
+-            helper = ca_iface.Get('org.fedorahosted.certmonger.ca',
+-                                  'external-helper')
+-            if helper:
+-                args = shlex.split(helper)
+-                if args[0] != paths.IPA_SERVER_GUARD:
+-                    self.backup_state('certmonger_ipa_helper', helper)
+-                    args = [paths.IPA_SERVER_GUARD] + args
+-                    helper = ' '.join(pipes.quote(a) for a in args)
+-                    ca_iface.Set('org.fedorahosted.certmonger.ca',
+-                                 'external-helper', helper)
++        certmonger = services.knownservices.certmonger
++        certmonger_stopped = not certmonger.is_running()
++
++        if certmonger_stopped:
++            certmonger.start()
++        try:
++            bus = dbus.SystemBus()
++            obj = bus.get_object('org.fedorahosted.certmonger',
++                                 '/org/fedorahosted/certmonger')
++            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
++            path = iface.find_ca_by_nickname('IPA')
++            if path:
++                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
++                ca_iface = dbus.Interface(ca_obj,
++                                          'org.freedesktop.DBus.Properties')
++                helper = ca_iface.Get('org.fedorahosted.certmonger.ca',
++                                      'external-helper')
++                if helper:
++                    args = shlex.split(helper)
++                    if args[0] != paths.IPA_SERVER_GUARD:
++                        self.backup_state('certmonger_ipa_helper', helper)
++                        args = [paths.IPA_SERVER_GUARD] + args
++                        helper = ' '.join(pipes.quote(a) for a in args)
++                        ca_iface.Set('org.fedorahosted.certmonger.ca',
++                                     'external-helper', helper)
++        finally:
++            if certmonger_stopped:
++                certmonger.stop()
+ 
+     def __setup_ssl(self):
+         fqdn = self.fqdn
+-- 
+2.1.0
+
diff --git a/SOURCES/0104-Replication-Administrators-cannot-remove-replication.patch b/SOURCES/0104-Replication-Administrators-cannot-remove-replication.patch
new file mode 100644
index 0000000..c6b0bc8
--- /dev/null
+++ b/SOURCES/0104-Replication-Administrators-cannot-remove-replication.patch
@@ -0,0 +1,41 @@
+From 0bea7bc245fe1471008d20c78626c2fa2572e91c Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Mon, 19 Jan 2015 12:42:11 +0100
+Subject: [PATCH] Replication Administrators cannot remove replication
+ agreements
+
+Replication agreement deletion requires read access to DNA range
+setting. The read access was accidently removed during PermissionV2
+refactoring.
+
+Add the read ACI back as a special SYSTEM permission.
+
+https://fedorahosted.org/freeipa/ticket/4848
+
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+---
+ install/updates/40-replication.update | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/install/updates/40-replication.update b/install/updates/40-replication.update
+index 619d14663eeb6f692864c960dfd3542fc22cb581..f46ab19f0090ba313880e6d99636f50397f8d33b 100644
+--- a/install/updates/40-replication.update
++++ b/install/updates/40-replication.update
+@@ -14,3 +14,14 @@ default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
+ 
+ dn: cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
+ add:aci: '(targetattr=dnaNextRange || dnaNextValue || dnaMaxValue)(version 3.0;acl "permission:Modify DNA Range";allow (write) groupdn = "ldap:///cn=Modify DNA Range,cn=permissions,cn=pbac,$SUFFIX";)'
++
++dn: cn=Read DNA Range,cn=permissions,cn=pbac,$SUFFIX
++default:objectClass: top
++default:objectClass: groupofnames
++default:objectClass: ipapermission
++default:cn: Read DNA Range
++default:ipapermissiontype: SYSTEM
++default:member: cn=Replication Administrators,cn=privileges,cn=pbac,$SUFFIX
++
++dn: cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
++add:aci: '(targetattr=cn || dnaMaxValue || dnaNextRange || dnaNextValue  || dnaThreshold || dnaType || objectclass)(version 3.0;acl "permission:Read DNA Range";allow (read, search, compare) groupdn = "ldap:///cn=Read DNA Range,cn=permissions,cn=pbac,$SUFFIX";)'
+-- 
+2.1.0
+
diff --git a/SOURCES/0105-Put-LDIF-files-to-their-original-location-in-ipa-res.patch b/SOURCES/0105-Put-LDIF-files-to-their-original-location-in-ipa-res.patch
new file mode 100644
index 0000000..1eca1dc
--- /dev/null
+++ b/SOURCES/0105-Put-LDIF-files-to-their-original-location-in-ipa-res.patch
@@ -0,0 +1,40 @@
+From 0717bc9dcaddf4f43bb9412af979b37a5a61c55b Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 20 Jan 2015 11:22:29 +0000
+Subject: [PATCH] Put LDIF files to their original location in ipa-restore
+
+This prevents SELinux failures during online data restore.
+
+https://fedorahosted.org/freeipa/ticket/4822
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index be487166d9b2319aeee5fcb54bf4779afcac5afa..562a793c2c9383d7495c84a817ac9f7a1407f9bb 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -504,10 +504,17 @@ class Restore(admintool.AdminTool):
+         cn = time.strftime('import_%Y_%m_%d_%H_%M_%S')
+         dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))
+ 
++        ldifdir = paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance
+         ldifname = '%s-%s.ldif' % (instance, backend)
++        ldiffile = os.path.join(ldifdir, ldifname)
+         srcldiffile = os.path.join(self.dir, ldifname)
+-        ldiffile = '%s.noruv' % srcldiffile
+ 
++        if not os.path.exists(ldifdir):
++            pent = pwd.getpwnam(DS_USER)
++            os.mkdir(ldifdir, 0770)
++            os.chown(ldifdir, pent.pw_uid, pent.pw_gid)
++
++        ipautil.backup_file(ldiffile)
+         with open(ldiffile, 'wb') as out_file:
+             ldif_writer = ldif.LDIFWriter(out_file)
+             with open(srcldiffile, 'rb') as in_file:
+-- 
+2.1.0
+
diff --git a/SOURCES/0106-Add-anonymous-read-ACI-for-DUA-profile.patch b/SOURCES/0106-Add-anonymous-read-ACI-for-DUA-profile.patch
new file mode 100644
index 0000000..dd94dc2
--- /dev/null
+++ b/SOURCES/0106-Add-anonymous-read-ACI-for-DUA-profile.patch
@@ -0,0 +1,62 @@
+From 113834837e775bfa40604d131725e9b34248465c Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Tue, 20 Jan 2015 17:57:07 +0100
+Subject: [PATCH] Add anonymous read ACI for DUA profile
+
+DUA profile(s) are consumed by Solaris clients.
+
+https://fedorahosted.org/freeipa/ticket/4850
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ACI.txt                                              |  2 ++
+ .../install/plugins/update_managed_permissions.py    | 20 ++++++++++++++++++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/ACI.txt b/ACI.txt
+index fe45d063e7d48c487e380ca3568b0f9368762c6d..67d583fabc295deb8aa5aab329bce5100c1b9088 100644
+--- a/ACI.txt
++++ b/ACI.txt
+@@ -298,6 +298,8 @@ dn: cn=certificates,cn=ipa,cn=etc,dc=ipa,dc=example
+ aci: (targetattr = "cacertificate || cn || createtimestamp || entryusn || ipacertissuerserial || ipacertsubject || ipaconfigstring || ipakeyextusage || ipakeytrust || ipakeyusage || ipapublickey || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipacertificate)")(version 3.0;acl "permission:System: Read Certificate Store Entries";allow (compare,read,search) userdn = "ldap:///anyone";)
+ dn: cn=dna,cn=ipa,cn=etc,dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || dnahostname || dnaportnum || dnaremainingvalues || dnaremotebindmethod || dnaremoteconnprotocol || dnasecureportnum || entryusn || modifytimestamp || objectclass")(targetfilter = "(objectclass=dnasharedconfig)")(version 3.0;acl "permission:System: Read DNA Configuration";allow (compare,read,search) userdn = "ldap:///all";)
++dn: ou=profile,dc=ipa,dc=example
++aci: (targetattr = "attributemap || authenticationmethod || bindtimelimit || cn || createtimestamp || credentiallevel || defaultsearchbase || defaultsearchscope || defaultserverlist || dereferencealiases || entryusn || followreferrals || modifytimestamp || objectclass || objectclassmap || ou || preferredserverlist || profilettl || searchtimelimit || serviceauthenticationmethod || servicecredentiallevel || servicesearchdescriptor")(targetfilter = "(|(objectclass=organizationalUnit)(objectclass=DUAConfigProfile))")(version 3.0;acl "permission:System: Read DUA Profile";allow (compare,read,search) userdn = "ldap:///anyone";)
+ dn: cn=masters,cn=ipa,cn=etc,dc=ipa,dc=example
+ aci: (targetattr = "cn || createtimestamp || entryusn || ipaconfigstring || modifytimestamp || objectclass")(targetfilter = "(objectclass=nscontainer)")(version 3.0;acl "permission:System: Read IPA Masters";allow (compare,read,search) groupdn = "ldap:///cn=System: Read IPA Masters,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+ dn: cn=config
+diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
+index 032485aac5b84b12b91464f16870c9940b18bc2d..430a2919a315bfd8d8e6174a915890d44b782c5c 100644
+--- a/ipaserver/install/plugins/update_managed_permissions.py
++++ b/ipaserver/install/plugins/update_managed_permissions.py
+@@ -320,6 +320,26 @@ NONOBJECT_PERMISSIONS = {
+             'winsyncsubtreepair',
+         },
+         'default_privileges': {'Replication Administrators'},
++    },
++    'System: Read DUA Profile': {
++        'ipapermlocation': DN('ou=profile', api.env.basedn),
++        'ipapermtargetfilter': {
++            '(|'
++                '(objectclass=organizationalUnit)'
++                '(objectclass=DUAConfigProfile)'
++            ')'
++        },
++        'ipapermbindruletype': 'anonymous',
++        'ipapermright': {'read', 'search', 'compare'},
++        'ipapermdefaultattr': {
++            'objectclass', 'ou', 'cn', 'defaultServerList',
++            'preferredServerList', 'defaultSearchBase', 'defaultSearchScope',
++            'searchTimeLimit', 'bindTimeLimit', 'credentialLevel',
++            'authenticationMethod', 'followReferrals', 'dereferenceAliases',
++            'serviceSearchDescriptor', 'serviceCredentialLevel',
++            'serviceAuthenticationMethod', 'objectclassMap', 'attributeMap',
++            'profileTTL'
++        },
+     }
+ }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/0107-Revert-Make-all-ipatokenTOTP-attributes-mandatory.patch b/SOURCES/0107-Revert-Make-all-ipatokenTOTP-attributes-mandatory.patch
new file mode 100644
index 0000000..da907c4
--- /dev/null
+++ b/SOURCES/0107-Revert-Make-all-ipatokenTOTP-attributes-mandatory.patch
@@ -0,0 +1,34 @@
+From 04eb9743de09e5d2bc00d6a775249c3c2c439a2d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Wed, 21 Jan 2015 07:57:03 +0000
+Subject: [PATCH] Revert "Make all ipatokenTOTP attributes mandatory"
+
+This prevents schema replication conflicts which cause replication failures
+with older versions of IPA. Details in
+https://bugzilla.redhat.com/show_bug.cgi?id=1176995#c7
+
+This reverts commit adcd373931c50d91550f6b74b191d08ecce5b137.
+
+https://fedorahosted.org/freeipa/ticket/4833
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ install/share/70ipaotp.ldif | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/install/share/70ipaotp.ldif b/install/share/70ipaotp.ldif
+index bc95556682ef65ba375aa2f3cab6f53621641b3f..61cb8f63b9b4aba80a2785afb46bff206ab0eff0 100644
+--- a/install/share/70ipaotp.ldif
++++ b/install/share/70ipaotp.ldif
+@@ -25,7 +25,7 @@ attributeTypes: (2.16.840.1.113730.3.8.16.1.20 NAME 'ipatokenUserMapAttribute' D
+ attributeTypes: (2.16.840.1.113730.3.8.16.1.21 NAME 'ipatokenHOTPcounter' DESC 'HOTP counter' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA OTP')
+ attributeTypes: (2.16.840.1.113730.3.8.16.1.22 NAME 'ipatokenTOTPwatermark' DESC 'TOTP watermark' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA OTP')
+ objectClasses:  (2.16.840.1.113730.3.8.16.2.1  NAME 'ipaToken' SUP top ABSTRACT DESC 'Abstract token class for tokens' MUST (ipatokenUniqueID) MAY (description $ managedBy $ ipatokenOwner $ ipatokenDisabled $ ipatokenNotBefore $ ipatokenNotAfter $ ipatokenVendor $ ipatokenModel $ ipatokenSerial) X-ORIGIN 'IPA OTP')
+-objectClasses:  (2.16.840.1.113730.3.8.16.2.2  NAME 'ipatokenTOTP' SUP ipaToken STRUCTURAL DESC 'TOTP Token Type' MUST (ipatokenOTPkey $ ipatokenOTPalgorithm $ ipatokenOTPdigits $ ipatokenTOTPclockOffset $ ipatokenTOTPtimeStep) MAY (ipatokenTOTPwatermark) X-ORIGIN 'IPA OTP')
++objectClasses:  (2.16.840.1.113730.3.8.16.2.2  NAME 'ipatokenTOTP' SUP ipaToken STRUCTURAL DESC 'TOTP Token Type' MAY (ipatokenOTPkey $ ipatokenOTPalgorithm $ ipatokenOTPdigits $ ipatokenTOTPclockOffset $ ipatokenTOTPtimeStep $ ipatokenTOTPwatermark) X-ORIGIN 'IPA OTP')
+ objectClasses:  (2.16.840.1.113730.3.8.16.2.3  NAME 'ipatokenRadiusProxyUser' SUP top AUXILIARY DESC 'Radius Proxy User' MAY (ipatokenRadiusConfigLink $ ipatokenRadiusUserName) X-ORIGIN 'IPA OTP')
+ objectClasses:  (2.16.840.1.113730.3.8.16.2.4  NAME 'ipatokenRadiusConfiguration' SUP top STRUCTURAL DESC 'Proxy Radius Configuration' MUST (cn $ ipatokenRadiusServer $ ipatokenRadiusSecret) MAY (description $ ipatokenRadiusTimeout $ ipatokenRadiusRetries $ ipatokenUserMapAttribute) X-ORIGIN 'IPA OTP')
+ objectClasses:  (2.16.840.1.113730.3.8.16.2.5  NAME 'ipatokenHOTP' SUP ipaToken STRUCTURAL DESC 'HOTP Token Type' MUST (ipatokenOTPkey $ ipatokenOTPalgorithm $ ipatokenOTPdigits $ ipatokenHOTPcounter) X-ORIGIN 'IPA OTP')
+-- 
+2.1.0
+
diff --git a/SOURCES/0108-Create-correct-log-directories-during-full-restore-i.patch b/SOURCES/0108-Create-correct-log-directories-during-full-restore-i.patch
new file mode 100644
index 0000000..5b916f5
--- /dev/null
+++ b/SOURCES/0108-Create-correct-log-directories-during-full-restore-i.patch
@@ -0,0 +1,57 @@
+From ed5044ffc209e842c000d1c47980de6e0ab8e52a Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Mon, 26 Jan 2015 10:39:48 +0000
+Subject: [PATCH] Create correct log directories during full restore in
+ ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4865
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 29 ++++++++++++++---------------
+ 1 file changed, 14 insertions(+), 15 deletions(-)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 562a793c2c9383d7495c84a817ac9f7a1407f9bb..6de73e640d101a72aacc7ce73a6937c222da4ebb 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -713,22 +713,21 @@ class Restore(admintool.AdminTool):
+         not exist then tomcat will fail to start.
+ 
+         The directory is different depending on whether we have a d9-based
+-        or a d10-based installation. We can tell based on whether there is
+-        a PKI-IPA 389-ds instance.
++        or a d10-based installation.
+         """
+-        if os.path.exists(paths.ETC_SLAPD_PKI_IPA_DIR): # dogtag 9
+-            topdir = paths.PKI_CA_LOG_DIR
+-            dirs = [topdir,
+-                    '/var/log/pki-ca/signedAudit,']
+-        else: # dogtag 10
+-            topdir = paths.TOMCAT_TOPLEVEL_DIR
+-            dirs = [topdir,
+-                    paths.TOMCAT_CA_DIR,
+-                    paths.TOMCAT_CA_ARCHIVE_DIR,
+-                    paths.TOMCAT_SIGNEDAUDIT_DIR,]
+-
+-        if os.path.exists(topdir):
+-            return
++        dirs = []
++        # dogtag 9
++        if (os.path.exists(paths.VAR_LIB_PKI_CA_DIR) and
++                not os.path.exists(paths.PKI_CA_LOG_DIR)):
++            dirs += [paths.PKI_CA_LOG_DIR,
++                     os.path.join(paths.PKI_CA_LOG_DIR, 'signedAudit')]
++        # dogtag 10
++        if (os.path.exists(paths.VAR_LIB_PKI_TOMCAT_DIR) and
++                not os.path.exists(paths.TOMCAT_TOPLEVEL_DIR)):
++            dirs += [paths.TOMCAT_TOPLEVEL_DIR,
++                     paths.TOMCAT_CA_DIR,
++                     paths.TOMCAT_CA_ARCHIVE_DIR,
++                     paths.TOMCAT_SIGNEDAUDIT_DIR]
+ 
+         try:
+             pent = pwd.getpwnam(PKI_USER)
+-- 
+2.1.0
+
diff --git a/SOURCES/0109-Do-not-crash-when-replica-is-unreachable-in-ipa-rest.patch b/SOURCES/0109-Do-not-crash-when-replica-is-unreachable-in-ipa-rest.patch
new file mode 100644
index 0000000..d770803
--- /dev/null
+++ b/SOURCES/0109-Do-not-crash-when-replica-is-unreachable-in-ipa-rest.patch
@@ -0,0 +1,35 @@
+From 394e24cee7dfb8f1d860b936f7a865e8cace8c71 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 27 Jan 2015 07:38:06 +0000
+Subject: [PATCH] Do not crash when replica is unreachable in ipa-restore
+
+https://fedorahosted.org/freeipa/ticket/4857
+
+Reviewed-By: Martin Kosek <mkosek@redhat.com>
+---
+ ipaserver/install/ipa_restore.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
+index 6de73e640d101a72aacc7ce73a6937c222da4ebb..efe3b9b1c0c10775b3a72b9d843924263526209a 100644
+--- a/ipaserver/install/ipa_restore.py
++++ b/ipaserver/install/ipa_restore.py
+@@ -458,6 +458,7 @@ class Restore(admintool.AdminTool):
+                                           self.dirman_password)
+             except Exception, e:
+                 self.log.critical("Unable to disable agreement on %s: %s" % (master, e))
++                continue
+ 
+             master_dn = DN(('cn', master), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
+             try:
+@@ -482,6 +483,7 @@ class Restore(admintool.AdminTool):
+                                                       self.dirman_password)
+                 except Exception, e:
+                     self.log.critical("Unable to disable agreement on %s: %s" % (master, e))
++                    continue
+ 
+                 host_entries = repl.find_ipa_replication_agreements()
+                 hosts = [rep.single_value.get('nsds5replicahost')
+-- 
+2.1.0
+
diff --git a/SOURCES/0110-idviews-Allow-setting-ssh-public-key-on-ipauseroverr.patch b/SOURCES/0110-idviews-Allow-setting-ssh-public-key-on-ipauseroverr.patch
new file mode 100644
index 0000000..fb67ee0
--- /dev/null
+++ b/SOURCES/0110-idviews-Allow-setting-ssh-public-key-on-ipauseroverr.patch
@@ -0,0 +1,36 @@
+From f6a6555e5dff1c3132529f7671b1978eab10315e Mon Sep 17 00:00:00 2001
+From: David Kupka <dkupka@redhat.com>
+Date: Tue, 27 Jan 2015 16:12:19 +0100
+Subject: [PATCH] idviews: Allow setting ssh public key on ipauseroverride-add
+
+https://fedorahosted.org/freeipa/ticket/4868
+
+Reviewed-By: Jan Cholasta <jcholast@redhat.com>
+---
+ ipalib/plugins/idviews.py | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py
+index 9c8721018325f56e681f168b55c31055bfd07345..aa2c89163d875a813b0b850125e522935e2ef44f 100644
+--- a/ipalib/plugins/idviews.py
++++ b/ipalib/plugins/idviews.py
+@@ -665,6 +665,7 @@ class idoverrideuser(baseidoverride):
+     }
+ 
+     object_class = baseidoverride.object_class + ['ipaUserOverride']
++    possible_objectclasses = ['ipasshuser', 'ipaSshGroupOfPubKeys']
+     default_attributes = baseidoverride.default_attributes + [
+        'homeDirectory', 'uidNumber', 'uid', 'ipaOriginalUid', 'loginShell',
+        'ipaSshPubkey', 'gidNumber', 'gecos',
+@@ -779,6 +780,8 @@ class idoverrideuser_add(baseidoverride_add):
+         dn = super(idoverrideuser_add, self).pre_callback(ldap, dn,
+                  entry_attrs, attrs_list, *keys, **options)
+ 
++        entry_attrs['objectclass'].append('ipasshuser')
++
+         # Update the ipaOriginalUid
+         self.obj.update_original_uid_reference(entry_attrs)
+         return dn
+-- 
+2.1.0
+
diff --git a/SOURCES/0111-Fix-ipa-pwd-extop-global-configuration-caching.patch b/SOURCES/0111-Fix-ipa-pwd-extop-global-configuration-caching.patch
new file mode 100644
index 0000000..5758f5f
--- /dev/null
+++ b/SOURCES/0111-Fix-ipa-pwd-extop-global-configuration-caching.patch
@@ -0,0 +1,39 @@
+From f0a61fa88284f8872f1496c0c0b24908d70274c8 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Thu, 29 Jan 2015 16:58:16 -0500
+Subject: [PATCH] Fix ipa-pwd-extop global configuration caching
+
+This fix is already upstream as part of the following commit:
+        9baa93da1cbf56c2a6f7e82e099bc3ff3f19e2e4
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1187342
+---
+ daemons/ipa-slapi-plugins/libotp/otp_config.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/libotp/otp_config.c b/daemons/ipa-slapi-plugins/libotp/otp_config.c
+index 1b7c1e658f126e3d1e8eabd129bb69dc5c4ce970..f600789f34ca87bf57ac3ee7d551843680cc86f1 100644
+--- a/daemons/ipa-slapi-plugins/libotp/otp_config.c
++++ b/daemons/ipa-slapi-plugins/libotp/otp_config.c
+@@ -126,10 +126,14 @@ static uint32_t find_value(const struct otp_config *cfg,
+
+     sdn = make_sdn(spec->prefix, suffix);
+     for (struct record *rec = cfg->records; rec != NULL; rec = rec->next) {
+-        if (rec->spec == spec) {
+-            value = PR_ATOMIC_ADD(&rec->value, 0);
+-            break;
+-        }
++        if (rec->spec != spec)
++            continue;
++
++        if (slapi_sdn_compare(sdn, rec->sdn) != 0)
++            continue;
++
++        value = PR_ATOMIC_ADD(&rec->value, 0);
++        break;
+     }
+
+     slapi_sdn_free(&sdn);
+--
+2.1.0
+
diff --git a/SOURCES/0112-group-detach-does-not-add-correct-objectclasses.patch b/SOURCES/0112-group-detach-does-not-add-correct-objectclasses.patch
new file mode 100644
index 0000000..e6f1196
--- /dev/null
+++ b/SOURCES/0112-group-detach-does-not-add-correct-objectclasses.patch
@@ -0,0 +1,25 @@
+From 225b31ba835e5c082dc116a9ca9a5d94eaaaf102 Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Fri, 30 Jan 2015 13:11:30 +0100
+Subject: [PATCH] group-detach does not add correct objectclasses
+
+https://fedorahosted.org/freeipa/ticket/4874
+---
+ ipalib/plugins/group.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
+index d25ed9a1958119a5872db85e958323fdb8205366..5d33ba217137f31e59a9e63cb69a442b138e156b 100644
+--- a/ipalib/plugins/group.py
++++ b/ipalib/plugins/group.py
+@@ -653,6 +653,7 @@ class group_detach(LDAPQuery):
+         objectclasses = list(set(def_objectclass + objectclasses))
+ 
+         group_attrs['mepManagedBy'] = None
++        group_attrs['objectclass'] = objectclasses
+         ldap.update_entry(group_attrs)
+ 
+         return dict(
+-- 
+1.9.3
+
diff --git a/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch b/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch
index c650b25..644a02f 100644
--- a/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch
+++ b/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch
@@ -1,6 +1,6 @@
-From ebaad372cdeb941af1a390f81c8a4d90ea128f9f Mon Sep 17 00:00:00 2001
+From e33a5c3b993e0111617e1c15bed374f6ce426b2d Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
-Date: Thu, 14 Aug 2014 13:34:13 +0200
+Date: Fri, 5 Sep 2014 11:24:27 +0200
 Subject: [PATCH] Hide pkinit functionality from production version
 
 Rebased from original patch from Jan Zeleny and Rob Crittenden.
@@ -8,15 +8,15 @@ Rebased from original patch from Jan Zeleny and Rob Crittenden.
 https://fedorahosted.org/freeipa/ticket/616
 ---
  install/tools/ipa-replica-install        |  5 +++--
- install/tools/ipa-server-install         | 10 ++++------
- ipaserver/install/ipa_replica_prepare.py | 11 +++--------
- 3 files changed, 10 insertions(+), 16 deletions(-)
+ install/tools/ipa-server-install         | 20 ++++----------------
+ ipaserver/install/ipa_replica_prepare.py | 20 +++-----------------
+ 3 files changed, 10 insertions(+), 35 deletions(-)
 
 diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
-index 4418b41784313121e73b560ee84715ddeba8bc54..ff4cd70147abb2dc6e0486155fb179d4fb1b29e9 100755
+index 75bbe981b96cf17950fe73d92d39ca3030f548f9..d3b520abf635ccc324b74bca31f241960a33d950 100755
 --- a/install/tools/ipa-replica-install
 +++ b/install/tools/ipa-replica-install
-@@ -95,8 +95,6 @@ def parse_options():
+@@ -97,8 +97,6 @@ def parse_options():
      parser.add_option_group(basic_group)
  
      cert_group = OptionGroup(parser, "certificate system options")
@@ -25,7 +25,7 @@ index 4418b41784313121e73b560ee84715ddeba8bc54..ff4cd70147abb2dc6e0486155fb179d4
      cert_group.add_option("--skip-schema-check", dest="skip_schema_check", action="store_true",
                        default=False, help="skip check for updated CA DS schema on the remote master")
      parser.add_option_group(cert_group)
-@@ -121,6 +119,9 @@ def parse_options():
+@@ -126,6 +124,9 @@ def parse_options():
      options, args = parser.parse_args()
      safe_options = parser.get_safe_opts(options)
  
@@ -36,82 +36,122 @@ index 4418b41784313121e73b560ee84715ddeba8bc54..ff4cd70147abb2dc6e0486155fb179d4
          parser.error("you must provide a file generated by ipa-replica-prepare")
  
 diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
-index feea616b089261bf46392d5514e6e3cc9e12fcac..5bd22bf18f2b00e26d674b6cbbf81989b4a030cb 100755
+index 0394314ee99817f221536136ae1432cc8e92220a..a5df3e9971a5ae128ebfa4c542dcad7cc3626276 100755
 --- a/install/tools/ipa-server-install
 +++ b/install/tools/ipa-server-install
-@@ -179,20 +179,14 @@ def parse_options():
-                       help="File containing the IPA CA certificate signed by the external CA in PEM format")
-     cert_group.add_option("", "--external_ca_file", dest="external_ca_file",
-                       help="File containing the external CA certificate chain in PEM format")
+@@ -218,8 +218,6 @@ def parse_options():
+     cert_group.add_option("--external_ca_file", dest="external_cert_files",
+                       action="append",
+                       help=SUPPRESS_HELP)
 -    cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
 -                      default=True, help="disables pkinit setup steps")
-     cert_group.add_option("--dirsrv_pkcs12", dest="dirsrv_pkcs12",
-                       help="PKCS#12 file containing the Directory Server SSL certificate")
-     cert_group.add_option("--http_pkcs12", dest="http_pkcs12",
-                       help="PKCS#12 file containing the Apache Server SSL certificate")
--    cert_group.add_option("--pkinit_pkcs12", dest="pkinit_pkcs12",
--                      help="PKCS#12 file containing the Kerberos KDC SSL certificate")
-     cert_group.add_option("--dirsrv_pin", dest="dirsrv_pin", sensitive=True,
-                       help="The password of the Directory Server PKCS#12 file")
+     cert_group.add_option("--dirsrv-cert-file", dest="dirsrv_cert_files",
+                       action="append", metavar="FILE",
+                       help="File containing the Directory Server SSL certificate and private key")
+@@ -232,12 +230,6 @@ def parse_options():
+     cert_group.add_option("--http_pkcs12", dest="http_cert_files",
+                       action="append",
+                       help=SUPPRESS_HELP)
+-    cert_group.add_option("--pkinit-cert-file", dest="pkinit_cert_files",
+-                      action="append", metavar="FILE",
+-                      help="File containing the Kerberos KDC SSL certificate and private key")
+-    cert_group.add_option("--pkinit_pkcs12", dest="pkinit_cert_files",
+-                      action="append",
+-                      help=SUPPRESS_HELP)
+     cert_group.add_option("--dirsrv-pin", dest="dirsrv_pin", sensitive=True,
+                       metavar="PIN",
+                       help="The password to unlock the Directory Server private key")
+@@ -248,20 +240,12 @@ def parse_options():
+                       help="The password to unlock the Apache Server private key")
      cert_group.add_option("--http_pin", dest="http_pin", sensitive=True,
-                       help="The password of the Apache Server PKCS#12 file")
--    cert_group.add_option("--pkinit_pin", dest="pkinit_pin",
--                      help="The password of the Kerberos KDC PKCS#12 file")
-     cert_group.add_option("--root-ca-file", dest="root_ca_file",
-                       help="PEM file with root CA certificate(s) to trust")
-     cert_group.add_option("--subject", action="callback", callback=subject_callback,
-@@ -229,6 +223,10 @@ def parse_options():
+                       help=SUPPRESS_HELP)
+-    cert_group.add_option("--pkinit-pin", dest="pkinit_pin", sensitive=True,
+-                      metavar="PIN",
+-                      help="The password to unlock the Kerberos KDC private key")
+-    cert_group.add_option("--pkinit_pin", dest="pkinit_pin", sensitive=True,
+-                      help=SUPPRESS_HELP)
+     cert_group.add_option("--dirsrv-cert-name", dest="dirsrv_cert_name",
+                       metavar="NAME",
+                       help="Name of the Directory Server SSL certificate to install")
+     cert_group.add_option("--http-cert-name", dest="http_cert_name",
+                       metavar="NAME",
+                       help="Name of the Apache Server SSL certificate to install")
+-    cert_group.add_option("--pkinit-cert-name", dest="pkinit_cert_name",
+-                      metavar="NAME",
+-                      help="Name of the Kerberos KDC SSL certificate to install")
+     cert_group.add_option("--ca-cert-file", dest="ca_cert_files",
+                       action="append", metavar="FILE",
+                       help="File containing CA certificates for the service certificate files")
+@@ -309,6 +293,10 @@ def parse_options():
      options, args = parser.parse_args()
      safe_options = parser.get_safe_opts(options)
  
 +    # pkinit is disabled in production version
 +    options.pkinit_pin = False
-+    options.pkinit_pkcs12 = False
++    options.pkinit_cert_files = False
 +
      if options.dm_password is not None:
          try:
              validate_dm_password(options.dm_password)
 diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
-index 36d078a6b73562cb0047154f4bb7666ab25687b8..a3b89a8a739c6082aa7117cea470e2a9d8dba7f9 100644
+index 3762f32700aa899541883d3af72b160c4c42ba7c..1d34aa26b49be0c5df8e7d315a45cd6d180e6da9 100644
 --- a/ipaserver/install/ipa_replica_prepare.py
 +++ b/ipaserver/install/ipa_replica_prepare.py
-@@ -56,9 +56,6 @@ def add_options(cls, parser):
+@@ -63,9 +63,6 @@ class ReplicaPrepare(admintool.AdminTool):
          parser.add_option("--no-reverse", dest="no_reverse",
              action="store_true", default=False,
              help="do not create reverse DNS zone")
 -        parser.add_option("--no-pkinit", dest="setup_pkinit",
 -            action="store_false", default=True,
 -            help="disables pkinit setup steps")
-         parser.add_option("--ca", dest="ca_file", default="/root/cacert.p12",
+         parser.add_option("--ca", dest="ca_file", default=paths.CACERT_P12,
              metavar="FILE",
              help="location of CA PKCS#12 file, default /root/cacert.p12")
-@@ -71,15 +68,10 @@ def add_options(cls, parser):
-         group.add_option("--http_pkcs12", dest="http_pkcs12",
-             metavar="FILE",
-             help="install certificate for the http server")
--        group.add_option("--pkinit_pkcs12", dest="pkinit_pkcs12",
--            metavar="FILE",
--            help="install certificate for the KDC")
-         group.add_option("--dirsrv_pin", dest="dirsrv_pin", metavar="PIN",
-             help="PIN for the Directory Server PKCS#12 file")
-         group.add_option("--http_pin", dest="http_pin", metavar="PIN",
-             help="PIN for the Apache Server PKCS#12 file")
--        group.add_option("--pkinit_pin", dest="pkinit_pin", metavar="PIN",
--            help="PIN for the KDC pkinit PKCS#12 file")
+@@ -87,12 +84,6 @@ class ReplicaPrepare(admintool.AdminTool):
+         group.add_option("--http_pkcs12", dest="http_cert_files",
+             action="append",
+             help=SUPPRESS_HELP)
+-        group.add_option("--pkinit-cert-file", dest="pkinit_cert_files",
+-            action="append", metavar="FILE",
+-            help="File containing the Kerberos KDC SSL certificate and private key")
+-        group.add_option("--pkinit_pkcs12", dest="pkinit_cert_files",
+-            action="append",
+-            help=SUPPRESS_HELP)
+         group.add_option("--dirsrv-pin", dest="dirsrv_pin", sensitive=True,
+             metavar="PIN",
+             help="The password to unlock the Directory Server private key")
+@@ -103,20 +94,12 @@ class ReplicaPrepare(admintool.AdminTool):
+             help="The password to unlock the Apache Server private key")
+         group.add_option("--http_pin", dest="http_pin", sensitive=True,
+             help=SUPPRESS_HELP)
+-        group.add_option("--pkinit-pin", dest="pkinit_pin", sensitive=True,
+-            metavar="PIN",
+-            help="The password to unlock the Kerberos KDC private key")
+-        group.add_option("--pkinit_pin", dest="pkinit_pin", sensitive=True,
+-            help=SUPPRESS_HELP)
+         group.add_option("--dirsrv-cert-name", dest="dirsrv_cert_name",
+             metavar="NAME",
+             help="Name of the Directory Server SSL certificate to install")
+         group.add_option("--http-cert-name", dest="http_cert_name",
+             metavar="NAME",
+             help="Name of the Apache Server SSL certificate to install")
+-        group.add_option("--pkinit-cert-name", dest="pkinit_cert_name",
+-            metavar="NAME",
+-            help="Name of the Kerberos KDC SSL certificate to install")
          parser.add_option_group(group)
  
      def validate_options(self):
-@@ -99,7 +91,10 @@ def validate_options(self):
+@@ -136,7 +119,10 @@ class ReplicaPrepare(admintool.AdminTool):
                  "option together with --no-reverse")
  
          #Automatically disable pkinit w/ dogtag until that is supported
 +        # pkinit is disabled in production version
          options.setup_pkinit = False
 +        options.pkinit_pin = False
-+        options.pkinit_pkcs12 = False
++        options.pkinit_cert_files = False
  
          # If any of the PKCS#12 options are selected, all are required.
-         pkcs12_req = (options.dirsrv_pkcs12, options.http_pkcs12)
+         cert_file_req = (options.dirsrv_cert_files, options.http_cert_files)
 -- 
 1.9.3
 
diff --git a/SOURCES/1002-Remove-pkinit-plugin.patch b/SOURCES/1002-Remove-pkinit-plugin.patch
index 6c53550..d2fed0a 100644
--- a/SOURCES/1002-Remove-pkinit-plugin.patch
+++ b/SOURCES/1002-Remove-pkinit-plugin.patch
@@ -1,7 +1,7 @@
-From 62b7d72f65ab8ac90a62486bb170133755764bc7 Mon Sep 17 00:00:00 2001
+From f7996d16d5a424f136d54a7dc190d4e6c5dad628 Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
-Date: Wed, 22 May 2013 09:40:39 +0200
-Subject: [PATCH 1002/1006] Remove pkinit plugin
+Date: Fri, 5 Sep 2014 11:26:18 +0200
+Subject: [PATCH] Remove pkinit plugin
 
 This patch completely removes any signs of pkinit in the IPA package. It
 should be used only as addition to the first patch attached to the
@@ -12,15 +12,15 @@ Rebased patch by Jan Zeleny and Rob Crittenden.
 https://fedorahosted.org/freeipa/ticket/616
 ---
  API.txt                  |   5 ---
- ipalib/plugins/pkinit.py | 101 -----------------------------------------------
- 2 files changed, 106 deletions(-)
+ ipalib/plugins/pkinit.py | 105 -----------------------------------------------
+ 2 files changed, 110 deletions(-)
  delete mode 100644 ipalib/plugins/pkinit.py
 
 diff --git a/API.txt b/API.txt
-index 5418f31dc8d936ee629155aff08c05577cf9c4ee..ec5b3c9f6459e048c516a64dbab2396306fa6a72 100644
+index 7949c49f9fb9e3cd7eceb64a05dd8e550eb48f8b..e573a2838777dc564fc8ef16f97b36fe17b67590 100644
 --- a/API.txt
 +++ b/API.txt
-@@ -2336,11 +2336,6 @@ command: ping
+@@ -2895,11 +2895,6 @@ command: ping
  args: 0,1,1
  option: Str('version?', exclude='webui')
  output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
@@ -34,10 +34,10 @@ index 5418f31dc8d936ee629155aff08c05577cf9c4ee..ec5b3c9f6459e048c516a64dbab23963
  option: Flag('all', autofill=True, cli_name='all', default=True, exclude='webui')
 diff --git a/ipalib/plugins/pkinit.py b/ipalib/plugins/pkinit.py
 deleted file mode 100644
-index 981e411df520e175fa88f1de02a4eae36d687ede..0000000000000000000000000000000000000000
+index 5f00b2b46ff94cca7f98876c0171f455c210d778..0000000000000000000000000000000000000000
 --- a/ipalib/plugins/pkinit.py
 +++ /dev/null
-@@ -1,101 +0,0 @@
+@@ -1,105 +0,0 @@
 -# Authors:
 -#   Simo Sorce <ssorce@redhat.com>
 -#
@@ -61,6 +61,7 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -from ipalib import Int, Str
 -from ipalib import Object, Command
 -from ipalib import _
+-from ipalib.plugable import Registry
 -from ipapython.dn import DN
 -
 -__doc__ = _("""
@@ -83,6 +84,9 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -http://k5wiki.kerberos.org/wiki/Projects/Anonymous_pkinit
 -""")
 -
+-register = Registry()
+-
+-@register()
 -class pkinit(Object):
 -    """
 -    PKINIT Options
@@ -91,7 +95,6 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -
 -    label=_('PKINIT')
 -
--api.register(pkinit)
 -
 -def valid_arg(ugettext, action):
 -    """
@@ -104,6 +107,7 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -            error=_('Unknown command %s') % action
 -        )
 -
+-@register()
 -class pkinit_anonymous(Command):
 -    __doc__ = _('Enable or Disable Anonymous PKINIT.')
 -
@@ -119,7 +123,7 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -        set_lock = False
 -        lock = None
 -
--        (dn, entry_attrs) = ldap.get_entry(self.default_dn, ['nsaccountlock'])
+-        entry_attrs = ldap.get_entry(self.default_dn, ['nsaccountlock'])
 -
 -        if 'nsaccountlock' in entry_attrs:
 -            lock = entry_attrs['nsaccountlock'][0].lower()
@@ -134,11 +138,11 @@ index 981e411df520e175fa88f1de02a4eae36d687ede..00000000000000000000000000000000
 -                lock = 'TRUE'
 -
 -        if set_lock:
--            ldap.update_entry(dn, {'nsaccountlock':lock})
+-            entry_attrs['nsaccountlock'] = lock
+-            ldap.update_entry(entry_attrs)
 -
 -        return dict(result=True)
 -
--api.register(pkinit_anonymous)
 -- 
-1.8.3.1
+2.1.0
 
diff --git a/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch b/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch
index d4a0099..cddd2b8 100644
--- a/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch
+++ b/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch
@@ -1,13 +1,13 @@
-From e7dcef627095e38ce29a5f446c08a55ee88fc893 Mon Sep 17 00:00:00 2001
+From c86d432ab449d86860ad6436684caa2af30da99f Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
 Date: Wed, 22 May 2013 09:59:12 +0200
-Subject: [PATCH 1003/1006] Remove pkinit references from tool man pages
+Subject: [PATCH] Remove pkinit references from tool man pages
 
 ---
- install/tools/man/ipa-replica-install.1 | 3 ---
- install/tools/man/ipa-replica-prepare.1 | 9 ---------
- install/tools/man/ipa-server-install.1  | 9 ---------
- 3 files changed, 21 deletions(-)
+ install/tools/man/ipa-replica-install.1 |  3 ---
+ install/tools/man/ipa-replica-prepare.1 | 12 ------------
+ install/tools/man/ipa-server-install.1  | 12 ------------
+ 3 files changed, 27 deletions(-)
 
 diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
 index b7a55cb748dfd5536d86e1b2634df34fd43f319b..993606d83c8117b47b73bb13ac1e7431ba03f369 100644
@@ -24,29 +24,38 @@ index b7a55cb748dfd5536d86e1b2634df34fd43f319b..993606d83c8117b47b73bb13ac1e7431
  Skip check for updated CA DS schema on the remote master
  
 diff --git a/install/tools/man/ipa-replica-prepare.1 b/install/tools/man/ipa-replica-prepare.1
-index 8e1e60a25628432bf380e7af1d2d2dac9abf8c8a..88c30757b38cfdfec36dce85e995d419dd05c17b 100644
+index a0d47c9add145b8840065f64b79443ade504d9db..7931b71ed6fceab059a51496d9289ce25eb86b4e 100644
 --- a/install/tools/man/ipa-replica-prepare.1
 +++ b/install/tools/man/ipa-replica-prepare.1
-@@ -41,18 +41,12 @@ PKCS#12 file containing the Directory Server SSL Certificate and Private Key
- \fB\-\-http_pkcs12\fR=\fIFILE\fR
- PKCS#12 file containing the Apache Server SSL Certificate and Private Key
+@@ -41,27 +41,18 @@ File containing the Directory Server SSL certificate and private key. The files
+ \fB\-\-http\-cert\-file\fR=\fIFILE\fR
+ File containing the Apache Server SSL certificate and private key. The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. This option may be used multiple times.
  .TP
--\fB\-\-pkinit_pkcs12\fR=\fIFILE\fR
--PKCS#12 file containing the Kerberos KDC Certificate and Private Key
+-\fB\-\-pkinit\-cert\-file\fR=\fIFILE\fR
+-File containing the Kerberos KDC SSL certificate and private key. The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. This option may be used multiple times.
 -.TP
- \fB\-\-dirsrv_pin\fR=\fIDIRSRV_PIN\fR
- The password of the Directory Server PKCS#12 file
+ \fB\-\-dirsrv\-pin\fR=\fIPIN\fR
+ The password to unlock the Directory Server private key
  .TP
- \fB\-\-http_pin\fR=\fIHTTP_PIN\fR
- The password of the Apache Server PKCS#12 file
+ \fB\-\-http\-pin\fR=\fIPIN\fR
+ The password to unlock the Apache Server private key
  .TP
--\fB\-\-pkinit_pin\fR=\fIPKINIT_PIN\fR
--The password of the Kerberos KDC PKCS#12 file
+-\fB\-\-pkinit\-pin\fR=\fIPIN\fR
+-The password to unlock the Kerberos KDC private key
+-.TP
+ \fB\-\-dirsrv\-cert\-name\fR=\fINAME\fR
+ Name of the Directory Server SSL certificate to install
+ .TP
+ \fB\-\-http\-cert\-name\fR=\fINAME\fR
+ Name of the Apache Server SSL certificate to install
+ .TP
+-\fB\-\-pkinit\-cert\-name\fR=\fINAME\fR
+-Name of the Kerberos KDC SSL certificate to install
 -.TP
  \fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-password\fR=\fIDM_PASSWORD\fR
  Directory Manager (existing master) password
  .TP
-@@ -68,9 +62,6 @@ Do not create reverse DNS zone
+@@ -77,9 +68,6 @@ Do not create reverse DNS zone
  \fB\-\-ca\fR=\fICA_FILE\fR
  Location of CA PKCS#12 file, default /root/cacert.p12
  .TP
@@ -57,37 +66,46 @@ index 8e1e60a25628432bf380e7af1d2d2dac9abf8c8a..88c30757b38cfdfec36dce85e995d419
  Prints info log messages to the output
  .SH "EXIT STATUS"
 diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
-index 59219c14727c5a3062d06d5ef02eb0eebdc9c4f2..409dcf24beb6c53a9908437738fbbe3c90078367 100644
+index e5c9c319b95268af091287a7be14df6a2d06a6e0..7343f323e5447c028bba36564172524690059342 100644
 --- a/install/tools/man/ipa-server-install.1
 +++ b/install/tools/man/ipa-server-install.1
-@@ -93,27 +93,18 @@ PEM file containing a certificate signed by the external CA. Must be given with
- \fB\-\-external_ca_file\fR=\fIFILE\fR
- PEM file containing the external CA chain
+@@ -93,36 +93,24 @@ Type of the external CA. Possible values are "generic", "ms-cs". Default value i
+ \fB\-\-external\-cert\-file\fR=\fIFILE\fR
+ File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times.
  .TP
 -\fB\-\-no\-pkinit\fR
 -Disables pkinit setup steps
 -.TP
- \fB\-\-dirsrv_pkcs12\fR=\fIFILE\fR
- PKCS#12 file containing the Directory Server SSL Certificate
+ \fB\-\-dirsrv\-cert\-file\fR=\fIFILE\fR
+ File containing the Directory Server SSL certificate and private key. The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. This option may be used multiple times.
  .TP
- \fB\-\-http_pkcs12\fR=\fIFILE\fR
- PKCS#12 file containing the Apache Server SSL Certificate
+ \fB\-\-http\-cert\-file\fR=\fIFILE\fR
+ File containing the Apache Server SSL certificate and private key. The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. This option may be used multiple times.
  .TP
--\fB\-\-pkinit_pkcs12\fR=\fIFILE\fR
--PKCS#12 file containing the Kerberos KDC SSL certificate
+-\fB\-\-pkinit\-cert\-file\fR=\fIFILE\fR
+-File containing the Kerberos KDC SSL certificate and private key. The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. This option may be used multiple times.
 -.TP
- \fB\-\-dirsrv_pin\fR=\fIDIRSRV_PIN\fR
- The password of the Directory Server PKCS#12 file
+ \fB\-\-dirsrv\-pin\fR=\fIPIN\fR
+ The password to unlock the Directory Server private key
  .TP
- \fB\-\-http_pin\fR=\fIHTTP_PIN\fR
- The password of the Apache Server PKCS#12 file
+ \fB\-\-http\-pin\fR=\fIPIN\fR
+ The password to unlock the Apache Server private key
  .TP
--\fB\-\-pkinit_pin\fR=\fIPKINIT_PIN\fR
--The password of the Kerberos KDC PKCS#12 file
+-\fB\-\-pkinit\-pin\fR=\fIPIN\fR
+-The password to unlock the Kerberos KDC private key
 -.TP
- \fB\-\-subject\fR=\fISUBJECT\fR
- The certificate subject base (default O=REALM.NAME)
- 
+ \fB\-\-dirsrv\-cert\-name\fR=\fINAME\fR
+ Name of the Directory Server SSL certificate to install
+ .TP
+ \fB\-\-http\-cert\-name\fR=\fINAME\fR
+ Name of the Apache Server SSL certificate to install
+ .TP
+-\fB\-\-pkinit\-cert\-name\fR=\fINAME\fR
+-Name of the Kerberos KDC SSL certificate to install
+-.TP
+ \fB\-\-ca\-cert\-file\fR=\fIFILE\fR
+ File containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC certificates. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. Use this option if the CA certificate is not present in the certificate files.
+ .TP
 -- 
-1.8.3.1
+1.9.3
 
diff --git a/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch b/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch
index 3f300c0..a1e96b4 100644
--- a/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch
+++ b/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch
@@ -1,13 +1,13 @@
-From 8f1aaebb76015f92601d012a4ce1d8da27a1c90c Mon Sep 17 00:00:00 2001
+From 7e7a531e1b503c6fe5e4ac0389591c546071411b Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
-Date: Thu, 18 Jul 2013 08:48:29 +0200
-Subject: [PATCH 1004/1006] Change branding to IPA and Identity Management
+Date: Fri, 5 Sep 2014 11:46:59 +0200
+Subject: [PATCH] Change branding to IPA and Identity Management
 
 ---
- install/html/browserconfig.html            | 2 +-
- install/html/ssbrowser.html                | 2 +-
- install/html/unauthorized.html             | 2 +-
- install/migration/error.html               | 2 +-
+ install/html/browserconfig.html            | 4 ++--
+ install/html/ssbrowser.html                | 4 ++--
+ install/html/unauthorized.html             | 4 ++--
+ install/migration/error.html               | 4 ++--
  install/migration/index.html               | 2 +-
  install/migration/invalid.html             | 2 +-
  install/tools/ipa-adtrust-install          | 6 +++---
@@ -24,6 +24,7 @@ Subject: [PATCH 1004/1006] Change branding to IPA and Identity Management
  install/tools/man/ipa-ldap-updater.1       | 2 +-
  install/tools/man/ipa-managed-entries.1    | 2 +-
  install/tools/man/ipa-nis-manage.1         | 2 +-
+ install/tools/man/ipa-otptoken-import.1    | 2 +-
  install/tools/man/ipa-replica-conncheck.1  | 2 +-
  install/tools/man/ipa-replica-install.1    | 2 +-
  install/tools/man/ipa-replica-manage.1     | 2 +-
@@ -33,19 +34,21 @@ Subject: [PATCH 1004/1006] Change branding to IPA and Identity Management
  install/tools/man/ipa-server-install.1     | 2 +-
  install/tools/man/ipactl.8                 | 2 +-
  install/ui/index.html                      | 2 +-
- install/ui/login.html                      | 2 +-
- install/ui/logout.html                     | 2 +-
  install/ui/reset_password.html             | 2 +-
+ install/ui/src/freeipa/widgets/App.js      | 2 +-
+ install/ui/sync_otp.html                   | 2 +-
  ipa-client/man/default.conf.5              | 2 +-
  ipa-client/man/ipa-client-automount.1      | 2 +-
  ipa-client/man/ipa-client-install.1        | 2 +-
- ipa-client/man/ipa-getkeytab.1             | 2 +-
+ ipa-client/man/ipa-getkeytab.1             | 4 ++--
  ipa-client/man/ipa-join.1                  | 2 +-
  ipa-client/man/ipa-rmkeytab.1              | 2 +-
- 38 files changed, 41 insertions(+), 41 deletions(-)
+ ipa.1                                      | 2 +-
+ ipaserver/advise/plugins/legacy_clients.py | 8 ++++----
+ 41 files changed, 52 insertions(+), 52 deletions(-)
 
 diff --git a/install/html/browserconfig.html b/install/html/browserconfig.html
-index a7784f75b8dabb19a5658b06a008bc3f4660823d..31508e95521b9c196c102cfda0be94bb25e43cf3 100644
+index d721a4ad2a3b684a4bf45602584fee78f4613360..b0cd570403b1604449887302844c43b1e89b80e2 100644
 --- a/install/html/browserconfig.html
 +++ b/install/html/browserconfig.html
 @@ -2,7 +2,7 @@
@@ -54,11 +57,20 @@ index a7784f75b8dabb19a5658b06a008bc3f4660823d..31508e95521b9c196c102cfda0be94bb
      <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
+     <script type="text/javascript" src="../ui/js/libs/loader.js"></script>
+     <script type="text/javascript">
+         (function() {
+@@ -26,7 +26,7 @@
+ 
+     <nav class="navbar navbar-default navbar-pf" role="navigation">
+     <div class="navbar-header">
+-        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="FreeIPA"></a>
++        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="Identity Management"></a>
+     </div>
+     </nav>
  
-     <link rel="stylesheet" type="text/css" href="../ui/jquery-ui.css" />
-     <link rel="stylesheet" type="text/css" href="../ui/ipa.css" />
 diff --git a/install/html/ssbrowser.html b/install/html/ssbrowser.html
-index 72fd573cf907e7ce3a27a17a2857633480cff9de..9a52a9f4d6920a949c071d58312c3d8177d4a1d6 100644
+index d90103228150a60bd49e91ea8c64891d53d75d7b..d066d9c26694d4f0637bccf5dd4e869db7f6da41 100644
 --- a/install/html/ssbrowser.html
 +++ b/install/html/ssbrowser.html
 @@ -2,7 +2,7 @@
@@ -67,11 +79,20 @@ index 72fd573cf907e7ce3a27a17a2857633480cff9de..9a52a9f4d6920a949c071d58312c3d81
  <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
+     <script type="text/javascript" src="../ui/js/libs/loader.js"></script>
+     <script type="text/javascript">
+         (function() {
+@@ -45,7 +45,7 @@
+ 
+     <nav class="navbar navbar-default navbar-pf" role="navigation">
+     <div class="navbar-header">
+-        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="FreeIPA"></a>
++        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="Identity Management"></a>
+     </div>
+     </nav>
  
-     <link rel="stylesheet" type="text/css" href="../ui/jquery-ui.css" />
-     <link rel="stylesheet" type="text/css" href="../ui/ipa.css" />
 diff --git a/install/html/unauthorized.html b/install/html/unauthorized.html
-index 0fac88b98bc6eebeaa776af8341dfb5fdad4773d..19c7eb19a04530273893156b3a61141a65f29076 100644
+index 0b4414f55e7e2ab242e782b6824c2af7ae9eae59..37f2548591f691c79c0ac29afb9f4213ec5dc31a 100644
 --- a/install/html/unauthorized.html
 +++ b/install/html/unauthorized.html
 @@ -2,7 +2,7 @@
@@ -80,11 +101,20 @@ index 0fac88b98bc6eebeaa776af8341dfb5fdad4773d..19c7eb19a04530273893156b3a61141a
      <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
+     <script type="text/javascript" src="../ui/js/libs/loader.js"></script>
+     <script type="text/javascript">
+         (function() {
+@@ -19,7 +19,7 @@
  
-     <script type="text/javascript" src="../ui/js/libs/jquery.js"></script>
+     <nav class="navbar navbar-default navbar-pf" role="navigation">
+     <div class="navbar-header">
+-        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="FreeIPA"></a>
++        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="Identity Management"></a>
+     </div>
+     </nav>
  
 diff --git a/install/migration/error.html b/install/migration/error.html
-index 9e1e3bd0b27f264534d013e8e526c3cded448c77..333ee1e5030596917a15a5b864719cc2abb374b4 100644
+index 896e56ec63c6eee62cb0b93f4e7fe97d668e703d..c7a4cb41961e181633ddd4f0d41064d8b696782f 100644
 --- a/install/migration/error.html
 +++ b/install/migration/error.html
 @@ -2,7 +2,7 @@
@@ -94,39 +124,48 @@ index 9e1e3bd0b27f264534d013e8e526c3cded448c77..333ee1e5030596917a15a5b864719cc2
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
  
-     <link rel="stylesheet" type="text/css" href="../ui/jquery-ui.css" />
-     <link rel="stylesheet" type="text/css" href="../ui/ipa.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/patternfly.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/ipa.css" />
+@@ -11,7 +11,7 @@
+ <body class="info-page">
+     <nav class="navbar navbar-default navbar-pf" role="navigation">
+     <div class="navbar-header">
+-        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="FreeIPA"></a>
++        <a class="brand" href="../ui/index.html"><img src="../ui/images/header-logo.png" alt="Identity Management"></a>
+     </div>
+     </nav>
+ 
 diff --git a/install/migration/index.html b/install/migration/index.html
-index eb816b35d9f420f8f64ee8a63c443818793e5e59..78c5165f076f77de59f5554bedfe59f4a580a133 100644
+index 302eca263fa62c92d39ad9ccc678cf251a0afc8c..189aa71943ae1a5acfae977c0f74400d7ac4d23b 100644
 --- a/install/migration/index.html
 +++ b/install/migration/index.html
 @@ -2,7 +2,7 @@
- <html>
+ <html class="login-pf">
  <head>
  <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
  
-     <link rel="stylesheet" type="text/css" href="../ui/jquery-ui.css" />
-     <link rel="stylesheet" type="text/css" href="../ui/ipa.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/patternfly.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/ipa.css" />
 diff --git a/install/migration/invalid.html b/install/migration/invalid.html
-index 4f46934066602b5bc52c62ad7006fe4b85ae2a6d..4f4e87a7d9490cab4ac97ed623d1f364d87be909 100644
+index f75b0bdc7d00d54d801ef66f373a09e89ead3251..16c455ca12e922ece1ea49813071fc2db0a22970 100644
 --- a/install/migration/invalid.html
 +++ b/install/migration/invalid.html
 @@ -2,7 +2,7 @@
- <html>
+ <html class="login-pf">
  <head>
  <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
  
-     <link rel="stylesheet" type="text/css" href="../ui/jquery-ui.css" />
-     <link rel="stylesheet" type="text/css" href="../ui/ipa.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/patternfly.css" />
+     <link rel="stylesheet" type="text/css" href="../ui/css/ipa.css" />
 diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
-index 838f7226bca66f4980c1144d7907bc42fcd31a22..bcf90a621ff052715951ed494d29c4d89742a458 100755
+index 6e55bbe3e57f1c609398dc571e90cb8677d91a33..2e235262ee1ed3aa084459a243c41a49f79b68fd 100755
 --- a/install/tools/ipa-adtrust-install
 +++ b/install/tools/ipa-adtrust-install
-@@ -225,11 +225,11 @@ def main():
+@@ -227,11 +227,11 @@ def main():
  
      print "=============================================================================="
      print "This program will setup components needed to establish trust to AD domains for"
@@ -140,7 +179,7 @@ index 838f7226bca66f4980c1144d7907bc42fcd31a22..bcf90a621ff052715951ed494d29c4d8
      #TODO:
      #print "  * Add a SID to all users and Posix groups"
      print ""
-@@ -398,7 +398,7 @@ You must make sure these network ports are open:
+@@ -429,7 +429,7 @@ You must make sure these network ports are open:
  \t  * 389: (C)LDAP
  \t  * 445: microsoft-ds
  
@@ -150,11 +189,11 @@ index 838f7226bca66f4980c1144d7907bc42fcd31a22..bcf90a621ff052715951ed494d29c4d8
  the following ports for these servers:
  \tTCP Ports:
 diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
-index 275e699ebc824e0eb454ac80089105c5e9ac2146..505f3d5b651c75df4f592f880bf29657c2f6b650 100755
+index 1d4db5f1fdff373bc0af725ee50f1210f3195b7d..cbf3faeef3644870b6978e02c95f67354cc7e61b 100755
 --- a/install/tools/ipa-dns-install
 +++ b/install/tools/ipa-dns-install
-@@ -112,7 +112,7 @@ def main():
-     fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+@@ -97,7 +97,7 @@ def main():
+     fstore = sysrestore.FileStore(paths.SYSRESTORE)
  
      print "=============================================================================="
 -    print "This program will setup DNS for the FreeIPA Server."
@@ -163,10 +202,10 @@ index 275e699ebc824e0eb454ac80089105c5e9ac2146..505f3d5b651c75df4f592f880bf29657
      print "This includes:"
      print "  * Configure DNS (bind)"
 diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
-index 583b5d5e75090483ddd9549862de04ea30fe820f..b2d4bc253e334ccce742489b376e29af649bd2e0 100755
+index 22348fc2158e59afc2e1aa51e3d3f51e90b99e39..e26e878c5b82b4e1e8a172a217b3225dcea642c4 100755
 --- a/install/tools/ipa-replica-conncheck
 +++ b/install/tools/ipa-replica-conncheck
-@@ -223,7 +223,7 @@ class PortResponder(threading.Thread):
+@@ -252,7 +252,7 @@ class PortResponder(threading.Thread):
                  ipautil.bind_port_responder(self.port,
                          self.port_type,
                          socket_timeout=self.socket_timeout,
@@ -176,10 +215,10 @@ index 583b5d5e75090483ddd9549862de04ea30fe820f..b2d4bc253e334ccce742489b376e29af
                  pass
              except socket.error, e:
 diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
-index 00aed1953f58c7f7c6a3c9bae8dcab8b8a669b62..fa9e4c47fe961c2296c5491ca19c61cc7869af0b 100755
+index 8f4cf457af54d47dbeda48f24a1b607e61106497..4fd4d8171ab89b805449a6625e9c5ea2d0921fa5 100755
 --- a/install/tools/ipa-server-install
 +++ b/install/tools/ipa-server-install
-@@ -730,7 +730,7 @@ def main():
+@@ -830,7 +830,7 @@ def main():
          external = 0
  
      print "=============================================================================="
@@ -189,7 +228,7 @@ index 00aed1953f58c7f7c6a3c9bae8dcab8b8a669b62..fa9e4c47fe961c2296c5491ca19c61cc
      print "This includes:"
      if setup_ca:
 diff --git a/install/tools/man/ipa-adtrust-install.1 b/install/tools/man/ipa-adtrust-install.1
-index 7f0566e135ce1eec049987ff99e922f76c53177b..3b591a033ee4639b951e15b937249c7890fbf3b6 100644
+index b0aa8ceefc34698329b2a13d3adbcb204f08b3a9..fe22b69ad7730b9c07c0e4cc8f8326b80738fe62 100644
 --- a/install/tools/man/ipa-adtrust-install.1
 +++ b/install/tools/man/ipa-adtrust-install.1
 @@ -16,7 +16,7 @@
@@ -235,7 +274,7 @@ index ff9759ec77d54f32532c4ececfa5081daab9ec15..476f9b534d514b03200369212807fc6d
  ipa\-backup \- Back up an IPA master
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-ca-install.1 b/install/tools/man/ipa-ca-install.1
-index 13ef43a80aa16afad8b7432ef2bce361e45d1fb8..0a6977dbf9780182f0d86564575433002ab50b71 100644
+index aa186987a15b5203607ac76e63751f01811c4bd7..c110db03ff48fd80b4dc70cf9d1c32d53d58b57b 100644
 --- a/install/tools/man/ipa-ca-install.1
 +++ b/install/tools/man/ipa-ca-install.1
 @@ -16,7 +16,7 @@
@@ -245,7 +284,7 @@ index 13ef43a80aa16afad8b7432ef2bce361e45d1fb8..0a6977dbf9780182f0d8656457543300
 -.TH "ipa-ca-install" "1" "Jun 17 2011" "FreeIPA" "FreeIPA Manual Pages"
 +.TH "ipa-ca-install" "1" "Jun 17 2011" "IPA" "IPA Manual Pages"
  .SH "NAME"
- ipa\-ca\-install \- Install a CA on a replica
+ ipa\-ca\-install \- Install a CA on a server
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-compat-manage.1 b/install/tools/man/ipa-compat-manage.1
 index f22b1743e31c3b07132acfcfdd8600544f9ace6c..26470331a127af9445c4473525434c237e23dbcf 100644
@@ -261,7 +300,7 @@ index f22b1743e31c3b07132acfcfdd8600544f9ace6c..26470331a127af9445c4473525434c23
  ipa\-compat\-manage \- Enables or disables the schema compatibility plugin
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-csreplica-manage.1 b/install/tools/man/ipa-csreplica-manage.1
-index ddb28da414ee12f4a8d09032b8b7346b2d3a06ea..ee1a030ace8dce345e66f42b37d2621d954083d9 100644
+index 3164ea60d67db99445dac168fad967cb48be428e..bdf70302e1743d0d94c0acad7e83b5a16026c643 100644
 --- a/install/tools/man/ipa-csreplica-manage.1
 +++ b/install/tools/man/ipa-csreplica-manage.1
 @@ -16,7 +16,7 @@
@@ -274,7 +313,7 @@ index ddb28da414ee12f4a8d09032b8b7346b2d3a06ea..ee1a030ace8dce345e66f42b37d2621d
  ipa\-csreplica\-manage \- Manage an IPA CS replica
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-dns-install.1 b/install/tools/man/ipa-dns-install.1
-index b0bdca94f4aea4a17fecc3362a92a9885bbafed0..68789506c11857190273d2ea67ce299517e3d338 100644
+index bde30cadba9b8b461f5373b734c3edf2faf9d0af..0e12918e5d906f0606e7fb6e19f2da25c91e2a3c 100644
 --- a/install/tools/man/ipa-dns-install.1
 +++ b/install/tools/man/ipa-dns-install.1
 @@ -16,7 +16,7 @@
@@ -287,7 +326,7 @@ index b0bdca94f4aea4a17fecc3362a92a9885bbafed0..68789506c11857190273d2ea67ce2995
  ipa\-dns\-install \- Add DNS as a service to an IPA server
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-ldap-updater.1 b/install/tools/man/ipa-ldap-updater.1
-index 37e200f520218150af4e1be63fc442131f908e27..23b8dc8177c85e351eae30a27e6001780ad267bb 100644
+index 79cc316501512879fa39ba4c15fd898b976eb25e..6d819cb531372e58c81eeb7e01ebfb9bb574169b 100644
 --- a/install/tools/man/ipa-ldap-updater.1
 +++ b/install/tools/man/ipa-ldap-updater.1
 @@ -16,7 +16,7 @@
@@ -325,6 +364,19 @@ index fa02cfc76fa6bd076ebddde702036fa0b36f1413..e25f53eddca6cf1da1b631c1bf4ae275
  .SH "NAME"
  ipa\-nis\-manage \- Enables or disables the NIS listener plugin
  .SH "SYNOPSIS"
+diff --git a/install/tools/man/ipa-otptoken-import.1 b/install/tools/man/ipa-otptoken-import.1
+index 920a08ca2c2f996d6281483f5c65bac6b412d6d5..fe91040fabd1cad7c395aafd6afc68ed816a1951 100644
+--- a/install/tools/man/ipa-otptoken-import.1
++++ b/install/tools/man/ipa-otptoken-import.1
+@@ -16,7 +16,7 @@
+ .\"
+ .\" Author: Nathaniel McCallum <npmccallum@redhat.com>
+ .\"
+-.TH "ipa-otptoken-import" "1" "Jun 12 2014" "FreeIPA" "FreeIPA Manual Pages"
++.TH "ipa-otptoken-import" "1" "Jun 12 2014" "IPA" "IPA Manual Pages"
+ .SH "NAME"
+ ipa\-otptoken\-import \- Imports OTP tokens from RFC 6030 XML file
+ .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-replica-conncheck.1 b/install/tools/man/ipa-replica-conncheck.1
 index 566322cf035bbb51d1ba8b14166a1b61375015da..7f220de96cc03a1f883f585740a82bff062f0ce9 100644
 --- a/install/tools/man/ipa-replica-conncheck.1
@@ -352,7 +404,7 @@ index 993606d83c8117b47b73bb13ac1e7431ba03f369..4452c807d963a4a501eeb802f1d96e57
  ipa\-replica\-install \- Create an IPA replica
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-replica-manage.1 b/install/tools/man/ipa-replica-manage.1
-index a981c72f59e23024110e0d9e8331cd50cbb22130..8703caa2baaf83211a5e64e4cd724c42a78a835f 100644
+index 8a7c78f39eeb6c7902ed99e7bed37e32eb0e92dc..2c162928dc7fa1567703019e2722a1c63914876d 100644
 --- a/install/tools/man/ipa-replica-manage.1
 +++ b/install/tools/man/ipa-replica-manage.1
 @@ -16,7 +16,7 @@
@@ -365,7 +417,7 @@ index a981c72f59e23024110e0d9e8331cd50cbb22130..8703caa2baaf83211a5e64e4cd724c42
  ipa\-replica\-manage \- Manage an IPA replica
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-replica-prepare.1 b/install/tools/man/ipa-replica-prepare.1
-index 88c30757b38cfdfec36dce85e995d419dd05c17b..24b6464d1683f23c1a95c952a27b8a92adfbf385 100644
+index 7931b71ed6fceab059a51496d9289ce25eb86b4e..fd07aa55c3d107378733d0eb3c1a6f0467182d2a 100644
 --- a/install/tools/man/ipa-replica-prepare.1
 +++ b/install/tools/man/ipa-replica-prepare.1
 @@ -16,7 +16,7 @@
@@ -391,7 +443,7 @@ index 31734b259524e4b07312a4009184e725aafc3728..689dc133fc4f526bffac0458b0c5c25f
  ipa\-restore \- Restore an IPA master
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-server-certinstall.1 b/install/tools/man/ipa-server-certinstall.1
-index ab293cf0fdcb2fb231c39f2a32eaa62842a94a94..023971db661d4c0bee495d14bd226534b50559c2 100644
+index d23bbd490e2b0454b8fb908e22f33c7a611c8874..d87b6bc16cfbea8f260d2767bf20eaac3562b050 100644
 --- a/install/tools/man/ipa-server-certinstall.1
 +++ b/install/tools/man/ipa-server-certinstall.1
 @@ -16,7 +16,7 @@
@@ -404,7 +456,7 @@ index ab293cf0fdcb2fb231c39f2a32eaa62842a94a94..023971db661d4c0bee495d14bd226534
  ipa\-server\-certinstall \- Install new SSL server certificates
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
-index 409dcf24beb6c53a9908437738fbbe3c90078367..807e1b38201c504b601a21751798a332d257e819 100644
+index 7343f323e5447c028bba36564172524690059342..1389f80f2e13f382b08b5b718b2d7eb46d3ff58e 100644
 --- a/install/tools/man/ipa-server-install.1
 +++ b/install/tools/man/ipa-server-install.1
 @@ -16,7 +16,7 @@
@@ -417,7 +469,7 @@ index 409dcf24beb6c53a9908437738fbbe3c90078367..807e1b38201c504b601a21751798a332
  ipa\-server\-install \- Configure an IPA server
  .SH "SYNOPSIS"
 diff --git a/install/tools/man/ipactl.8 b/install/tools/man/ipactl.8
-index 05be8e0e29f792ad2a2159ca3f8f38624a42ffa4..b9e4700858c7490298bac58c092fe97d2c6d3a19 100644
+index 5a1fd27ad6cb88877589173709c6cf0afa357fe1..0e6e339cef0a97c27b9e992a5082b2e47f00e7bd 100644
 --- a/install/tools/man/ipactl.8
 +++ b/install/tools/man/ipactl.8
 @@ -16,7 +16,7 @@
@@ -430,48 +482,48 @@ index 05be8e0e29f792ad2a2159ca3f8f38624a42ffa4..b9e4700858c7490298bac58c092fe97d
  ipactl \- IPA Server Control Interface
  .SH "SYNOPSIS"
 diff --git a/install/ui/index.html b/install/ui/index.html
-index 75ff829970a42c6efa0f62a61bf922d07fb779a5..7a71f815496a6651850d7076015f30c6df281fed 100644
+index ce9859074d52dd67a13afe823f2b0860eb9db8af..1ed43b0ca940d0ed8369e59cecac57cd236d8e58 100644
 --- a/install/ui/index.html
 +++ b/install/ui/index.html
 @@ -2,7 +2,7 @@
  <html>
  <head>
- <meta charset="utf-8">
--    <title>IPA: Identity Policy Audit</title>
-+    <title>Identity Management</title>
- 
- 
-     <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
-diff --git a/install/ui/login.html b/install/ui/login.html
-index 5545e8834a38fd24a6f0debf263a56402be42dbc..7b4d13962790e6b9457727424c37b41879a3404a 100644
---- a/install/ui/login.html
-+++ b/install/ui/login.html
-@@ -2,7 +2,7 @@
- <html>
- <head>
      <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
  
-     <link rel="stylesheet" type="text/css" href="ipa.css" />
- 
-diff --git a/install/ui/logout.html b/install/ui/logout.html
-index e356d2a5f9b59f0b516825fb039eaa4210dc5d98..80740069c9c3b3fa1b5ccbcf64487b4f1ab4a2cd 100644
---- a/install/ui/logout.html
-+++ b/install/ui/logout.html
+     <!--[if IE]>
+     <meta id="ie-detector">
+diff --git a/install/ui/reset_password.html b/install/ui/reset_password.html
+index ec09bbfafc1670df4bdb082c4f337be1ea81213f..998d796b7c1e6b8d3eb2e5273a897e99f1f56ca7 100644
+--- a/install/ui/reset_password.html
++++ b/install/ui/reset_password.html
 @@ -2,7 +2,7 @@
- <html>
+ <html class="login-pf">
  <head>
      <meta charset="utf-8">
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
+     <script type="text/javascript" src="js/libs/loader.js"></script>
+     <script type="text/javascript">
+         (function() {
+diff --git a/install/ui/src/freeipa/widgets/App.js b/install/ui/src/freeipa/widgets/App.js
+index b70b14a94eadc3788ed6c31132476e53986b3e77..164b499e7ef43508af7a1c423ed9ab9f30217c16 100644
+--- a/install/ui/src/freeipa/widgets/App.js
++++ b/install/ui/src/freeipa/widgets/App.js
+@@ -188,7 +188,7 @@ define(['dojo/_base/declare',
  
-     <link rel="stylesheet" type="text/css" href="ipa.css" />
+             construct.create('img', {
+                 src: 'images/header-logo.png',
+-                alt: 'FreeIPA' // TODO: replace with configuration value
++                alt: 'Identity Management' // TODO: replace with configuration value
+             }, this.brand_node);
  
-diff --git a/install/ui/reset_password.html b/install/ui/reset_password.html
-index 4dbbb7aacd52fe4ab787a8db73ca780225a98307..2d9c7aa7e704fa76ad5e1a93672626ad71b78568 100644
---- a/install/ui/reset_password.html
-+++ b/install/ui/reset_password.html
+             return this.brand_node;
+diff --git a/install/ui/sync_otp.html b/install/ui/sync_otp.html
+index 5814b6c578c250d253c8eabeff7a787f1b24f10b..36a51ca62899790da3b8788fcd8a32ffc7407375 100644
+--- a/install/ui/sync_otp.html
++++ b/install/ui/sync_otp.html
 @@ -2,7 +2,7 @@
  <html>
  <head>
@@ -479,10 +531,10 @@ index 4dbbb7aacd52fe4ab787a8db73ca780225a98307..2d9c7aa7e704fa76ad5e1a93672626ad
 -    <title>IPA: Identity Policy Audit</title>
 +    <title>Identity Management</title>
  
-     <link rel="stylesheet" type="text/css" href="ipa.css" />
- 
+     <!--[if IE]>
+     <meta id="ie-detector">
 diff --git a/ipa-client/man/default.conf.5 b/ipa-client/man/default.conf.5
-index 9e87bb7c8b0b2767b590e0b920a752f83a2fde51..315f15d75ecb10a30690adb41fa12837ca32a6c6 100644
+index dbc8a5b4647439de4de7c01152d098eb0561e236..65dd5b1c233b664a853ee44fcc3c3f89b143be65 100644
 --- a/ipa-client/man/default.conf.5
 +++ b/ipa-client/man/default.conf.5
 @@ -16,7 +16,7 @@
@@ -508,7 +560,7 @@ index 5b60503f1304d0a0b03a8862708ba126c50c7eff..2e6f78aa659e90f879f66431c4e52e30
  ipa\-client\-automount \- Configure automount and NFS for IPA
  .SH "SYNOPSIS"
 diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1
-index bb19041b13622e3384fb800fca60b7b6f695e8f0..17b0666232d95e84692a7ecba7cd7b7e6117b2e7 100644
+index 726a6c133132dd2e3ba2fde43d8a2ec0549bfcef..400be7a4baadd455a370e00bca05ac4f445efbe7 100644
 --- a/ipa-client/man/ipa-client-install.1
 +++ b/ipa-client/man/ipa-client-install.1
 @@ -16,7 +16,7 @@
@@ -521,7 +573,7 @@ index bb19041b13622e3384fb800fca60b7b6f695e8f0..17b0666232d95e84692a7ecba7cd7b7e
  ipa\-client\-install \- Configure an IPA client
  .SH "SYNOPSIS"
 diff --git a/ipa-client/man/ipa-getkeytab.1 b/ipa-client/man/ipa-getkeytab.1
-index ce62d9d09df07401a4d067e9247035ca6f957b83..07f0f05b604a6bf50f6149e1d3699d4643013b82 100644
+index bb84ad8f2b29f0753d48f480fc571ed6122ba539..349da64c82cfc53549ef666074e89d83a24d74e0 100644
 --- a/ipa-client/man/ipa-getkeytab.1
 +++ b/ipa-client/man/ipa-getkeytab.1
 @@ -17,7 +17,7 @@
@@ -533,8 +585,17 @@ index ce62d9d09df07401a4d067e9247035ca6f957b83..07f0f05b604a6bf50f6149e1d3699d46
  .SH "NAME"
  ipa\-getkeytab \- Get a keytab for a Kerberos principal
  .SH "SYNOPSIS"
+@@ -99,7 +99,7 @@ The LDAP password to use when not binding with Kerberos.
+ \fB\-r\fR
+ Retrieve mode. Retrieve an existing key from the server instead of generating a
+ new one. This is incompatibile with the \-\-password option, and will work only
+-against a FreeIPA server more recent than version 3.3. The user requesting the
++against a IPA server more recent than version 3.3. The user requesting the
+ keytab must have access to the keys for this operation to succeed.
+ .SH "EXAMPLES"
+ Add and retrieve a keytab for the NFS service principal on
 diff --git a/ipa-client/man/ipa-join.1 b/ipa-client/man/ipa-join.1
-index 5dd4004b36c096bbccf1cd966e3f189fa2e356ca..86272b6409b8966348969e998848fac5039193db 100644
+index d881607842bb0227c2da863bd1674db01530e910..30b667558ba3105cf320896ef40b0661a18066f5 100644
 --- a/ipa-client/man/ipa-join.1
 +++ b/ipa-client/man/ipa-join.1
 @@ -16,7 +16,7 @@
@@ -559,6 +620,59 @@ index 4f4fcee2665c105c5cdab5f964e3295bea4b7997..84d8abd548b873213d165fe5fb012ec0
  .SH "NAME"
  ipa\-rmkeytab \- Remove a kerberos principal from a keytab
  .SH "SYNOPSIS"
+diff --git a/ipa.1 b/ipa.1
+index ec7e5da7077a41095fdaa75babb1b680f3522f7f..f53e815d26e5a3f4843a220012240a775387195e 100644
+--- a/ipa.1
++++ b/ipa.1
+@@ -16,7 +16,7 @@
+ .\"
+ .\" Author: Pavel Zuna <pzuna@redhat.com>
+ .\"
+-.TH "ipa" "1" "Jan 24 2012" "FreeIPA" "FreeIPA Manual Pages"
++.TH "ipa" "1" "Jan 24 2012" "IPA" "IPA Manual Pages"
+ .SH "NAME"
+ ipa \- IPA command\-line interface
+ .SH "SYNOPSIS"
+diff --git a/ipaserver/advise/plugins/legacy_clients.py b/ipaserver/advise/plugins/legacy_clients.py
+index 6d17f7ecaa5d022190a9f8983e3ea6ab9a66f694..7d5efe14ee70abd4e09eaddfacb23ca54d065c75 100644
+--- a/ipaserver/advise/plugins/legacy_clients.py
++++ b/ipaserver/advise/plugins/legacy_clients.py
+@@ -85,7 +85,7 @@ class config_redhat_sssd_before_1_9(config_base_legacy_client):
+     Legacy client configuration for Red Hat based systems, using SSSD.
+     """
+     description = ('Instructions for configuring a system with an old version '
+-                   'of SSSD (1.5-1.8) as a FreeIPA client. This set of '
++                   'of SSSD (1.5-1.8) as a IPA client. This set of '
+                    'instructions is targeted for platforms that include '
+                    'the authconfig utility, which are all Red Hat based '
+                    'platforms.')
+@@ -122,7 +122,7 @@ class config_generic_linux_sssd_before_1_9(config_base_legacy_client):
+     using SSSD.
+     """
+     description = ('Instructions for configuring a system with an old version '
+-                   'of SSSD (1.5-1.8) as a FreeIPA client. This set of '
++                   'of SSSD (1.5-1.8) as a IPA client. This set of '
+                    'instructions is targeted for linux systems that do not '
+                    'include the authconfig utility.')
+ 
+@@ -179,7 +179,7 @@ class config_redhat_nss_pam_ldapd(config_base_legacy_client):
+     using nss-pam-ldapd.
+     """
+     description = ('Instructions for configuring a system with nss-pam-ldapd '
+-                   'as a FreeIPA client. This set of instructions is targeted '
++                   'as a IPA client. This set of instructions is targeted '
+                    'for platforms that include the authconfig utility, which '
+                    'are all Red Hat based platforms.')
+ 
+@@ -352,7 +352,7 @@ class config_redhat_nss_ldap(config_base_legacy_client):
+     using nss-ldap.
+     """
+     description = ('Instructions for configuring a system with nss-ldap '
+-                   'as a FreeIPA client. This set of instructions is targeted '
++                   'as a IPA client. This set of instructions is targeted '
+                    'for platforms that include the authconfig utility, which '
+                    'are all Red Hat based platforms.')
+ 
 -- 
-1.8.3.1
+2.1.0
 
diff --git a/SOURCES/1005-Remove-pylint-from-build-process.patch b/SOURCES/1005-Remove-pylint-from-build-process.patch
index d74e340..94732b8 100644
--- a/SOURCES/1005-Remove-pylint-from-build-process.patch
+++ b/SOURCES/1005-Remove-pylint-from-build-process.patch
@@ -1,7 +1,7 @@
-From d48ef24f108af76f950fc67cd728d5eeee1221c4 Mon Sep 17 00:00:00 2001
+From c920c528ba53161a8186b914da9f93b8cb5176fc Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
-Date: Wed, 22 May 2013 10:52:32 +0200
-Subject: [PATCH 1005/1006] Remove pylint from build process
+Date: Fri, 5 Sep 2014 11:48:20 +0200
+Subject: [PATCH] Remove pylint from build process
 
 pylint is not present in RHEL-7.0.
 ---
@@ -9,10 +9,10 @@ pylint is not present in RHEL-7.0.
  1 file changed, 4 deletions(-)
 
 diff --git a/Makefile b/Makefile
-index 484144fd6f2dfb905abfc96621fc03b306d2f230..0718367cd78e070e160d50f28006ded580be78cf 100644
+index 8fd0c60e392d720f47c8ee7c4b674727dc5eb789..29dc07c64b8e88caaa11764557af34fd53139274 100644
 --- a/Makefile
 +++ b/Makefile
-@@ -46,9 +46,6 @@ IPA_RPM_RELEASE=$(shell cat RELEASE)
+@@ -48,9 +48,6 @@ IPA_RPM_RELEASE=$(shell cat RELEASE)
  LIBDIR ?= /usr/lib
  
  DEVELOPER_MODE ?= 0
@@ -20,9 +20,9 @@ index 484144fd6f2dfb905abfc96621fc03b306d2f230..0718367cd78e070e160d50f28006ded5
 -LINT_OPTIONS=--no-fail
 -endif
  
- PYTHON ?= $(shell rpm -E %__python)
+ PYTHON ?= $(shell rpm -E %__python || echo /usr/bin/python2)
  
-@@ -97,7 +94,6 @@ client-dirs:
+@@ -115,7 +112,6 @@ client-dirs:
  	fi
  
  lint: bootstrap-autogen
@@ -31,5 +31,5 @@ index 484144fd6f2dfb905abfc96621fc03b306d2f230..0718367cd78e070e160d50f28006ded5
  
  
 -- 
-1.8.3.1
+2.1.0
 
diff --git a/SOURCES/1006-Remove-i18test-from-build-process.patch b/SOURCES/1006-Remove-i18test-from-build-process.patch
index aee4946..baeb2af 100644
--- a/SOURCES/1006-Remove-i18test-from-build-process.patch
+++ b/SOURCES/1006-Remove-i18test-from-build-process.patch
@@ -1,7 +1,7 @@
-From 87a676e2d02194a37343e32660a2228b92f56ea9 Mon Sep 17 00:00:00 2001
+From 55cacef4a5b893b59e4d29e5d02a2af7e6c88c7e Mon Sep 17 00:00:00 2001
 From: Martin Kosek <mkosek@redhat.com>
 Date: Wed, 22 May 2013 11:55:06 +0200
-Subject: [PATCH 1006/1006] Remove i18test from build process
+Subject: [PATCH] Remove i18test from build process
 
 Required package python-polib is not present in RHEL-7.0.
 ---
@@ -9,10 +9,10 @@ Required package python-polib is not present in RHEL-7.0.
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/Makefile b/Makefile
-index 0718367cd78e070e160d50f28006ded580be78cf..f53fcd8ff79289e867e17c71dcb3fc7b38e40c63 100644
+index 29dc07c64b8e88caaa11764557af34fd53139274..8c2237b94183c44bf8aa2aa39fecef252e1860e8 100644
 --- a/Makefile
 +++ b/Makefile
-@@ -94,7 +94,7 @@ client-dirs:
+@@ -112,7 +112,7 @@ client-dirs:
  	fi
  
  lint: bootstrap-autogen
@@ -22,5 +22,5 @@ index 0718367cd78e070e160d50f28006ded580be78cf..f53fcd8ff79289e867e17c71dcb3fc7b
  
  test:
 -- 
-1.8.3.1
+2.1.0
 
diff --git a/SOURCES/1007-Do-not-build-tests.patch b/SOURCES/1007-Do-not-build-tests.patch
new file mode 100644
index 0000000..72c449f
--- /dev/null
+++ b/SOURCES/1007-Do-not-build-tests.patch
@@ -0,0 +1,35 @@
+From a9fb3ae5890086ab09ed88aa99410eb09d5812c2 Mon Sep 17 00:00:00 2001
+From: Martin Kosek <mkosek@redhat.com>
+Date: Mon, 15 Sep 2014 10:21:40 +0200
+Subject: [PATCH] Do not build tests
+
+Tests have been moved to other SRPM.
+---
+ Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 8c2237b94183c44bf8aa2aa39fecef252e1860e8..04e28ec3e2f1c4b68bb0416dc61f2d17b563c739 100644
+--- a/Makefile
++++ b/Makefile
+@@ -59,7 +59,7 @@ export CFLAGS
+ #JAVA_STACK_SIZE ?= 8m
+ #export JAVA_STACK_SIZE
+ 
+-all: bootstrap-autogen server tests
++all: bootstrap-autogen server
+ 	@for subdir in $(SUBDIRS); do \
+ 		(cd $$subdir && $(MAKE) $@) || exit 1; \
+ 	done
+@@ -84,7 +84,7 @@ client-autogen: version-update
+ tests-man-autogen: version-update
+ 	cd ipatests/man; if [ ! -e Makefile ]; then ../../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi
+ 
+-install: all server-install tests-install
++install: all server-install
+ 	@for subdir in $(SUBDIRS); do \
+ 		(cd $$subdir && $(MAKE) $@) || exit 1; \
+ 	done
+-- 
+2.1.0
+
diff --git a/SOURCES/1007-Remove-ipa-backup-and-ipa-restore-functionality.patch b/SOURCES/1007-Remove-ipa-backup-and-ipa-restore-functionality.patch
deleted file mode 100644
index 2241ab2..0000000
--- a/SOURCES/1007-Remove-ipa-backup-and-ipa-restore-functionality.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From fb6ff1a18bc4ffe88a98fb7b5ffe23fefe103da9 Mon Sep 17 00:00:00 2001
-From: Martin Kosek <mkosek@redhat.com>
-Date: Mon, 23 Sep 2013 13:10:26 +0200
-Subject: [PATCH] Remove ipa-backup and ipa-restore functionality
-
-https://bugzilla.redhat.com/show_bug.cgi?id=1003933
----
- install/tools/Makefile.am     | 2 --
- install/tools/man/Makefile.am | 2 --
- 2 files changed, 4 deletions(-)
-
-diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am
-index 2cf66c6dfc1c272bb423253902e7339e7d159567..0eb3a6b6122b3eea8539ae9a913a0f2c6cb23698 100644
---- a/install/tools/Makefile.am
-+++ b/install/tools/Makefile.am
-@@ -21,8 +21,6 @@ sbin_SCRIPTS =			\
- 	ipa-managed-entries     \
- 	ipa-ldap-updater	\
- 	ipa-upgradeconfig	\
--	ipa-backup		\
--	ipa-restore		\
- 	ipa-advise		\
- 	$(NULL)
- 
-diff --git a/install/tools/man/Makefile.am b/install/tools/man/Makefile.am
-index 33e8a9e4b3408cc5447c8cad9a289ddd6ae1ebd7..ee208783ccb9daa600610abd4a83236ede92066a 100644
---- a/install/tools/man/Makefile.am
-+++ b/install/tools/man/Makefile.am
-@@ -19,8 +19,6 @@ man1_MANS = 				\
- 	ipa-compat-manage.1		\
- 	ipa-nis-manage.1		\
- 	ipa-managed-entries.1		\
--	ipa-backup.1			\
--	ipa-restore.1			\
- 	ipa-advise.1			\
-         $(NULL)
- 
--- 
-1.8.3.1
-
diff --git a/SOURCES/1008-RCUE.patch b/SOURCES/1008-RCUE.patch
new file mode 100644
index 0000000..e556202
--- /dev/null
+++ b/SOURCES/1008-RCUE.patch
@@ -0,0 +1,196 @@
+From c9ab8eff958d8f66b2b6563234dd89fd4c4b987b Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Mon, 8 Sep 2014 20:13:09 +0200
+Subject: [PATCH] RCUE
+
+---
+ install/ui/css/patternfly.css   |   2 +-
+ install/ui/less/brand.less      | 101 +++++++++++++++++++---------------------
+ install/ui/less/patternfly.less |  48 ++++++++++++++++++-
+ 3 files changed, 96 insertions(+), 55 deletions(-)
+
+diff --git a/install/ui/css/patternfly.css b/install/ui/css/patternfly.css
+index b8549933ff5fd6d3e3382281b6ed02ba029421a8..687a31bff14043ba0beee0b5c0948135bf265fc2 100644
+--- a/install/ui/css/patternfly.css
++++ b/install/ui/css/patternfly.css
+@@ -4,4 +4,4 @@
+  *
+  * Copyright 2013 bootstrap-select
+  * Licensed under the MIT license
+- */.bootstrap-select.btn-group,.bootstrap-select.btn-group[class*=span]{float:none;display:inline-block;margin-bottom:10px;margin-left:0}.form-search .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group{margin-bottom:0}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.btn-group.pull-right,.bootstrap-select.btn-group[class*=span].pull-right,.row-fluid .bootstrap-select.btn-group[class*=span].pull-right{float:right}.input-append .bootstrap-select.btn-group{margin-left:-1px}.input-prepend .bootstrap-select.btn-group{margin-right:-1px}.bootstrap-select:not([class*=span]):not([class*=col-]):not([class*=form-control]){width:220px}.bootstrap-select{width:220px\0}.bootstrap-select.form-control:not([class*=span]){width:100%}.bootstrap-select>.btn{width:100%}.error .bootstrap-select .btn{border:1px solid #b94a48}.dropdown-menu{z-index:2000}.bootstrap-select.show-menu-arrow.open>.btn{z-index:2051}.bootstrap-select .btn:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.btn-group .btn .filter-option{overflow:hidden;position:absolute;left:12px;right:25px;text-align:left}.bootstrap-select.btn-group .btn .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group>.disabled,.bootstrap-select.btn-group .dropdown-menu li.disabled>a{cursor:not-allowed}.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group[class*=span] .btn{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;border:0;padding:0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu dt{display:block;padding:3px 20px;cursor:default}.bootstrap-select.btn-group .div-contain{overflow:hidden}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li>a.opt{position:relative;padding-left:35px}.bootstrap-select.btn-group .dropdown-menu li>a{cursor:pointer}.bootstrap-select.btn-group .dropdown-menu li>dt small{font-weight:400}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a i.check-mark{display:inline-block;position:absolute;right:15px;margin-top:2.5px}.bootstrap-select.btn-group .dropdown-menu li a i.check-mark{display:none}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:hover small,.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:focus small,.bootstrap-select.btn-group .dropdown-menu li.active:not(.disabled)>a small{color:#64b1d8;color:rgba(255,255,255,.4)}.bootstrap-select.btn-group .dropdown-menu li>dt small{font-weight:400}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #CCC;border-bottom-color:rgba(0,0,0,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,.2)}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after{display:block}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px}.mobile-device{position:absolute;top:0;left:0;display:block!important;width:100%;height:100%!important;opacity:0}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select.btn-group.fit-width .btn .filter-option{position:static}.bootstrap-select.btn-group.fit-width .btn .caret{position:static;top:auto;margin-top:-1px}.control-group.error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select-searchbox{padding:4px 8px}.bootstrap-select-searchbox input{margin-bottom:0}.alert{border-width:2px;padding-left:34px;position:relative}.alert .alert-link{color:#0099d3}.alert .alert-link:hover{color:#00618a}.alert>.pficon,.alert>.pficon-layered{font-size:20px;position:absolute;left:7px;top:7px}.alert .pficon-info{color:#72767b}.alert-dismissable .close{right:-16px;top:1px}.badge{margin-left:6px}.nav-pills>li>a>.badge{margin-left:6px}.bootstrap-select.btn-group .btn .caret{font-size:16px;margin-top:-4px}.bootstrap-select.btn-group .dropdown-menu>.active>a:hover{background-color:#0099d3!important;border-color:#0076b7!important}.bootstrap-select.btn-group .dropdown-menu>.active>a:hover small{color:rgba(225,255,255,.4)!important}.bootstrap-select.btn-group .dropdown-menu dt{color:#969696;font-weight:400;padding:1px 10px}.bootstrap-select.btn-group .dropdown-menu li>a.opt{padding:1px 10px}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:focus small{color:rgba(225,255,255,.4)!important}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:active small,.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:hover small{color:#999}.breadcrumb{padding-left:0}.breadcrumb>.active strong{font-weight:600}.breadcrumb>li+li:before{color:#999;content:"\f101";font-family:FontAwesome;font-size:11px;padding:0 9px 0 7px}.btn{-webkit-box-shadow:0 2px 3px rgba(0,0,0,.1);box-shadow:0 2px 3px rgba(0,0,0,.1)}.btn:active{-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{background-color:#f8f8f8!important;background-image:none!important;border-color:#d1d1d1!important;color:#969696!important;opacity:1}.btn.disabled:active,.btn[disabled]:active,fieldset[disabled] .btn:active{-webkit-box-shadow:none;box-shadow:none}.btn.disabled.btn-link,.btn[disabled].btn-link,fieldset[disabled] .btn.btn-link{background-color:transparent!important;border:0}.btn-danger{background-color:#ab070f;background-image:-webkit-linear-gradient(top,#d60915 0,#ac0710 100%);background-image:linear-gradient(to bottom,#d60915 0,#ac0710 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd60915', endColorstr='#ffac0710', GradientType=0);border-color:#781919;color:#fff}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-color:#ab070f;background-image:none;border-color:#781919;color:#fff}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#ab070f;border-color:#781919}.btn-default{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#eee;border-color:#b7b7b7}.btn-link,.btn-link:active{-webkit-box-shadow:none;box-shadow:none}.btn-primary{background-color:#189ad1;background-image:-webkit-linear-gradient(top,#1cace8 0,#1998cc 100%);background-image:linear-gradient(to bottom,#1cace8 0,#1998cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1cace8', endColorstr='#ff1998cc', GradientType=0);border-color:#267da1;color:#fff}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-color:#189ad1;background-image:none;border-color:#267da1;color:#fff}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#189ad1;border-color:#267da1}.btn-xs,.btn-group-xs .btn,.btn-group-xs>.btn{font-weight:400}.close{text-shadow:none;opacity:.6;filter:alpha(opacity=60)}.close:hover,.close:focus{opacity:.9;filter:alpha(opacity=90)}.input-group-pf>.input-group-btn{position:static}.ie8 .input-group-pf .input-group-btn .dropdown-toggle{margin-left:-1px}.dataTables_header{background-color:#f6f6f6;border:1px solid #d1d1d1;border-bottom:none;padding:5px;position:relative;text-align:center}.dataTables_header .dataTables_filter{position:absolute}.dataTables_header .dataTables_filter input{border:1px solid #bbb;height:24px}@media (max-width:767px){.dataTables_header .dataTables_filter input{width:100px}}.dataTables_header .dataTables_info{padding:2px 0}@media (max-width:480px){.dataTables_header .dataTables_info{text-align:right}}.dataTables_header .dataTables_info b{font-weight:700}.dataTables_footer{background-color:#fff;border:1px solid #d1d1d1;border-top:none;overflow:hidden}.dataTables_paginate{background:#fafafa;float:right;margin:0}.dataTables_paginate .pagination{float:left;margin:0}.dataTables_paginate .pagination>li>span{border-color:#fff #e1e1e1 #f4f4f4;border-width:0 1px;font-size:16px;font-weight:400;padding:0;text-align:center;width:31px}.dataTables_paginate .pagination>li>span:hover,.dataTables_paginate .pagination>li>span:focus{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dataTables_paginate .pagination>li.last>span{border-right:none}.dataTables_paginate .pagination>li.disabled>span{background:#f5f5f5;border-left-color:#ececec;border-right-color:#ececec;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dataTables_paginate .pagination-input{float:left;font-size:12px;line-height:1em;padding:4px 15px 0;text-align:right}.dataTables_paginate .pagination-input .paginate_input{border:1px solid #d3d3d3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);font-size:12px;font-weight:600;height:19px;margin-right:8px;padding-right:3px;text-align:right;width:30px}.dataTables_paginate .pagination-input .paginate_of{position:relative}.dataTables_paginate .pagination-input .paginate_of b{margin-left:3px}.dataTables_wrapper{margin:20px 0}@media (max-width:767px){.dataTables_wrapper .table-responsive{margin-bottom:0}}table.datatable{margin-bottom:0;max-width:none!important}table.datatable thead .sorting,table.datatable thead .sorting_asc,table.datatable thead .sorting_desc,table.datatable thead .sorting_asc_disabled,table.datatable thead .sorting_desc_disabled{cursor:pointer;*cursor:hand}table.datatable thead .sorting_asc,table.datatable thead .sorting_desc{border:0;color:#0099d3!important;display:block;position:relative}table.datatable thead .sorting_asc:after,table.datatable thead .sorting_desc:after{content:"\f107";font-family:FontAwesome;font-size:10px;font-weight:400;height:9px;left:7px;line-height:12px;position:relative;top:2px;vertical-align:baseline;width:12px}table.datatable thead .sorting_asc:before,table.datatable thead .sorting_desc:before{background:#0099d3;content:'';height:2px;position:absolute;left:0;top:0;width:100%}table.datatable thead .sorting_asc:after{content:"\f106";top:-3px}table.datatable th:active{outline:0}.caret{font-family:FontAwesome;font-weight:400;height:9px;position:relative;vertical-align:baseline;width:12px}.caret:before{bottom:0;content:"\f107";left:0;line-height:12px;position:absolute;text-align:center;top:-1px;right:0}.dropdown-menu .divider{background-color:#e5e5e5;height:1px;margin:4px 1px;overflow:hidden}.dropdown-menu>li>a{border-color:transparent;border-style:solid;border-width:1px 0;padding:1px 10px}.dropdown-menu>li>a:hover{border-color:#b3d3e7;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:active{background-color:#0099d3;border-color:#0076b7;color:#fff!important;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#0099d3!important;border-color:#0076b7!important;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{border-color:transparent}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{border-color:transparent}.dropdown-header{padding-left:10px;padding-right:10px;text-transform:uppercase}.btn-group>.dropdown-menu,.input-group-btn>.dropdown-menu{margin-top:-1px}.dropup .dropdown-menu{margin-bottom:-1px}.dropdown-submenu{position:relative}.dropdown-submenu:hover>a{background-color:#d4edfa;border-color:#b3d3e7}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu.pull-left{float:none!important}.dropdown-submenu.pull-left>.dropdown-menu{left:auto;margin-left:10px;right:100%}.dropdown-submenu>a{padding-right:20px!important}.dropdown-submenu>a:after{content:"\f105";font-family:FontAwesome;display:block;position:absolute;right:10px;top:2px}.dropdown-submenu>.dropdown-menu{left:100%;margin-top:0;top:-6px}.dropup .dropdown-submenu>.dropdown-menu{bottom:-5px;top:auto}.open .dropdown-submenu.active>.dropdown-menu{display:block}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local('Open Sans'),local('OpenSans'),url(../fonts/open-sans/OpenSans-Regular.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:local('OpenSans-Light'),local('Open Sans Light'),url(../fonts/open-sans/OpenSans-Light.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:local('Open Sans Semibold'),local('OpenSans-Semibold'),url(../fonts/open-sans/OpenSans-Semibold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local('Open Sans Bold'),local('OpenSans-Bold'),url(../fonts/open-sans/OpenSans-Bold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:800;src:local('Open Sans Extrabold'),local('OpenSans-Extrabold'),url(../fonts/open-sans/OpenSans-ExtraBold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:local('Open Sans Light Italic'),local('OpenSansLight-Italic'),url(../fonts/open-sans/OpenSans-LightItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:local('Open Sans Italic'),local('OpenSans-Italic'),url(../fonts/open-sans/OpenSans-Italic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:local('Open Sans Semibold Italic'),local('OpenSans-SemiboldItalic'),url(../fonts/open-sans/OpenSans-SemiboldItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:700;src:local('Open Sans Bold Italic'),local('OpenSans-BoldItalic'),url(../fonts/open-sans/OpenSans-BoldItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:800;src:local('Open Sans Extrabold Italic'),local('OpenSans-ExtraboldItalic'),url(../fonts/open-sans/OpenSans-ExtraBoldItalic.ttf) format('truetype')}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{border-color:#d4d4d4!important;-webkit-box-shadow:none;box-shadow:none;color:#969696}.form-control:hover{border-color:#7BB2DD}.input-group .input-group-btn .btn{-webkit-box-shadow:none;box-shadow:none}label{font-weight:600}.navbar-nav>li>.dropdown-menu.infotip{border-top-width:1px!important;margin-top:10px}@media (max-width:767px){.navbar-pf .navbar-nav .open .dropdown-menu.infotip{background-color:#fff!important;margin-top:0}}.infotip{-webkit-box-shadow:0 2px 2px rgba(0,0,0,.08);box-shadow:0 2px 2px rgba(0,0,0,.08);min-width:235px;padding:0}.infotip .list-group{border-top:0;margin:0;padding:8px 0}.infotip .list-group .list-group-item{border:none;margin:0 15px 0 34px;padding:5px 0}.infotip .list-group .list-group-item>.i{color:#4d5258;font-size:13px;left:-20px;position:absolute;top:8px}.infotip .list-group .list-group-item>a{color:#4d5258;line-height:13px}.infotip .list-group .list-group-item>.close{float:right}.infotip .footer{background-color:#f5f5f5;padding:6px 15px}.infotip .footer a:hover{color:#0099d3}.infotip .arrow,.infotip .arrow:after{border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0}.infotip .arrow{border-width:11px}.infotip .arrow:after{border-width:10px;content:""}.infotip.bottom-right .arrow,.infotip.bottom .arrow{border-bottom-color:#999;border-bottom-color:#bbb;border-top-width:0;left:50%;margin-left:-11px;top:-11px}.infotip.bottom-right .arrow:after,.infotip.bottom .arrow:after{border-top-width:0;border-bottom-color:#fff;content:" ";margin-left:-10px;top:1px}.infotip.bottom-right .arrow{left:80%}.infotip.top .arrow{border-bottom-width:0;border-top-color:#999;border-top-color:#bbb;bottom:-11px;left:50%;margin-left:-11px}.infotip.top .arrow:after{border-bottom-width:0;border-top-color:#f5f5f5;bottom:1px;content:" ";margin-left:-10px}.infotip.right .arrow{border-left-width:0;border-right-color:#999;border-right-color:#bbb;left:-11px;margin-top:-11px;top:50%}.infotip.right .arrow:after{bottom:-10px;border-left-width:0;border-right-color:#fff;content:" ";left:1px}.infotip.left .arrow{border-left-color:#999;border-left-color:#bbb;border-right-width:0;margin-top:-11px;right:-11px;top:50%}.infotip.left .arrow:after{border-left-color:#fff;border-right-width:0;bottom:-10px;content:" ";right:1px}.label{border-radius:0;font-size:100%;font-weight:600}h1 .label,h2 .label,h3 .label,h4 .label,h5 .label,h6 .label{font-size:75%}.list-group{border-top:1px solid #e9e8e8}.list-group .list-group-item:first-child{border-top:0}.list-group-item{border-left:0;border-right:0}.list-group-item-heading{font-weight:700}.login-pf{height:100%}.login-pf #brand{position:relative;top:-70px}.login-pf #brand img{display:block;height:18px;margin:0 auto;max-width:100%}@media (min-width:768px){.login-pf #brand img{margin:0;text-align:left}}.login-pf #badge{display:block;margin:20px auto 70px;position:relative;text-align:center}@media (min-width:768px){.login-pf #badge{float:right;margin-right:64px;margin-top:50px}}.login-pf body{background:#080808 url(../img/bg-login.jpg) repeat-x 50% 0;background-size:auto;color:#fff}@media (min-width:768px){.login-pf body{background-size:100% auto}}.login-pf .container{background-color:#181818;background-color:rgba(255,255,255,.055);clear:right;padding-bottom:40px;padding-top:20px;width:auto}@media (min-width:768px){.login-pf .container{bottom:13%;padding-left:80px;position:absolute;width:100%}}.login-pf .container .details p:first-child{border-top:1px solid #474747;padding-top:25px;margin-top:25px}@media (min-width:768px){.login-pf .container .details{border-left:1px solid #474747;padding-left:40px}.login-pf .container .details p:first-child{border-top:0;padding-top:0;margin-top:0}}.login-pf .container .details p{margin-bottom:2px}.login-pf .container .form-horizontal .control-label{font-size:13px;font-weight:400;text-align:left}.login-pf .container .form-horizontal .form-group:last-child,.login-pf .container .form-horizontal .form-group:last-child .help-block:last-child{margin-bottom:0}.login-pf .container .help-block{color:#fff}@media (min-width:768px){.login-pf .container .login{padding-right:40px}}.login-pf .container .submit{text-align:right}.ie8.login-pf #badge{background:url(../img/logo.png) no-repeat;height:69px;width:73px}.ie8.login-pf #badge img{width:0}.ie8.login-pf #brand{background:url(../img/brand-lg.png) no-repeat center;background-size:cover auto}@media (min-width:768px){.ie8.login-pf #brand{background-position:0 0}}.ie8.login-pf #brand img{width:0}.modal-header{background-color:#f8f8f8;border-bottom:none;padding:10px 18px}.modal-header .close{margin-top:2px}.modal-title{font-size:13px;font-weight:700}.modal-footer{border-top:none;margin-top:15px;padding:19px 20px 20px}.modal-footer>.btn{padding-left:10px;padding-right:10px}.modal-footer>.btn>.fa-angle-left{margin-right:5px}.modal-footer>.btn>.fa-angle-right{margin-left:5px}.navbar-pf{background:#030303;border:0;border-radius:0;border-top:3px solid #199dde;margin-bottom:0;min-height:0}.navbar-pf .navbar-brand{color:#f1f1f1;height:auto;padding:12px 0;margin:0 0 0 20px}.ie8 .navbar-pf .navbar-brand{background:url(../img/brand.png) no-repeat 0 49%;min-width:270px}.navbar-pf .navbar-brand img{display:block}.ie8 .navbar-pf .navbar-brand img{height:10px;width:0}.navbar-pf .navbar-collapse{border-top:0;-webkit-box-shadow:none;box-shadow:none;padding:0}.navbar-pf .navbar-header{border-bottom:1px solid #292929;float:none}.navbar-pf .navbar-nav{margin:0}.navbar-pf .navbar-nav>.active>a,.navbar-pf .navbar-nav>.active>a:hover,.navbar-pf .navbar-nav>.active>a:focus{background-color:#232323;color:#f1f1f1}.navbar-pf .navbar-nav>li>a{color:#cfcfcf;line-height:1;padding:10px 20px;text-shadow:none}.navbar-pf .navbar-nav>li>a:hover,.navbar-pf .navbar-nav>li>a:focus{color:#f1f1f1}.navbar-pf .navbar-nav>.open>a,.navbar-pf .navbar-nav>.open>a:hover,.navbar-pf .navbar-nav>.open>a:focus{background-color:#232323;color:#f1f1f1}@media (max-width:767px){.navbar-pf .navbar-nav .active .navbar-persistent,.navbar-pf .navbar-nav .active .dropdown-menu,.navbar-pf .navbar-nav .open .dropdown-menu{background-color:#171717!important;margin-left:0;padding-bottom:0;padding-top:0}.navbar-pf .navbar-nav .active .navbar-persistent>.active>a,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a,.navbar-pf .navbar-nav .active .navbar-persistent>.active>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .active .navbar-persistent>.active>a:focus,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a:focus,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a:focus,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a:focus,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a:focus{background-color:#1f1f1f!important;color:#f1f1f1}.navbar-pf .navbar-nav .active .navbar-persistent>li>a,.navbar-pf .navbar-nav .active .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu>li>a{background-color:transparent;border:0;color:#cfcfcf;outline:0;padding-left:30px}.navbar-pf .navbar-nav .active .navbar-persistent>li>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu>li>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu>li>a:hover{color:#f1f1f1}.navbar-pf .navbar-nav .active .navbar-persistent .divider,.navbar-pf .navbar-nav .active .dropdown-menu .divider,.navbar-pf .navbar-nav .open .dropdown-menu .divider{background-color:#292929;margin:0 1px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-header,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-header,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-header{padding-bottom:0;padding-left:30px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open .dropdown-toggle,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open .dropdown-toggle,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open .dropdown-toggle{color:#f1f1f1}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.pull-left,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.pull-left,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.pull-left{float:none!important}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu>a:after,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu>a:after,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu>a:after{display:none}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-header,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-header,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-header{padding-left:45px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu{border:0;bottom:auto;-webkit-box-shadow:none;box-shadow:none;display:block;float:none;margin:0;min-width:0;padding:0;position:relative;left:auto;right:auto;top:auto}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu>li>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu>li>a{padding:5px 15px 5px 45px;line-height:20px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu .dropdown-menu>li>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu .dropdown-menu>li>a{padding-left:60px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open .dropdown-menu{display:block}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu>a:after{display:inline-block!important;position:relative;right:auto;top:1px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu{display:none}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-submenu>a:after{display:none!important}}.navbar-pf .navbar-persistent{display:none}.navbar-pf .active>.navbar-persistent{display:block}.navbar-pf .navbar-primary{float:none}.navbar-pf .navbar-primary .context{border-bottom:1px solid #292929}.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a{position:relative}.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a:after{content:"\f107";display:inline-block;font-family:FontAwesome;font-weight:400}@media (max-width:767px){.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a:after{height:10px;margin-left:4px;vertical-align:baseline}}.navbar-pf .navbar-toggle{border:0;margin:0;padding:10px 20px}.navbar-pf .navbar-toggle:hover,.navbar-pf .navbar-toggle:focus{background-color:transparent;outline:0}.navbar-pf .navbar-toggle:hover .icon-bar,.navbar-pf .navbar-toggle:focus .icon-bar{-webkit-box-shadow:0 0 3px #fff;box-shadow:0 0 3px #fff}.navbar-pf .navbar-toggle .icon-bar{background-color:#fff}.navbar-pf .navbar-utility{border-bottom:1px solid #292929}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle{padding-left:36px;position:relative}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle .pficon-user{left:20px;position:absolute;top:10px}@media (max-width:767px){.navbar-pf .navbar-utility>li+li{border-top:1px solid #292929}}@media (min-width:768px){.navbar-pf .navbar-brand{padding:8px 0 7px}.navbar-pf .navbar-nav>li>a{padding-bottom:14px;padding-top:14px}.navbar-pf .navbar-persistent{font-size:14px}.navbar-pf .navbar-primary{font-size:14px;background-image:-webkit-linear-gradient(top,#1d1d1d 0,#030303 100%);background-image:linear-gradient(to bottom,#1d1d1d 0,#030303 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1d1d1d', endColorstr='#ff030303', GradientType=0)}.navbar-pf .navbar-primary.persistent-secondary .context .dropdown-menu{top:auto}.navbar-pf .navbar-primary.persistent-secondary .dropup .dropdown-menu{bottom:-5px;top:auto}.navbar-pf .navbar-primary.persistent-secondary>li{position:static}.navbar-pf .navbar-primary.persistent-secondary>li.active{margin-bottom:32px}.navbar-pf .navbar-primary.persistent-secondary>li.active>.navbar-persistent{display:block;left:0;position:absolute}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent{background:#f6f6f6;border-bottom:1px solid #cecdcd;padding:0;width:100%}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent a{text-decoration:none!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:before,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:hover:before{background:#0099d3;bottom:-1px;content:'';display:block;height:2px;left:20px;position:absolute;right:20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active>a,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active>a:hover,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:hover>a{color:#0099d3!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active .active>a{color:#f1f1f1}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu:hover>.dropdown-menu{display:none}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-menu{display:block;left:20px;margin-top:1px;top:100%}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-toggle{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-toggle:after{border-top-color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu>.dropdown-toggle{padding-right:35px!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu>.dropdown-toggle:after{position:absolute;right:20px;top:10px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover:before,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open:before{background:#aaa;bottom:-1px;content:'';display:block;height:2px;left:20px;position:absolute;right:20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover>a,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open>a{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover>a:after,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open>a:after{border-top-color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a{background-color:transparent;display:block;line-height:1;padding:9px 20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a.dropdown-toggle{padding-right:35px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a.dropdown-toggle:after{font-size:15px;position:absolute;right:20px;top:9px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a:hover{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li a{color:#4d5258}.navbar-pf .navbar-primary>li>a{border-bottom:1px solid transparent;border-top:1px solid transparent;position:relative;margin:-1px 0 0}.navbar-pf .navbar-primary>li>a:hover{background-color:#1d1d1d;border-top-color:#5c5c5c;color:#cfcfcf;background-image:-webkit-linear-gradient(top,#363636 0,#1d1d1d 100%);background-image:linear-gradient(to bottom,#363636 0,#1d1d1d 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff363636', endColorstr='#ff1d1d1d', GradientType=0)}.navbar-pf .navbar-primary>.active>a,.navbar-pf .navbar-primary>.active>a:hover,.navbar-pf .navbar-primary>.active>a:focus,.navbar-pf .navbar-primary>.open>a,.navbar-pf .navbar-primary>.open>a:hover,.navbar-pf .navbar-primary>.open>a:focus{background-color:#303030;border-bottom-color:#303030;border-top-color:#696969;-webkit-box-shadow:none;box-shadow:none;color:#f1f1f1;background-image:-webkit-linear-gradient(top,#434343 0,#303030 100%);background-image:linear-gradient(to bottom,#434343 0,#303030 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff434343', endColorstr='#ff303030', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context{border-bottom:0}.navbar-pf .navbar-primary li.dropdown.context>a{background-color:#1f1f1f;border-bottom-color:#3e3e3e;border-right:1px solid #3e3e3e;border-top-color:#3b3b3b;font-weight:600;background-image:-webkit-linear-gradient(top,#323232 0,#1f1f1f 100%);background-image:linear-gradient(to bottom,#323232 0,#1f1f1f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff323232', endColorstr='#ff1f1f1f', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context>a:hover{background-color:#323232;border-bottom-color:#4a4a4a;border-right-color:#4a4a4a;border-top-color:#4a4a4a;background-image:-webkit-linear-gradient(top,#3f3f3f 0,#323232 100%);background-image:linear-gradient(to bottom,#3f3f3f 0,#323232 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3f3f3f', endColorstr='#ff323232', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context.open>a{background-color:#454545;border-bottom-color:#575757;border-right-color:#575757;border-top-color:#5a5a5a;background-image:-webkit-linear-gradient(top,#4c4c4c 0,#454545 100%);background-image:linear-gradient(to bottom,#4c4c4c 0,#454545 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4c4c4c', endColorstr='#ff454545', GradientType=0)}.navbar-pf .navbar-utility{border-bottom:0;font-size:11px;position:absolute;right:0;top:0}.navbar-pf .navbar-utility>.active>a,.navbar-pf .navbar-utility>.active>a:hover,.navbar-pf .navbar-utility>.active>a:focus,.navbar-pf .navbar-utility>.open>a,.navbar-pf .navbar-utility>.open>a:hover,.navbar-pf .navbar-utility>.open>a:focus{background:#363636;color:#cfcfcf}.navbar-pf .navbar-utility>li>a{border-left:1px solid #2b2b2b;color:#cfcfcf!important;padding:7px 10px}.navbar-pf .navbar-utility>li>a:hover{background:#232323;border-left-color:#373737}.navbar-pf .navbar-utility>li.open>a{border-left-color:#444;color:#f1f1f1!important}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle{padding-left:26px}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle .pficon-user{left:10px;top:7px}.navbar-pf .navbar-utility .open .dropdown-menu{left:auto;right:0}.navbar-pf .navbar-utility .open .dropdown-menu .dropdown-menu{left:auto;right:100%}.navbar-pf .open .dropdown-menu{border-top-width:0!important}.navbar-pf .open .dropdown-submenu>.dropdown-menu{border-top-width:1px!important}}@media (max-width:360px){.navbar-pf .navbar-brand{margin-left:10px;width:75%}.navbar-pf .navbar-brand img{height:auto;max-width:100%}.navbar-pf .navbar-toggle{padding-left:0}}.pager li>a,.pager li>span{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258;font-weight:600;line-height:22px;padding:2px 14px}.pager li>a:hover,.pager li>span:hover,.pager li>a:focus,.pager li>span:focus,.pager li>a:active,.pager li>span:active,.pager li>a.active,.pager li>span.active,.open .dropdown-toggle.pager li>a,.open .dropdown-toggle.pager li>span{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.pager li>a:active,.pager li>span:active,.pager li>a.active,.pager li>span.active,.open .dropdown-toggle.pager li>a,.open .dropdown-toggle.pager li>span{background-image:none}.pager li>a.disabled,.pager li>span.disabled,.pager li>a[disabled],.pager li>span[disabled],fieldset[disabled] .pager li>a,fieldset[disabled] .pager li>span,.pager li>a.disabled:hover,.pager li>span.disabled:hover,.pager li>a[disabled]:hover,.pager li>span[disabled]:hover,fieldset[disabled] .pager li>a:hover,fieldset[disabled] .pager li>span:hover,.pager li>a.disabled:focus,.pager li>span.disabled:focus,.pager li>a[disabled]:focus,.pager li>span[disabled]:focus,fieldset[disabled] .pager li>a:focus,fieldset[disabled] .pager li>span:focus,.pager li>a.disabled:active,.pager li>span.disabled:active,.pager li>a[disabled]:active,.pager li>span[disabled]:active,fieldset[disabled] .pager li>a:active,fieldset[disabled] .pager li>span:active,.pager li>a.disabled.active,.pager li>span.disabled.active,.pager li>a[disabled].active,.pager li>span[disabled].active,fieldset[disabled] .pager li>a.active,fieldset[disabled] .pager li>span.active{background-color:#eee;border-color:#b7b7b7}.pager li>a>.i,.pager li>span>.i{font-size:18px;vertical-align:top;margin:2px 0}.pager li>a:hover>a:focus{color:#4d5258}.pager li a:active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125);outline:0}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>a:active,.pager .disabled>span{background:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#969696;cursor:default}.pager .next>a>.i,.pager .next>span>.i{margin-left:5px}.pager .previous>a>.i,.pager .previous>span>.i{margin-right:5px}.pager-sm li>a,.pager-sm li>span{font-weight:400;line-height:16px;padding:1px 10px}.pager-sm li>a>.i,.pager-sm li>span>.i{font-size:12px}.pagination>li>a,.pagination>li>span{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258;cursor:default;font-weight:600;padding:2px 10px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus,.pagination>li>a:active,.pagination>li>span:active,.pagination>li>a.active,.pagination>li>span.active,.open .dropdown-toggle.pagination>li>a,.open .dropdown-toggle.pagination>li>span{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.pagination>li>a:active,.pagination>li>span:active,.pagination>li>a.active,.pagination>li>span.active,.open .dropdown-toggle.pagination>li>a,.open .dropdown-toggle.pagination>li>span{background-image:none}.pagination>li>a.disabled,.pagination>li>span.disabled,.pagination>li>a[disabled],.pagination>li>span[disabled],fieldset[disabled] .pagination>li>a,fieldset[disabled] .pagination>li>span,.pagination>li>a.disabled:hover,.pagination>li>span.disabled:hover,.pagination>li>a[disabled]:hover,.pagination>li>span[disabled]:hover,fieldset[disabled] .pagination>li>a:hover,fieldset[disabled] .pagination>li>span:hover,.pagination>li>a.disabled:focus,.pagination>li>span.disabled:focus,.pagination>li>a[disabled]:focus,.pagination>li>span[disabled]:focus,fieldset[disabled] .pagination>li>a:focus,fieldset[disabled] .pagination>li>span:focus,.pagination>li>a.disabled:active,.pagination>li>span.disabled:active,.pagination>li>a[disabled]:active,.pagination>li>span[disabled]:active,fieldset[disabled] .pagination>li>a:active,fieldset[disabled] .pagination>li>span:active,.pagination>li>a.disabled.active,.pagination>li>span.disabled.active,.pagination>li>a[disabled].active,.pagination>li>span[disabled].active,fieldset[disabled] .pagination>li>a.active,fieldset[disabled] .pagination>li>span.active{background-color:#eee;border-color:#b7b7b7}.pagination>li>a>.i,.pagination>li>span>.i{font-size:15px;vertical-align:top;margin:2px 0}.pagination>li>a:active,.pagination>li>span:active{-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{background-color:#eee;border-color:#bbb;-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2);color:#4d5258;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{-webkit-box-shadow:none;box-shadow:none;cursor:default;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.pagination-sm>li>a,.pagination-sm>li>span{padding:0 6px;font-size:11px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:1px;border-top-left-radius:1px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:1px;border-top-right-radius:1px}.pagination-sm>li>a,.pagination-sm>li>span{font-weight:400}.pagination-sm>li>a>.i,.pagination-sm>li>span>.i{font-size:12px;margin-top:3px}.panel-title{font-weight:700}.panel-group .panel{color:#4d5258}.panel-group .panel+.panel{margin-top:-1px}.panel-group .panel-default{border-color:#bebdbd;border-top-color:#c4c3c3}.panel-group .panel-heading{background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #cecdcd}.panel-group .panel-title{font-weight:500;line-height:1}.panel-group .panel-title>a{color:#4d5258;font-weight:600}.panel-group .panel-title>a:before{content:"\f107";font-family:FontAwesome;font-size:13px;margin-right:5px;vertical-align:0}.panel-group .panel-title>a:focus{outline:0;text-decoration:none}.panel-group .panel-title>a:hover{text-decoration:none}.panel-group .panel-title>a.collapsed:before{content:"\f105";margin-left:4px;margin-right:7px}.popover{-webkit-box-shadow:0 2px 2px rgba(0,0,0,.08);box-shadow:0 2px 2px rgba(0,0,0,.08);padding:0}.popover-content{color:#4d5258;line-height:18px;padding:10px 14px}.popover-title{border-bottom:none;border-radius:0;color:#4d5258;font-size:13px;font-weight:700;min-height:34px}.popover-title .close{height:22px;position:absolute;right:8px;top:6px}.popover-title.closable{padding-right:30px}.sidebar-header{border-bottom:1px solid #e9e9e9;padding-bottom:11px;margin:50px 0 20px}.sidebar-header .actions{margin-top:-2px}.sidebar-pf .sidebar-header+.list-group{border-top:0;margin-top:-10px}.sidebar-pf .sidebar-header+.list-group .list-group-item{background:0 0;border-color:#e9e9e9;padding-left:0}.sidebar-pf .sidebar-header+.list-group .list-group-item-heading{font-size:12px}.sidebar-pf .nav-pills>li.active>a{background:#0099d3!important;border-color:#0076b7!important;color:#fff}@media (min-width:767px){.sidebar-pf .nav-pills>li.active>a:after{content:"\f105";font-family:FontAwesome;display:block;position:absolute;right:10px;top:2px}}.sidebar-pf .nav-pills>li>a{border-bottom:1px solid transparent;border-radius:0;border-top:1px solid transparent;color:#333;padding:1px 20px}.sidebar-pf .nav-pills>li>a:hover{background:#d4edfa;border-color:#b3d3e7}.sidebar-pf .nav-stacked{margin-left:-20px;margin-right:-20px}.sidebar-pf .nav-stacked li+li{margin-top:0}.sidebar-pf .panel{background:0 0}.sidebar-pf .panel-body{padding:2px 20px}.sidebar-pf .panel-body .nav-pills>li>a{padding-left:37px}.sidebar-pf .panel-heading{padding:7px 20px}.sidebar-pf .panel-title{font-size:12px}.sidebar-pf .panel-title>a:before{display:inline-block;margin-left:1px;margin-right:4px;width:9px}.sidebar-pf .panel-title>a.collapsed:before{margin-left:3px;margin-right:2px}@media (min-width:767px){.sidebar-header-bleed-left{margin-left:-20px}.sidebar-header-bleed-left>h2{margin-left:20px}.sidebar-header-bleed-right{margin-right:-20px}.sidebar-header-bleed-right .actions{margin-right:20px}.sidebar-header-bleed-right>h2{margin-right:20px}.sidebar-header-bleed-right+.list-group{margin-right:-20px}.sidebar-pf{background:#fafafa}.sidebar-pf.sidebar-pf-left{border-right:1px solid #d0d0d0}.sidebar-pf.sidebar-pf-right{border-left:1px solid #d0d0d0}.sidebar-pf .panel-group .panel-default{border-left:0;border-right:0;margin-left:-20px;margin-right:-20px}}.btn-group-pf>.dropdown-toggle{padding-left:10px;padding-right:22px;text-align:left}.btn-group-pf>.dropdown-toggle .caret{margin-top:-4px;padding-right:9px;position:absolute;right:8px;top:50%}.nav-tabs{font-size:14px}.nav-tabs>li>a{color:#4d5258;margin-right:-1px;padding-bottom:5px;padding-top:5px}.nav-tabs>li>a:active,.nav-tabs>li>a:focus,.nav-tabs>li>a:hover{background:0 0;border-color:#e9e8e8;color:#222}.nav-tabs>li>.dropdown-menu{border-top:0;border-color:#e9e8e8}.nav-tabs>li>.dropdown-menu.pull-right{right:-1px}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{background-color:transparent;border-color:#e9e8e8}@media (min-width:768px){.nav-tabs-pf.nav-justified{border-bottom:1px solid #e9e8e8}}.nav-tabs-pf.nav-justified>li:first-child>a{padding-left:15px}.nav-tabs-pf.nav-justified>li>a{border-bottom:0}.nav-tabs-pf.nav-justified>li>a:before{left:0!important;right:0!important}.nav-tabs-pf>li{margin-bottom:0}.nav-tabs-pf>li.active>a:before{background:#0099d3;bottom:-1px;content:'';display:block;height:2px;left:15px;position:absolute;right:15px}.nav-tabs-pf>li.active>a,.nav-tabs-pf>li.active>a:active,.nav-tabs-pf>li.active>a:focus,.nav-tabs-pf>li.active>a:hover{background-color:transparent;border:0!important;color:#0099d3}.nav-tabs-pf>li.active>a:before,.nav-tabs-pf>li.active>a:active:before,.nav-tabs-pf>li.active>a:focus:before,.nav-tabs-pf>li.active>a:hover:before{background:#0099d3}.nav-tabs-pf>li:first-child>a{padding-left:0}.nav-tabs-pf>li:first-child>a:before{left:0!important}.nav-tabs-pf>li>a{border:0;line-height:1;margin-right:0;padding-bottom:10px;padding-top:10px}.nav-tabs-pf>li>a:active:before,.nav-tabs-pf>li>a:focus:before,.nav-tabs-pf>li>a:hover:before{background:#aaa;bottom:-1px;content:'';display:block;height:2px;left:15px;position:absolute;right:15px}.nav-tabs-pf>li>.dropdown-menu{left:15px;margin-top:1px}.nav-tabs-pf>li>.dropdown-menu.pull-right{left:auto;right:15px}.nav-tabs-pf .open>a,.nav-tabs-pf .open>a:hover,.nav-tabs-pf .open>a:focus{background-color:transparent}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:2px 10px 3px}.table>thead>tr>th>a:hover,.table>tbody>tr>th>a:hover,.table>tfoot>tr>th>a:hover,.table>thead>tr>td>a:hover,.table>tbody>tr>td>a:hover,.table>tfoot>tr>td>a:hover{text-decoration:none}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th{font-family:'Open Sans';font-style:normal;font-weight:600}.table>thead{background-clip:padding-box;background-color:#f9f9f9;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.table-bordered{border:1px solid #d1d1d1}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #d1d1d1}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:1px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:transparent}.table-striped>tbody>tr:nth-child(even)>td,.table-striped>tbody>tr:nth-child(even)>th{background-color:#f5f5f5}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#d5ecf9;border-bottom-color:#a7cadf}h1,.h1,h2,.h2{font-weight:300}.page-header .actions{margin-top:8px}.page-header .actions a>.pficon{margin-right:4px}@media (min-width:767px){.page-header-bleed-left{margin-left:-20px}.page-header-bleed-right{margin-right:-20px}.page-header-bleed-right .actions{margin-right:20px}}.tooltip{font-size:12px}.tooltip.in{opacity:.88;filter:alpha(opacity=88)}.tooltip-inner{padding:7px 12px;text-align:left}
+\ No newline at end of file
++ */.bootstrap-select.btn-group,.bootstrap-select.btn-group[class*=span]{float:none;display:inline-block;margin-bottom:10px;margin-left:0}.form-search .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group{margin-bottom:0}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.btn-group.pull-right,.bootstrap-select.btn-group[class*=span].pull-right,.row-fluid .bootstrap-select.btn-group[class*=span].pull-right{float:right}.input-append .bootstrap-select.btn-group{margin-left:-1px}.input-prepend .bootstrap-select.btn-group{margin-right:-1px}.bootstrap-select:not([class*=span]):not([class*=col-]):not([class*=form-control]){width:220px}.bootstrap-select{width:220px\0}.bootstrap-select.form-control:not([class*=span]){width:100%}.bootstrap-select>.btn{width:100%}.error .bootstrap-select .btn{border:1px solid #b94a48}.dropdown-menu{z-index:2000}.bootstrap-select.show-menu-arrow.open>.btn{z-index:2051}.bootstrap-select .btn:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.btn-group .btn .filter-option{overflow:hidden;position:absolute;left:12px;right:25px;text-align:left}.bootstrap-select.btn-group .btn .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group>.disabled,.bootstrap-select.btn-group .dropdown-menu li.disabled>a{cursor:not-allowed}.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group[class*=span] .btn{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;border:0;padding:0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu dt{display:block;padding:3px 20px;cursor:default}.bootstrap-select.btn-group .div-contain{overflow:hidden}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li>a.opt{position:relative;padding-left:35px}.bootstrap-select.btn-group .dropdown-menu li>a{cursor:pointer}.bootstrap-select.btn-group .dropdown-menu li>dt small{font-weight:400}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a i.check-mark{display:inline-block;position:absolute;right:15px;margin-top:2.5px}.bootstrap-select.btn-group .dropdown-menu li a i.check-mark{display:none}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:hover small,.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:focus small,.bootstrap-select.btn-group .dropdown-menu li.active:not(.disabled)>a small{color:#64b1d8;color:rgba(255,255,255,.4)}.bootstrap-select.btn-group .dropdown-menu li>dt small{font-weight:400}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #CCC;border-bottom-color:rgba(0,0,0,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,.2)}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after{display:block}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px}.mobile-device{position:absolute;top:0;left:0;display:block!important;width:100%;height:100%!important;opacity:0}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select.btn-group.fit-width .btn .filter-option{position:static}.bootstrap-select.btn-group.fit-width .btn .caret{position:static;top:auto;margin-top:-1px}.control-group.error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select-searchbox{padding:4px 8px}.bootstrap-select-searchbox input{margin-bottom:0}.alert{border-width:2px;padding-left:34px;position:relative}.alert .alert-link{color:#0099d3}.alert .alert-link:hover{color:#00618a}.alert>.pficon,.alert>.pficon-layered{font-size:20px;position:absolute;left:7px;top:7px}.alert .pficon-info{color:#72767b}.alert-dismissable .close{right:-16px;top:1px}.badge{margin-left:6px}.nav-pills>li>a>.badge{margin-left:6px}.bootstrap-select.btn-group .btn .caret{font-size:16px;margin-top:-4px}.bootstrap-select.btn-group .dropdown-menu>.active>a:hover{background-color:#0099d3!important;border-color:#0076b7!important}.bootstrap-select.btn-group .dropdown-menu>.active>a:hover small{color:rgba(225,255,255,.4)!important}.bootstrap-select.btn-group .dropdown-menu dt{color:#969696;font-weight:400;padding:1px 10px}.bootstrap-select.btn-group .dropdown-menu li>a.opt{padding:1px 10px}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:focus small{color:rgba(225,255,255,.4)!important}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:active small,.bootstrap-select.btn-group .dropdown-menu li:not(.disabled)>a:hover small{color:#999}.breadcrumb{padding-left:0}.breadcrumb>.active strong{font-weight:600}.breadcrumb>li+li:before{color:#999;content:"\f101";font-family:FontAwesome;font-size:11px;padding:0 9px 0 7px}.btn{-webkit-box-shadow:0 2px 3px rgba(0,0,0,.1);box-shadow:0 2px 3px rgba(0,0,0,.1)}.btn:active{-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{background-color:#f8f8f8!important;background-image:none!important;border-color:#d1d1d1!important;color:#969696!important;opacity:1}.btn.disabled:active,.btn[disabled]:active,fieldset[disabled] .btn:active{-webkit-box-shadow:none;box-shadow:none}.btn.disabled.btn-link,.btn[disabled].btn-link,fieldset[disabled] .btn.btn-link{background-color:transparent!important;border:0}.btn-danger{background-color:#ab070f;background-image:-webkit-linear-gradient(top,#d60915 0,#ac0710 100%);background-image:linear-gradient(to bottom,#d60915 0,#ac0710 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd60915', endColorstr='#ffac0710', GradientType=0);border-color:#781919;color:#fff}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-color:#ab070f;background-image:none;border-color:#781919;color:#fff}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#ab070f;border-color:#781919}.btn-default{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#eee;border-color:#b7b7b7}.btn-link,.btn-link:active{-webkit-box-shadow:none;box-shadow:none}.btn-primary{background-color:#189ad1;background-image:-webkit-linear-gradient(top,#1cace8 0,#1998cc 100%);background-image:linear-gradient(to bottom,#1cace8 0,#1998cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1cace8', endColorstr='#ff1998cc', GradientType=0);border-color:#267da1;color:#fff}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-color:#189ad1;background-image:none;border-color:#267da1;color:#fff}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#189ad1;border-color:#267da1}.btn-xs,.btn-group-xs .btn,.btn-group-xs>.btn{font-weight:400}.close{text-shadow:none;opacity:.6;filter:alpha(opacity=60)}.close:hover,.close:focus{opacity:.9;filter:alpha(opacity=90)}.input-group-pf>.input-group-btn{position:static}.ie8 .input-group-pf .input-group-btn .dropdown-toggle{margin-left:-1px}.dataTables_header{background-color:#f6f6f6;border:1px solid #d1d1d1;border-bottom:none;padding:5px;position:relative;text-align:center}.dataTables_header .dataTables_filter{position:absolute}.dataTables_header .dataTables_filter input{border:1px solid #bbb;height:24px}@media (max-width:767px){.dataTables_header .dataTables_filter input{width:100px}}.dataTables_header .dataTables_info{padding:2px 0}@media (max-width:480px){.dataTables_header .dataTables_info{text-align:right}}.dataTables_header .dataTables_info b{font-weight:700}.dataTables_footer{background-color:#fff;border:1px solid #d1d1d1;border-top:none;overflow:hidden}.dataTables_paginate{background:#fafafa;float:right;margin:0}.dataTables_paginate .pagination{float:left;margin:0}.dataTables_paginate .pagination>li>span{border-color:#fff #e1e1e1 #f4f4f4;border-width:0 1px;font-size:16px;font-weight:400;padding:0;text-align:center;width:31px}.dataTables_paginate .pagination>li>span:hover,.dataTables_paginate .pagination>li>span:focus{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dataTables_paginate .pagination>li.last>span{border-right:none}.dataTables_paginate .pagination>li.disabled>span{background:#f5f5f5;border-left-color:#ececec;border-right-color:#ececec;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dataTables_paginate .pagination-input{float:left;font-size:12px;line-height:1em;padding:4px 15px 0;text-align:right}.dataTables_paginate .pagination-input .paginate_input{border:1px solid #d3d3d3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);font-size:12px;font-weight:600;height:19px;margin-right:8px;padding-right:3px;text-align:right;width:30px}.dataTables_paginate .pagination-input .paginate_of{position:relative}.dataTables_paginate .pagination-input .paginate_of b{margin-left:3px}.dataTables_wrapper{margin:20px 0}@media (max-width:767px){.dataTables_wrapper .table-responsive{margin-bottom:0}}table.datatable{margin-bottom:0;max-width:none!important}table.datatable thead .sorting,table.datatable thead .sorting_asc,table.datatable thead .sorting_desc,table.datatable thead .sorting_asc_disabled,table.datatable thead .sorting_desc_disabled{cursor:pointer;*cursor:hand}table.datatable thead .sorting_asc,table.datatable thead .sorting_desc{border:0;color:#0099d3!important;display:block;position:relative}table.datatable thead .sorting_asc:after,table.datatable thead .sorting_desc:after{content:"\f107";font-family:FontAwesome;font-size:10px;font-weight:400;height:9px;left:7px;line-height:12px;position:relative;top:2px;vertical-align:baseline;width:12px}table.datatable thead .sorting_asc:before,table.datatable thead .sorting_desc:before{background:#0099d3;content:'';height:2px;position:absolute;left:0;top:0;width:100%}table.datatable thead .sorting_asc:after{content:"\f106";top:-3px}table.datatable th:active{outline:0}.caret{font-family:FontAwesome;font-weight:400;height:9px;position:relative;vertical-align:baseline;width:12px}.caret:before{bottom:0;content:"\f107";left:0;line-height:12px;position:absolute;text-align:center;top:-1px;right:0}.dropdown-menu .divider{background-color:#e5e5e5;height:1px;margin:4px 1px;overflow:hidden}.dropdown-menu>li>a{border-color:transparent;border-style:solid;border-width:1px 0;padding:1px 10px}.dropdown-menu>li>a:hover{border-color:#b3d3e7;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:active{background-color:#0099d3;border-color:#0076b7;color:#fff!important;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#0099d3!important;border-color:#0076b7!important;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{border-color:transparent}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{border-color:transparent}.dropdown-header{padding-left:10px;padding-right:10px;text-transform:uppercase}.btn-group>.dropdown-menu,.input-group-btn>.dropdown-menu{margin-top:-1px}.dropup .dropdown-menu{margin-bottom:-1px}.dropdown-submenu{position:relative}.dropdown-submenu:hover>a{background-color:#d4edfa;border-color:#b3d3e7}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu.pull-left{float:none!important}.dropdown-submenu.pull-left>.dropdown-menu{left:auto;margin-left:10px;right:100%}.dropdown-submenu>a{padding-right:20px!important}.dropdown-submenu>a:after{content:"\f105";font-family:FontAwesome;display:block;position:absolute;right:10px;top:2px}.dropdown-submenu>.dropdown-menu{left:100%;margin-top:0;top:-6px}.dropup .dropdown-submenu>.dropdown-menu{bottom:-5px;top:auto}.open .dropdown-submenu.active>.dropdown-menu{display:block}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local('Open Sans'),local('OpenSans'),url(../fonts/open-sans/OpenSans-Regular.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:local('OpenSans-Light'),local('Open Sans Light'),url(../fonts/open-sans/OpenSans-Light.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:local('Open Sans Semibold'),local('OpenSans-Semibold'),url(../fonts/open-sans/OpenSans-Semibold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local('Open Sans Bold'),local('OpenSans-Bold'),url(../fonts/open-sans/OpenSans-Bold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:800;src:local('Open Sans Extrabold'),local('OpenSans-Extrabold'),url(../fonts/open-sans/OpenSans-ExtraBold.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:local('Open Sans Light Italic'),local('OpenSansLight-Italic'),url(../fonts/open-sans/OpenSans-LightItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:local('Open Sans Italic'),local('OpenSans-Italic'),url(../fonts/open-sans/OpenSans-Italic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:local('Open Sans Semibold Italic'),local('OpenSans-SemiboldItalic'),url(../fonts/open-sans/OpenSans-SemiboldItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:700;src:local('Open Sans Bold Italic'),local('OpenSans-BoldItalic'),url(../fonts/open-sans/OpenSans-BoldItalic.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:italic;font-weight:800;src:local('Open Sans Extrabold Italic'),local('OpenSans-ExtraboldItalic'),url(../fonts/open-sans/OpenSans-ExtraBoldItalic.ttf) format('truetype')}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{border-color:#d4d4d4!important;-webkit-box-shadow:none;box-shadow:none;color:#969696}.form-control:hover{border-color:#7BB2DD}.input-group .input-group-btn .btn{-webkit-box-shadow:none;box-shadow:none}label{font-weight:600}.navbar-nav>li>.dropdown-menu.infotip{border-top-width:1px!important;margin-top:10px}@media (max-width:767px){.navbar-pf .navbar-nav .open .dropdown-menu.infotip{background-color:#fff!important;margin-top:0}}.infotip{-webkit-box-shadow:0 2px 2px rgba(0,0,0,.08);box-shadow:0 2px 2px rgba(0,0,0,.08);min-width:235px;padding:0}.infotip .list-group{border-top:0;margin:0;padding:8px 0}.infotip .list-group .list-group-item{border:none;margin:0 15px 0 34px;padding:5px 0}.infotip .list-group .list-group-item>.i{color:#4d5258;font-size:13px;left:-20px;position:absolute;top:8px}.infotip .list-group .list-group-item>a{color:#4d5258;line-height:13px}.infotip .list-group .list-group-item>.close{float:right}.infotip .footer{background-color:#f5f5f5;padding:6px 15px}.infotip .footer a:hover{color:#0099d3}.infotip .arrow,.infotip .arrow:after{border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0}.infotip .arrow{border-width:11px}.infotip .arrow:after{border-width:10px;content:""}.infotip.bottom-right .arrow,.infotip.bottom .arrow{border-bottom-color:#999;border-bottom-color:#bbb;border-top-width:0;left:50%;margin-left:-11px;top:-11px}.infotip.bottom-right .arrow:after,.infotip.bottom .arrow:after{border-top-width:0;border-bottom-color:#fff;content:" ";margin-left:-10px;top:1px}.infotip.bottom-right .arrow{left:80%}.infotip.top .arrow{border-bottom-width:0;border-top-color:#999;border-top-color:#bbb;bottom:-11px;left:50%;margin-left:-11px}.infotip.top .arrow:after{border-bottom-width:0;border-top-color:#f5f5f5;bottom:1px;content:" ";margin-left:-10px}.infotip.right .arrow{border-left-width:0;border-right-color:#999;border-right-color:#bbb;left:-11px;margin-top:-11px;top:50%}.infotip.right .arrow:after{bottom:-10px;border-left-width:0;border-right-color:#fff;content:" ";left:1px}.infotip.left .arrow{border-left-color:#999;border-left-color:#bbb;border-right-width:0;margin-top:-11px;right:-11px;top:50%}.infotip.left .arrow:after{border-left-color:#fff;border-right-width:0;bottom:-10px;content:" ";right:1px}.label{border-radius:0;font-size:100%;font-weight:600}h1 .label,h2 .label,h3 .label,h4 .label,h5 .label,h6 .label{font-size:75%}.list-group{border-top:1px solid #e9e8e8}.list-group .list-group-item:first-child{border-top:0}.list-group-item{border-left:0;border-right:0}.list-group-item-heading{font-weight:700}.login-pf{height:100%}.login-pf #brand{position:relative;top:-70px}.login-pf #brand img{display:block;height:18px;margin:0 auto;max-width:100%}@media (min-width:768px){.login-pf #brand img{margin:0;text-align:left}}.login-pf #badge{display:block;margin:20px auto 70px;position:relative;text-align:center}@media (min-width:768px){.login-pf #badge{float:right;margin-right:64px;margin-top:50px}}.login-pf body{background:#1d2226 url(../img/bg-login.jpg) repeat-x 50% 0;background-size:auto;color:#fff}@media (min-width:768px){.login-pf body{background-size:100% auto}}.login-pf .container{background-color:#252a2e;background-color:rgba(0,0,0,.3);clear:right;padding-bottom:40px;padding-top:20px;width:auto}@media (min-width:768px){.login-pf .container{bottom:13%;padding-left:80px;position:absolute;width:100%}}.login-pf .container .details p:first-child{border-top:1px solid #474747;padding-top:25px;margin-top:25px}@media (min-width:768px){.login-pf .container .details{border-left:1px solid #474747;padding-left:40px}.login-pf .container .details p:first-child{border-top:0;padding-top:0;margin-top:0}}.login-pf .container .details p{margin-bottom:2px}.login-pf .container .form-horizontal .control-label{font-size:13px;font-weight:400;text-align:left}.login-pf .container .form-horizontal .form-group:last-child,.login-pf .container .form-horizontal .form-group:last-child .help-block:last-child{margin-bottom:0}.login-pf .container .help-block{color:#fff}@media (min-width:768px){.login-pf .container .login{padding-right:40px}}.login-pf .container .submit{text-align:right}.ie8.login-pf #badge{background:url(../img/logo.png) no-repeat;height:44px;width:137px}.ie8.login-pf #badge img{width:0}.ie8.login-pf #brand{background:url(../img/brand-lg.png) no-repeat center;background-size:cover auto}@media (min-width:768px){.ie8.login-pf #brand{background-position:0 0}}.ie8.login-pf #brand img{width:0}.modal-header{background-color:#f8f8f8;border-bottom:none;padding:10px 18px}.modal-header .close{margin-top:2px}.modal-title{font-size:13px;font-weight:700}.modal-footer{border-top:none;margin-top:15px;padding:19px 20px 20px}.modal-footer>.btn{padding-left:10px;padding-right:10px}.modal-footer>.btn>.fa-angle-left{margin-right:5px}.modal-footer>.btn>.fa-angle-right{margin-left:5px}.navbar-pf{background:#393f45;border:0;border-radius:0;border-top:3px solid #c00;margin-bottom:0;min-height:0}.navbar-pf .navbar-brand{color:#fff;height:auto;padding:12px 0;margin:0 0 0 20px}.ie8 .navbar-pf .navbar-brand{background:url(../img/brand.png) no-repeat 0 49%;min-width:300px}.navbar-pf .navbar-brand img{display:block}.ie8 .navbar-pf .navbar-brand img{height:10px;width:0}.navbar-pf .navbar-collapse{border-top:0;-webkit-box-shadow:none;box-shadow:none;padding:0}.navbar-pf .navbar-header{border-bottom:1px solid #53565b;float:none}.navbar-pf .navbar-nav{margin:0}.navbar-pf .navbar-nav>.active>a,.navbar-pf .navbar-nav>.active>a:hover,.navbar-pf .navbar-nav>.active>a:focus{background-color:#454c53;color:#fff}.navbar-pf .navbar-nav>li>a{color:#dbdada;line-height:1;padding:10px 20px;text-shadow:none}.navbar-pf .navbar-nav>li>a:hover,.navbar-pf .navbar-nav>li>a:focus{color:#fff}.navbar-pf .navbar-nav>.open>a,.navbar-pf .navbar-nav>.open>a:hover,.navbar-pf .navbar-nav>.open>a:focus{background-color:#454c53;color:#fff}@media (max-width:767px){.navbar-pf .navbar-nav .active .navbar-persistent,.navbar-pf .navbar-nav .active .dropdown-menu,.navbar-pf .navbar-nav .open .dropdown-menu{background-color:#3c434a!important;margin-left:0;padding-bottom:0;padding-top:0}.navbar-pf .navbar-nav .active .navbar-persistent>.active>a,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a,.navbar-pf .navbar-nav .active .navbar-persistent>.active>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a:hover,.navbar-pf .navbar-nav .active .navbar-persistent>.active>a:focus,.navbar-pf .navbar-nav .active .dropdown-menu>.active>a:focus,.navbar-pf .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open>a:focus,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open>a:focus,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open>a:focus{background-color:#424950!important;color:#fff}.navbar-pf .navbar-nav .active .navbar-persistent>li>a,.navbar-pf .navbar-nav .active .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu>li>a{background-color:transparent;border:0;color:#dbdada;outline:0;padding-left:30px}.navbar-pf .navbar-nav .active .navbar-persistent>li>a:hover,.navbar-pf .navbar-nav .active .dropdown-menu>li>a:hover,.navbar-pf .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff}.navbar-pf .navbar-nav .active .navbar-persistent .divider,.navbar-pf .navbar-nav .active .dropdown-menu .divider,.navbar-pf .navbar-nav .open .dropdown-menu .divider{background-color:#53565b;margin:0 1px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-header,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-header,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-header{padding-bottom:0;padding-left:30px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open .dropdown-toggle,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.open .dropdown-toggle,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.open .dropdown-toggle{color:#fff}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.pull-left,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu.pull-left,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu.pull-left{float:none!important}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu>a:after,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu>a:after,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu>a:after{display:none}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-header,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-header,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-header{padding-left:45px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu{border:0;bottom:auto;-webkit-box-shadow:none;box-shadow:none;display:block;float:none;margin:0;min-width:0;padding:0;position:relative;left:auto;right:auto;top:auto}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu>li>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu>li>a{padding:5px 15px 5px 45px;line-height:20px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu .dropdown-menu>li>a,.navbar-pf .navbar-nav .active .dropdown-menu .dropdown-submenu .dropdown-menu .dropdown-menu>li>a,.navbar-pf .navbar-nav .open .dropdown-menu .dropdown-submenu .dropdown-menu .dropdown-menu>li>a{padding-left:60px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu.open .dropdown-menu{display:block}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu>a:after{display:inline-block!important;position:relative;right:auto;top:1px}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-menu{display:none}.navbar-pf .navbar-nav .active .navbar-persistent .dropdown-submenu .dropdown-submenu>a:after{display:none!important}}.navbar-pf .navbar-persistent{display:none}.navbar-pf .active>.navbar-persistent{display:block}.navbar-pf .navbar-primary{float:none}.navbar-pf .navbar-primary .context{border-bottom:1px solid #53565b}.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a{position:relative}.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a:after{content:"\f107";display:inline-block;font-family:FontAwesome;font-weight:400}@media (max-width:767px){.navbar-pf .navbar-primary>li>.navbar-persistent>.dropdown-submenu>a:after{height:10px;margin-left:4px;vertical-align:baseline}}.navbar-pf .navbar-toggle{border:0;margin:0;padding:10px 20px}.navbar-pf .navbar-toggle:hover,.navbar-pf .navbar-toggle:focus{background-color:transparent;outline:0}.navbar-pf .navbar-toggle:hover .icon-bar,.navbar-pf .navbar-toggle:focus .icon-bar{-webkit-box-shadow:0 0 3px #fff;box-shadow:0 0 3px #fff}.navbar-pf .navbar-toggle .icon-bar{background-color:#fff}.navbar-pf .navbar-utility{border-bottom:1px solid #53565b}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle{padding-left:36px;position:relative}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle .pficon-user{left:20px;position:absolute;top:10px}@media (max-width:767px){.navbar-pf .navbar-utility>li+li{border-top:1px solid #53565b}}@media (min-width:768px){.navbar-pf .navbar-brand{padding:7px 0 8px}.navbar-pf .navbar-nav>li>a{padding-bottom:14px;padding-top:14px}.navbar-pf .navbar-persistent{font-size:14px}.navbar-pf .navbar-primary{font-size:14px;background-image:-webkit-linear-gradient(top,#474c50 0,#383f43 100%);background-image:linear-gradient(to bottom,#474c50 0,#383f43 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff474c50', endColorstr='#ff383f43', GradientType=0)}.navbar-pf .navbar-primary.persistent-secondary .context .dropdown-menu{top:auto}.navbar-pf .navbar-primary.persistent-secondary .dropup .dropdown-menu{bottom:-5px;top:auto}.navbar-pf .navbar-primary.persistent-secondary>li{position:static}.navbar-pf .navbar-primary.persistent-secondary>li.active{margin-bottom:32px}.navbar-pf .navbar-primary.persistent-secondary>li.active>.navbar-persistent{display:block;left:0;position:absolute}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent{background:#f6f6f6;border-bottom:1px solid #cecdcd;padding:0;width:100%}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent a{text-decoration:none!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:before,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:hover:before{background:#0099d3;bottom:-1px;content:'';display:block;height:2px;left:20px;position:absolute;right:20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active>a,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active>a:hover,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active:hover>a{color:#0099d3!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.active .active>a{color:#fff}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu:hover>.dropdown-menu{display:none}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-menu{display:block;left:20px;margin-top:1px;top:100%}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-toggle{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu.open>.dropdown-toggle:after{border-top-color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu>.dropdown-toggle{padding-right:35px!important}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.dropdown-submenu>.dropdown-toggle:after{position:absolute;right:20px;top:10px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover:before,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open:before{background:#aaa;bottom:-1px;content:'';display:block;height:2px;left:20px;position:absolute;right:20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover>a,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open>a{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li:hover>a:after,.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li.open>a:after{border-top-color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a{background-color:transparent;display:block;line-height:1;padding:9px 20px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a.dropdown-toggle{padding-right:35px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a.dropdown-toggle:after{font-size:15px;position:absolute;right:20px;top:9px}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li>a:hover{color:#222}.navbar-pf .navbar-primary.persistent-secondary>li>.navbar-persistent>li a{color:#4d5258}.navbar-pf .navbar-primary>li>a{border-bottom:1px solid transparent;border-top:1px solid transparent;position:relative;margin:-1px 0 0}.navbar-pf .navbar-primary>li>a:hover{background-color:#4b5053;border-top-color:#949699;color:#dbdada;background-image:-webkit-linear-gradient(top,#5c6165 0,#4b5053 100%);background-image:linear-gradient(to bottom,#5c6165 0,#4b5053 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5c6165', endColorstr='#ff4b5053', GradientType=0)}.navbar-pf .navbar-primary>.active>a,.navbar-pf .navbar-primary>.active>a:hover,.navbar-pf .navbar-primary>.active>a:focus,.navbar-pf .navbar-primary>.open>a,.navbar-pf .navbar-primary>.open>a:hover,.navbar-pf .navbar-primary>.open>a:focus{background-color:#64686c;border-bottom-color:#64686c;border-top-color:#949699;-webkit-box-shadow:none;box-shadow:none;color:#fff;background-image:-webkit-linear-gradient(top,#72757a 0,#64686c 100%);background-image:linear-gradient(to bottom,#72757a 0,#64686c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff72757a', endColorstr='#ff64686c', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context{border-bottom:0}.navbar-pf .navbar-primary li.dropdown.context>a{background-color:#505458;border-bottom-color:#65696d;border-right:1px solid #65696d;border-top-color:#64696d;font-weight:600;background-image:-webkit-linear-gradient(top,#585d61 0,#505458 100%);background-image:linear-gradient(to bottom,#585d61 0,#505458 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff585d61', endColorstr='#ff505458', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context>a:hover{background-color:#5a5e62;border-bottom-color:#6e7276;border-right-color:#6e7276;border-top-color:#6c7276;background-image:-webkit-linear-gradient(top,#62676b 0,#5a5e62 100%);background-image:linear-gradient(to bottom,#62676b 0,#5a5e62 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62676b', endColorstr='#ff5a5e62', GradientType=0)}.navbar-pf .navbar-primary li.dropdown.context.open>a{background-color:#65696d;border-bottom-color:#6e7276;border-right-color:#777a7e;border-top-color:#767a7e;background-image:-webkit-linear-gradient(top,#6b7175 0,#65696d 100%);background-image:linear-gradient(to bottom,#6b7175 0,#65696d 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6b7175', endColorstr='#ff65696d', GradientType=0)}.navbar-pf .navbar-utility{border-bottom:0;font-size:11px;position:absolute;right:0;top:0}.navbar-pf .navbar-utility>.active>a,.navbar-pf .navbar-utility>.active>a:hover,.navbar-pf .navbar-utility>.active>a:focus,.navbar-pf .navbar-utility>.open>a,.navbar-pf .navbar-utility>.open>a:hover,.navbar-pf .navbar-utility>.open>a:focus{background:#5b6165;color:#fff}.navbar-pf .navbar-utility>li>a{border-left:1px solid #53565b;color:#fff!important;padding:7px 10px}.navbar-pf .navbar-utility>li>a:hover{background:#4a5053;border-left-color:#636466}.navbar-pf .navbar-utility>li.open>a{border-left-color:#6c6e70;color:#fff!important}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle{padding-left:26px}.navbar-pf .navbar-utility li.dropdown>.dropdown-toggle .pficon-user{left:10px;top:7px}.navbar-pf .navbar-utility .open .dropdown-menu{left:auto;right:0}.navbar-pf .navbar-utility .open .dropdown-menu .dropdown-menu{left:auto;right:100%}.navbar-pf .open .dropdown-menu{border-top-width:0!important}.navbar-pf .open .dropdown-submenu>.dropdown-menu{border-top-width:1px!important}}@media (max-width:360px){.navbar-pf .navbar-brand{margin-left:10px;width:75%}.navbar-pf .navbar-brand img{height:auto;max-width:100%}.navbar-pf .navbar-toggle{padding-left:0}}.pager li>a,.pager li>span{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258;font-weight:600;line-height:22px;padding:2px 14px}.pager li>a:hover,.pager li>span:hover,.pager li>a:focus,.pager li>span:focus,.pager li>a:active,.pager li>span:active,.pager li>a.active,.pager li>span.active,.open .dropdown-toggle.pager li>a,.open .dropdown-toggle.pager li>span{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.pager li>a:active,.pager li>span:active,.pager li>a.active,.pager li>span.active,.open .dropdown-toggle.pager li>a,.open .dropdown-toggle.pager li>span{background-image:none}.pager li>a.disabled,.pager li>span.disabled,.pager li>a[disabled],.pager li>span[disabled],fieldset[disabled] .pager li>a,fieldset[disabled] .pager li>span,.pager li>a.disabled:hover,.pager li>span.disabled:hover,.pager li>a[disabled]:hover,.pager li>span[disabled]:hover,fieldset[disabled] .pager li>a:hover,fieldset[disabled] .pager li>span:hover,.pager li>a.disabled:focus,.pager li>span.disabled:focus,.pager li>a[disabled]:focus,.pager li>span[disabled]:focus,fieldset[disabled] .pager li>a:focus,fieldset[disabled] .pager li>span:focus,.pager li>a.disabled:active,.pager li>span.disabled:active,.pager li>a[disabled]:active,.pager li>span[disabled]:active,fieldset[disabled] .pager li>a:active,fieldset[disabled] .pager li>span:active,.pager li>a.disabled.active,.pager li>span.disabled.active,.pager li>a[disabled].active,.pager li>span[disabled].active,fieldset[disabled] .pager li>a.active,fieldset[disabled] .pager li>span.active{background-color:#eee;border-color:#b7b7b7}.pager li>a>.i,.pager li>span>.i{font-size:18px;vertical-align:top;margin:2px 0}.pager li>a:hover>a:focus{color:#4d5258}.pager li a:active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125);outline:0}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>a:active,.pager .disabled>span{background:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#969696;cursor:default}.pager .next>a>.i,.pager .next>span>.i{margin-left:5px}.pager .previous>a>.i,.pager .previous>span>.i{margin-right:5px}.pager-sm li>a,.pager-sm li>span{font-weight:400;line-height:16px;padding:1px 10px}.pager-sm li>a>.i,.pager-sm li>span>.i{font-size:12px}.pagination>li>a,.pagination>li>span{background-color:#eee;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);border-color:#b7b7b7;color:#4d5258;cursor:default;font-weight:600;padding:2px 10px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus,.pagination>li>a:active,.pagination>li>span:active,.pagination>li>a.active,.pagination>li>span.active,.open .dropdown-toggle.pagination>li>a,.open .dropdown-toggle.pagination>li>span{background-color:#eee;background-image:none;border-color:#b7b7b7;color:#4d5258}.pagination>li>a:active,.pagination>li>span:active,.pagination>li>a.active,.pagination>li>span.active,.open .dropdown-toggle.pagination>li>a,.open .dropdown-toggle.pagination>li>span{background-image:none}.pagination>li>a.disabled,.pagination>li>span.disabled,.pagination>li>a[disabled],.pagination>li>span[disabled],fieldset[disabled] .pagination>li>a,fieldset[disabled] .pagination>li>span,.pagination>li>a.disabled:hover,.pagination>li>span.disabled:hover,.pagination>li>a[disabled]:hover,.pagination>li>span[disabled]:hover,fieldset[disabled] .pagination>li>a:hover,fieldset[disabled] .pagination>li>span:hover,.pagination>li>a.disabled:focus,.pagination>li>span.disabled:focus,.pagination>li>a[disabled]:focus,.pagination>li>span[disabled]:focus,fieldset[disabled] .pagination>li>a:focus,fieldset[disabled] .pagination>li>span:focus,.pagination>li>a.disabled:active,.pagination>li>span.disabled:active,.pagination>li>a[disabled]:active,.pagination>li>span[disabled]:active,fieldset[disabled] .pagination>li>a:active,fieldset[disabled] .pagination>li>span:active,.pagination>li>a.disabled.active,.pagination>li>span.disabled.active,.pagination>li>a[disabled].active,.pagination>li>span[disabled].active,fieldset[disabled] .pagination>li>a.active,fieldset[disabled] .pagination>li>span.active{background-color:#eee;border-color:#b7b7b7}.pagination>li>a>.i,.pagination>li>span>.i{font-size:15px;vertical-align:top;margin:2px 0}.pagination>li>a:active,.pagination>li>span:active{-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{background-color:#eee;border-color:#bbb;-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.2);box-shadow:inset 0 2px 8px rgba(0,0,0,.2);color:#4d5258;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{-webkit-box-shadow:none;box-shadow:none;cursor:default;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.pagination-sm>li>a,.pagination-sm>li>span{padding:0 6px;font-size:11px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:1px;border-top-left-radius:1px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:1px;border-top-right-radius:1px}.pagination-sm>li>a,.pagination-sm>li>span{font-weight:400}.pagination-sm>li>a>.i,.pagination-sm>li>span>.i{font-size:12px;margin-top:3px}.panel-title{font-weight:700}.panel-group .panel{color:#4d5258}.panel-group .panel+.panel{margin-top:-1px}.panel-group .panel-default{border-color:#bebdbd;border-top-color:#c4c3c3}.panel-group .panel-heading{background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #cecdcd}.panel-group .panel-title{font-weight:500;line-height:1}.panel-group .panel-title>a{color:#4d5258;font-weight:600}.panel-group .panel-title>a:before{content:"\f107";font-family:FontAwesome;font-size:13px;margin-right:5px;vertical-align:0}.panel-group .panel-title>a:focus{outline:0;text-decoration:none}.panel-group .panel-title>a:hover{text-decoration:none}.panel-group .panel-title>a.collapsed:before{content:"\f105";margin-left:4px;margin-right:7px}.popover{-webkit-box-shadow:0 2px 2px rgba(0,0,0,.08);box-shadow:0 2px 2px rgba(0,0,0,.08);padding:0}.popover-content{color:#4d5258;line-height:18px;padding:10px 14px}.popover-title{border-bottom:none;border-radius:0;color:#4d5258;font-size:13px;font-weight:700;min-height:34px}.popover-title .close{height:22px;position:absolute;right:8px;top:6px}.popover-title.closable{padding-right:30px}.sidebar-header{border-bottom:1px solid #e9e9e9;padding-bottom:11px;margin:50px 0 20px}.sidebar-header .actions{margin-top:-2px}.sidebar-pf .sidebar-header+.list-group{border-top:0;margin-top:-10px}.sidebar-pf .sidebar-header+.list-group .list-group-item{background:0 0;border-color:#e9e9e9;padding-left:0}.sidebar-pf .sidebar-header+.list-group .list-group-item-heading{font-size:12px}.sidebar-pf .nav-pills>li.active>a{background:#0099d3!important;border-color:#0076b7!important;color:#fff}@media (min-width:767px){.sidebar-pf .nav-pills>li.active>a:after{content:"\f105";font-family:FontAwesome;display:block;position:absolute;right:10px;top:2px}}.sidebar-pf .nav-pills>li>a{border-bottom:1px solid transparent;border-radius:0;border-top:1px solid transparent;color:#333;padding:1px 20px}.sidebar-pf .nav-pills>li>a:hover{background:#d4edfa;border-color:#b3d3e7}.sidebar-pf .nav-stacked{margin-left:-20px;margin-right:-20px}.sidebar-pf .nav-stacked li+li{margin-top:0}.sidebar-pf .panel{background:0 0}.sidebar-pf .panel-body{padding:2px 20px}.sidebar-pf .panel-body .nav-pills>li>a{padding-left:37px}.sidebar-pf .panel-heading{padding:7px 20px}.sidebar-pf .panel-title{font-size:12px}.sidebar-pf .panel-title>a:before{display:inline-block;margin-left:1px;margin-right:4px;width:9px}.sidebar-pf .panel-title>a.collapsed:before{margin-left:3px;margin-right:2px}@media (min-width:767px){.sidebar-header-bleed-left{margin-left:-20px}.sidebar-header-bleed-left>h2{margin-left:20px}.sidebar-header-bleed-right{margin-right:-20px}.sidebar-header-bleed-right .actions{margin-right:20px}.sidebar-header-bleed-right>h2{margin-right:20px}.sidebar-header-bleed-right+.list-group{margin-right:-20px}.sidebar-pf{background:#fafafa}.sidebar-pf.sidebar-pf-left{border-right:1px solid #d0d0d0}.sidebar-pf.sidebar-pf-right{border-left:1px solid #d0d0d0}.sidebar-pf .panel-group .panel-default{border-left:0;border-right:0;margin-left:-20px;margin-right:-20px}}.btn-group-pf>.dropdown-toggle{padding-left:10px;padding-right:22px;text-align:left}.btn-group-pf>.dropdown-toggle .caret{margin-top:-4px;padding-right:9px;position:absolute;right:8px;top:50%}.nav-tabs{font-size:14px}.nav-tabs>li>a{color:#4d5258;margin-right:-1px;padding-bottom:5px;padding-top:5px}.nav-tabs>li>a:active,.nav-tabs>li>a:focus,.nav-tabs>li>a:hover{background:0 0;border-color:#e9e8e8;color:#222}.nav-tabs>li>.dropdown-menu{border-top:0;border-color:#e9e8e8}.nav-tabs>li>.dropdown-menu.pull-right{right:-1px}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{background-color:transparent;border-color:#e9e8e8}@media (min-width:768px){.nav-tabs-pf.nav-justified{border-bottom:1px solid #e9e8e8}}.nav-tabs-pf.nav-justified>li:first-child>a{padding-left:15px}.nav-tabs-pf.nav-justified>li>a{border-bottom:0}.nav-tabs-pf.nav-justified>li>a:before{left:0!important;right:0!important}.nav-tabs-pf>li{margin-bottom:0}.nav-tabs-pf>li.active>a:before{background:#0099d3;bottom:-1px;content:'';display:block;height:2px;left:15px;position:absolute;right:15px}.nav-tabs-pf>li.active>a,.nav-tabs-pf>li.active>a:active,.nav-tabs-pf>li.active>a:focus,.nav-tabs-pf>li.active>a:hover{background-color:transparent;border:0!important;color:#0099d3}.nav-tabs-pf>li.active>a:before,.nav-tabs-pf>li.active>a:active:before,.nav-tabs-pf>li.active>a:focus:before,.nav-tabs-pf>li.active>a:hover:before{background:#0099d3}.nav-tabs-pf>li:first-child>a{padding-left:0}.nav-tabs-pf>li:first-child>a:before{left:0!important}.nav-tabs-pf>li>a{border:0;line-height:1;margin-right:0;padding-bottom:10px;padding-top:10px}.nav-tabs-pf>li>a:active:before,.nav-tabs-pf>li>a:focus:before,.nav-tabs-pf>li>a:hover:before{background:#aaa;bottom:-1px;content:'';display:block;height:2px;left:15px;position:absolute;right:15px}.nav-tabs-pf>li>.dropdown-menu{left:15px;margin-top:1px}.nav-tabs-pf>li>.dropdown-menu.pull-right{left:auto;right:15px}.nav-tabs-pf .open>a,.nav-tabs-pf .open>a:hover,.nav-tabs-pf .open>a:focus{background-color:transparent}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:2px 10px 3px}.table>thead>tr>th>a:hover,.table>tbody>tr>th>a:hover,.table>tfoot>tr>th>a:hover,.table>thead>tr>td>a:hover,.table>tbody>tr>td>a:hover,.table>tfoot>tr>td>a:hover{text-decoration:none}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th{font-family:'Open Sans';font-style:normal;font-weight:600}.table>thead{background-clip:padding-box;background-color:#f9f9f9;background-image:-webkit-linear-gradient(top,#fafafa 0,#ededed 100%);background-image:linear-gradient(to bottom,#fafafa 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)}.table-bordered{border:1px solid #d1d1d1}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #d1d1d1}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:1px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:transparent}.table-striped>tbody>tr:nth-child(even)>td,.table-striped>tbody>tr:nth-child(even)>th{background-color:#f5f5f5}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#d5ecf9;border-bottom-color:#a7cadf}h1,.h1,h2,.h2{font-weight:300}.page-header .actions{margin-top:8px}.page-header .actions a>.pficon{margin-right:4px}@media (min-width:767px){.page-header-bleed-left{margin-left:-20px}.page-header-bleed-right{margin-right:-20px}.page-header-bleed-right .actions{margin-right:20px}}.tooltip{font-size:12px}.tooltip.in{opacity:.88;filter:alpha(opacity=88)}.tooltip-inner{padding:7px 12px;text-align:left}
+\ No newline at end of file
+diff --git a/install/ui/less/brand.less b/install/ui/less/brand.less
+index c9030bb0bdb6067a7be837cdc3da08cb8c5185b4..2300448de0b66e3239d6a7e9fb57f4c1814500a7 100644
+--- a/install/ui/less/brand.less
++++ b/install/ui/less/brand.less
+@@ -20,58 +20,53 @@
+ 
+ // this file should be overridden with brand/platform specific content
+ 
+-@login-details-border: #777777;
++@img-badge-ie8-height:                                              44px;
++@img-badge-ie8-width:                                               137px;
++@login-bg-color:                                                    #1D2226;
++@login-container-bg-color:                                          #252a2e;
++@login-container-bg-color-rgba:                                     rgba(0, 0, 0, 0.3);
++@navbar-pf-bg-color:                                                #393F45;
++@navbar-pf-border-color:                                            #cc0000;
++@navbar-pf-active-color:                                            #fff;
++@navbar-pf-color:                                                   #dbdada;
++@navbar-pf-icon-bar-bg-color:                                       #fff;
++@navbar-pf-navbar-header-border-color:                              #53565b;
++@navbar-pf-navbar-nav-active-bg-color:                              #454C53;
++@navbar-pf-navbar-nav-active-active-bg-color:                       #3c434a;
++@navbar-pf-navbar-nav-active-active-open-bg-color:                  #424950;
++@navbar-pf-navbar-navbar-brand-min-width:                           300px;
++@navbar-pf-navbar-navbar-brand-padding:                             7px 0 8px;
++@navbar-pf-navbar-navbar-persistent-bg-color:                       #f6f6f6;
++@navbar-pf-navbar-navbar-persistent-border-color:                   #cecdcd;
++@navbar-pf-navbar-primary-active-bg-color-start:                    #72757a;
++@navbar-pf-navbar-primary-active-bg-color-stop:                     #64686c;
++@navbar-pf-navbar-primary-active-border-color:                      #949699;
++@navbar-pf-navbar-primary-bg-color-start:                           #474c50;
++@navbar-pf-navbar-primary-bg-color-stop:                            #383f43;
++@navbar-pf-navbar-primary-hover-bg-color-start:                     #5c6165;
++@navbar-pf-navbar-primary-hover-bg-color-stop:                      #4b5053;
++@navbar-pf-navbar-primary-hover-border-color:                       #949699;
++@navbar-pf-navbar-primary-context-active-bg-color-start:            #6b7175;
++@navbar-pf-navbar-primary-context-active-bg-color-stop:             #65696d;
++@navbar-pf-navbar-primary-context-active-border-color:              #6e7276;
++@navbar-pf-navbar-primary-context-active-border-right-color:        #777a7e;
++@navbar-pf-navbar-primary-context-active-border-top-color:          #767a7e;
++@navbar-pf-navbar-primary-context-bg-color-start:                   #585d61;
++@navbar-pf-navbar-primary-context-bg-color-stop:                    #505458;
++@navbar-pf-navbar-primary-context-border-color:                     #65696d;
++@navbar-pf-navbar-primary-context-border-top-color:                 #64696d;
++@navbar-pf-navbar-primary-context-hover-bg-color-start:             #62676b;
++@navbar-pf-navbar-primary-context-hover-bg-color-stop:              #5a5e62;
++@navbar-pf-navbar-primary-context-hover-border-color:               #6e7276;
++@navbar-pf-navbar-primary-context-hover-border-top-color:           #6c7276;
++@navbar-pf-navbar-utility-border-color:                             #53565b;
++@navbar-pf-navbar-utility-color:                                    #fff;
++@navbar-pf-navbar-utility-hover-bg-color:                           #4a5053;
++@navbar-pf-navbar-utility-hover-border-color:                       #636466;
++@navbar-pf-navbar-utility-open-bg-color:                            #5b6165;
++@navbar-pf-navbar-utility-open-border-color:                        #6c6e70;
+ 
+-.login-pf {
+-
+-    .login-pf-body {
+-        padding-top: 50px;
+-    }
+-
+-    #badge img {
+-        display: none;
+-    }
+-
+-    #brand {
+-        position: absolute;
+-        top: -135px;
+-        img {
+-            height: auto;
+-        }
+-    }
+-
+-    .container {
+-        padding-top: 40px;
+-
+-        .details p:first-child {
+-            border-top: 1px solid @login-details-border;
+-        }
+-    }
+-}
+-
+-// 768px == @screen-sm-min
+-@media (min-width: 768px) {
+-    .navbar-pf .navbar-brand {
+-        padding: 2px 0 3px;
+-    }
+-
+-    .login-pf .container .details {
+-        p:first-child {
+-            border-top: 0;
+-        }
+-        border-left: 1px solid @login-details-border;
+-    }
+-}
+-
+-@media (max-height: 520px) {
+-    .reset-login-pf-height;
+-    .login-pf {
+-        .login-pf-body {
+-            padding-top: 0;
+-        }
+-        #badge {
+-            margin-top: 0;
+-            height: 70px;
+-        }
+-    }
++.info-page .navbar-header {
++    line-height: inherit;
++    margin-left: 20px;
+ }
+\ No newline at end of file
+diff --git a/install/ui/less/patternfly.less b/install/ui/less/patternfly.less
+index 091b669c5601d0e2ef3aa95cd611c422c4e2647c..e3b20fb573efd31df61fda524f11254e316f4558 100644
+--- a/install/ui/less/patternfly.less
++++ b/install/ui/less/patternfly.less
+@@ -120,4 +120,50 @@
+ @import "@{patternfly_dir}/less/tooltip";
+ 
+ // our overrides
+-@fa-font-path:        "../fonts/fontawesome";
+\ No newline at end of file
++@fa-font-path:        "../fonts/fontawesome";
++
++@img-badge-ie8-height:                                              44px;
++@img-badge-ie8-width:                                               137px;
++@login-bg-color:                                                    #1D2226;
++@login-container-bg-color:                                          #252a2e;
++@login-container-bg-color-rgba:                                     rgba(0, 0, 0, 0.3);
++@navbar-pf-bg-color:                                                #393F45;
++@navbar-pf-border-color:                                            #cc0000;
++@navbar-pf-active-color:                                            #fff;
++@navbar-pf-color:                                                   #dbdada;
++@navbar-pf-icon-bar-bg-color:                                       #fff;
++@navbar-pf-navbar-header-border-color:                              #53565b;
++@navbar-pf-navbar-nav-active-bg-color:                              #454C53;
++@navbar-pf-navbar-nav-active-active-bg-color:                       #3c434a;
++@navbar-pf-navbar-nav-active-active-open-bg-color:                  #424950;
++@navbar-pf-navbar-navbar-brand-min-width:                           300px;
++@navbar-pf-navbar-navbar-brand-padding:                             7px 0 8px;
++@navbar-pf-navbar-navbar-persistent-bg-color:                       #f6f6f6;
++@navbar-pf-navbar-navbar-persistent-border-color:                   #cecdcd;
++@navbar-pf-navbar-primary-active-bg-color-start:                    #72757a;
++@navbar-pf-navbar-primary-active-bg-color-stop:                     #64686c;
++@navbar-pf-navbar-primary-active-border-color:                      #949699;
++@navbar-pf-navbar-primary-bg-color-start:                           #474c50;
++@navbar-pf-navbar-primary-bg-color-stop:                            #383f43;
++@navbar-pf-navbar-primary-hover-bg-color-start:                     #5c6165;
++@navbar-pf-navbar-primary-hover-bg-color-stop:                      #4b5053;
++@navbar-pf-navbar-primary-hover-border-color:                       #949699;
++@navbar-pf-navbar-primary-context-active-bg-color-start:            #6b7175;
++@navbar-pf-navbar-primary-context-active-bg-color-stop:             #65696d;
++@navbar-pf-navbar-primary-context-active-border-color:              #6e7276;
++@navbar-pf-navbar-primary-context-active-border-right-color:        #777a7e;
++@navbar-pf-navbar-primary-context-active-border-top-color:          #767a7e;
++@navbar-pf-navbar-primary-context-bg-color-start:                   #585d61;
++@navbar-pf-navbar-primary-context-bg-color-stop:                    #505458;
++@navbar-pf-navbar-primary-context-border-color:                     #65696d;
++@navbar-pf-navbar-primary-context-border-top-color:                 #64696d;
++@navbar-pf-navbar-primary-context-hover-bg-color-start:             #62676b;
++@navbar-pf-navbar-primary-context-hover-bg-color-stop:              #5a5e62;
++@navbar-pf-navbar-primary-context-hover-border-color:               #6e7276;
++@navbar-pf-navbar-primary-context-hover-border-top-color:           #6c7276;
++@navbar-pf-navbar-utility-border-color:                             #53565b;
++@navbar-pf-navbar-utility-color:                                    #fff;
++@navbar-pf-navbar-utility-hover-bg-color:                           #4a5053;
++@navbar-pf-navbar-utility-hover-border-color:                       #636466;
++@navbar-pf-navbar-utility-open-bg-color:                            #5b6165;
++@navbar-pf-navbar-utility-open-border-color:                        #6c6e70;
+\ No newline at end of file
+-- 
+1.9.3
+
diff --git a/SOURCES/1009-Do-not-allow-installation-in-FIPS-mode.patch b/SOURCES/1009-Do-not-allow-installation-in-FIPS-mode.patch
new file mode 100644
index 0000000..29eb9cc
--- /dev/null
+++ b/SOURCES/1009-Do-not-allow-installation-in-FIPS-mode.patch
@@ -0,0 +1,80 @@
+From ec381c10fc6080b1e2594cbee857725c886566d4 Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 21 Oct 2014 14:56:28 +0200
+Subject: [PATCH] Do not allow installation in FIPS mode
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1131570
+---
+ install/tools/ipa-replica-install         | 5 +++++
+ install/tools/ipa-server-install          | 5 +++++
+ install/tools/ipactl                      | 6 ++++++
+ ipa-client/ipa-install/ipa-client-install | 4 ++++
+ 4 files changed, 20 insertions(+)
+
+diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
+index d3b520abf635ccc324b74bca31f241960a33d950..70190b718965518803b9767325d58f9526c32f7c 100755
+--- a/install/tools/ipa-replica-install
++++ b/install/tools/ipa-replica-install
+@@ -457,6 +457,11 @@ def main():
+     if os.geteuid() != 0:
+         sys.exit("\nYou must be root to run this script.\n")
+ 
++    if os.path.exists('/proc/sys/crypto/fips_enabled'):
++        with open('/proc/sys/crypto/fips_enabled', 'r') as f:
++            if f.read().strip() != '0':
++                sys.exit("Cannot install IPA server in FIPS mode")
++
+     standard_logging_setup(log_file_name, debug=options.debug)
+     root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
+     root_logger.debug('IPA version %s' % version.VENDOR_VERSION)
+diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
+index 4fd4d8171ab89b805449a6625e9c5ea2d0921fa5..3b748aaab37fa8806ebc7a4983ed97cc8243a9c4 100755
+--- a/install/tools/ipa-server-install
++++ b/install/tools/ipa-server-install
+@@ -662,6 +662,11 @@ def main():
+     if os.getegid() != 0:
+         sys.exit("Must be root to set up server")
+ 
++    if os.path.exists('/proc/sys/crypto/fips_enabled'):
++        with open('/proc/sys/crypto/fips_enabled', 'r') as f:
++            if f.read().strip() != '0':
++                sys.exit("Cannot install IPA server in FIPS mode")
++
+     tasks.check_selinux_status()
+ 
+     signal.signal(signal.SIGTERM, signal_handler)
+diff --git a/install/tools/ipactl b/install/tools/ipactl
+index b1b0b6e26fa97cdc953c86eee22e160782b57379..56d24b0dab1770d23348f4c60db62bab3bd508d4 100755
+--- a/install/tools/ipactl
++++ b/install/tools/ipactl
+@@ -480,6 +480,12 @@ def main():
+     elif args[0] != "start" and args[0] != "stop" and args[0] != "restart" and args[0] != "status":
+         raise IpactlError("Unrecognized action [" + args[0] + "]", 2)
+ 
++    if (args[0] in ('start', 'restart') and
++        os.path.exists('/proc/sys/crypto/fips_enabled')):
++        with open('/proc/sys/crypto/fips_enabled', 'r') as f:
++            if f.read().strip() != '0':
++                raise IpactlError("Cannot start IPA server in FIPS mode")
++
+     # check if IPA is configured at all
+     try:
+         check_IPA_configuration()
+diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
+index 75a1711a7e1fdc9359ad02d55ad94d65af51ea93..53d969ee0b607a4392a008daebaf3befc0785084 100755
+--- a/ipa-client/ipa-install/ipa-client-install
++++ b/ipa-client/ipa-install/ipa-client-install
+@@ -2865,6 +2865,10 @@ def main():
+ 
+     if not os.getegid() == 0:
+         sys.exit("\nYou must be root to run ipa-client-install.\n")
++    if os.path.exists('/proc/sys/crypto/fips_enabled'):
++        with open('/proc/sys/crypto/fips_enabled', 'r') as f:
++            if f.read().strip() != '0':
++                sys.exit("Cannot install IPA client in FIPS mode")
+     tasks.check_selinux_status()
+     logging_setup(options)
+     root_logger.debug(
+-- 
+2.1.0
+
diff --git a/SOURCES/1010-Disable-DNSSEC-support.patch b/SOURCES/1010-Disable-DNSSEC-support.patch
new file mode 100644
index 0000000..e550f55
--- /dev/null
+++ b/SOURCES/1010-Disable-DNSSEC-support.patch
@@ -0,0 +1,512 @@
+From 80cae5f5ea38528caab01efae9100659e2ebb86e Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 21 Oct 2014 14:25:50 +0200
+Subject: [PATCH] Disable DNSSEC support
+
+---
+ install/share/bind.named.conf.template |  2 +-
+ install/tools/ipa-dns-install          | 52 ++++------------------------------
+ install/tools/ipa-replica-install      | 16 ++++-------
+ install/tools/ipa-replica-manage       | 12 --------
+ install/tools/ipa-server-install       | 40 +++-----------------------
+ install/tools/ipa-upgradeconfig        | 10 -------
+ ipalib/plugins/dns.py                  |  4 ++-
+ ipaplatform/redhat/services.py         |  6 ++--
+ ipapython/Makefile                     |  2 +-
+ ipapython/setup.py.in                  |  2 +-
+ ipaserver/install/bindinstance.py      | 25 ----------------
+ 11 files changed, 24 insertions(+), 147 deletions(-)
+
+diff --git a/install/share/bind.named.conf.template b/install/share/bind.named.conf.template
+index 3c19383c0dde4353b30b16240ec2b81d7ea65776..b3b06211b15cc1736453b203b52bacfba8036618 100644
+--- a/install/share/bind.named.conf.template
++++ b/install/share/bind.named.conf.template
+@@ -18,7 +18,7 @@ options {
+ 	pid-file "$NAMED_PID";
+ 
+ 	dnssec-enable yes;
+-	dnssec-validation yes;
++	dnssec-validation no;
+ 
+ 	/* Path to ISC DLV key */
+ 	bindkeys-file "$BINDKEYS_FILE";
+diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
+index cbf3faeef3644870b6978e02c95f67354cc7e61b..114351c9f7a5a779e4c8516c1411139c38d7138b 100755
+--- a/install/tools/ipa-dns-install
++++ b/install/tools/ipa-dns-install
+@@ -23,8 +23,7 @@ from optparse import OptionGroup, SUPPRESS_HELP
+ 
+ import krbV
+ 
+-from ipaserver.install import (service, bindinstance, ntpinstance,
+-    httpinstance, dnskeysyncinstance, opendnssecinstance, odsexporterinstance)
++from ipaserver.install import service, bindinstance, ntpinstance, httpinstance
+ from ipaserver.install.installutils import *
+ from ipaserver.install import installutils
+ from ipapython import version
+@@ -54,10 +53,6 @@ def parse_options():
+                       help="The reverse DNS zone to use")
+     parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
+                       default=False, help="Do not create new reverse DNS zone")
+-    parser.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true",
+-                      default=False, help="Disable DNSSEC validation")
+-    parser.add_option("--dnssec-master", dest="dnssec_master", action="store_true",
+-                      default=False, help="Setup server to be DNSSEC key master")
+     parser.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
+                       type="string",
+                       help="DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN")
+@@ -67,6 +62,10 @@ def parse_options():
+     options, args = parser.parse_args()
+     safe_options = parser.get_safe_opts(options)
+ 
++    # Disable DNSSEC support
++    options.no_dnssec_validation = False
++    options.dnssec_master = False
++
+     if options.forwarders and options.no_forwarders:
+         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
+     elif options.reverse_zones and options.no_reverse:
+@@ -101,21 +100,6 @@ def main():
+     print ""
+     print "This includes:"
+     print "  * Configure DNS (bind)"
+-    print "  * Configure SoftHSM (required by DNSSEC)"
+-    print "  * Configure ipa-dnskeysyncd (required by DNSSEC)"
+-    if options.dnssec_master:
+-        print "  * Configure ipa-ods-exporter (required by DNSSEC key master)"
+-        print "  * Configure OpenDNSSEC (required by DNSSEC key master)"
+-        print "  * Generate DNSSEC master key (required by DNSSEC key master)"
+-    print ""
+-    print "NOTE: DNSSEC zone signing is not enabled by default"
+-    print ""
+-    if options.dnssec_master:
+-        print "DNSSEC support is experimental!"
+-        print ""
+-        print "Plan carefully, current version doesn't allow you to move DNSSEC"
+-        print "key master to different server and master cannot be uninstalled"
+-        print ""
+     print ""
+     print "To accept the default shown in brackets, press the Enter key."
+     print ""
+@@ -126,15 +110,9 @@ def main():
+         sys.exit("Aborted")
+ 
+     # Check bind packages are installed
+-    if not (bindinstance.check_inst(options.unattended) and
+-            dnskeysyncinstance.check_inst()):
++    if not bindinstance.check_inst(options.unattended):
+         sys.exit("Aborting installation.")
+ 
+-    if options.dnssec_master:
+-        # check opendnssec packages are installed
+-        if not opendnssecinstance.check_inst():
+-            sys.exit("Aborting installation")
+-
+     # Initialize the ipalib api
+     cfg = dict(
+         in_server=True,
+@@ -160,14 +138,6 @@ def main():
+     except errors.ACIError:
+         sys.exit("Password is not valid!")
+ 
+-    ods = opendnssecinstance.OpenDNSSECInstance(fstore, dm_password)
+-    if options.dnssec_master:
+-        dnssec_masters = ods.get_masters()
+-        # we can reinstall current server if it is dnssec master
+-        if not api.env.host in dnssec_masters and dnssec_masters:
+-            print "DNSSEC key master(s):", u','.join(dnssec_masters)
+-            sys.exit("Only one DNSSEC key master is supported in current version.")
+-
+     ip_addresses = get_server_ip_address(api.env.host, fstore,
+         options.unattended, True, options.ip_addresses)
+ 
+@@ -213,16 +183,6 @@ def main():
+                no_dnssec_validation=options.no_dnssec_validation)
+     bind.create_instance()
+ 
+-    # on dnssec master this must be installed last
+-    dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(fstore, dm_password)
+-    dnskeysyncd.create_instance(api.env.host, api.env.realm)
+-    if options.dnssec_master:
+-        ods_exporter = odsexporterinstance.ODSExporterInstance(fstore, dm_password)
+-
+-        ods_exporter.create_instance(api.env.host, api.env.realm)
+-        ods.create_instance(api.env.host, api.env.realm)
+-
+-    dnskeysyncd.start_dnskeysyncd()
+     bind.start_named()
+ 
+     # Restart http instance to make sure that python-dns has the right resolver
+diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
+index 70190b718965518803b9767325d58f9526c32f7c..b8813aaa5d54d40756e9d9b8f0ee3e2dd7e8b253 100755
+--- a/install/tools/ipa-replica-install
++++ b/install/tools/ipa-replica-install
+@@ -33,7 +33,7 @@ from ipapython import ipautil
+ 
+ from ipaserver.install import dsinstance, installutils, krbinstance, service
+ from ipaserver.install import bindinstance, httpinstance, ntpinstance
+-from ipaserver.install import memcacheinstance, dnskeysyncinstance
++from ipaserver.install import memcacheinstance
+ from ipaserver.install import otpdinstance
+ from ipaserver.install.replication import replica_conn_check, ReplicationManager
+ from ipaserver.install.installutils import (ReplicaConfig, expand_replica_info,
+@@ -112,8 +112,6 @@ def parse_options():
+                          action="append", help="The reverse DNS zone to use")
+     dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
+                       default=False, help="Do not create new reverse DNS zone")
+-    dns_group.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true",
+-                      default=False, help="Disable DNSSEC validation")
+     dns_group.add_option("--no-host-dns", dest="no_host_dns", action="store_true",
+                       default=False,
+                       help="Do not use DNS for hostname lookup during installation")
+@@ -127,6 +125,9 @@ def parse_options():
+     # pkinit is disabled in production version
+     options.setup_pkinit = False
+ 
++    # Disable DNSSEC support
++    options.no_dnssec_validation = False
++
+     if len(args) != 1:
+         parser.error("you must provide a file generated by ipa-replica-prepare")
+ 
+@@ -139,8 +140,6 @@ def parse_options():
+             parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
+         if options.no_reverse:
+             parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
+-        if options.no_dnssec_validation:
+-            parser.error("You cannot specify a --no-dnssec-validation option without the --setup-dns option")
+     elif options.forwarders and options.no_forwarders:
+         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
+     elif not options.forwarders and not options.no_forwarders:
+@@ -274,10 +273,6 @@ def install_bind(config, options):
+                no_dnssec_validation=options.no_dnssec_validation)
+     bind.create_instance()
+     print ""
+-    dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(
+-        dm_password=config.dirman_password)
+-    dnskeysyncd.create_instance(api.env.host, api.env.realm)
+-    dnskeysyncd.start_dnskeysyncd()
+     bind.start_named()
+     print ""
+     bind.check_global_configuration()
+@@ -354,8 +349,7 @@ def check_dirsrv():
+         sys.exit(1)
+ 
+ def check_bind():
+-    if not (bindinstance.check_inst(unattended=True) and
+-            dnskeysyncinstance.check_inst()):
++    if not bindinstance.check_inst(unattended=True):
+         print "Aborting installation"
+         sys.exit(1)
+ 
+diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
+index 4f92c0c927b3267eeb466a06d3283823c05437b0..86d77844489abe4d7151a29a4e81320e01d5c412 100755
+--- a/install/tools/ipa-replica-manage
++++ b/install/tools/ipa-replica-manage
+@@ -29,7 +29,6 @@ import socket
+ from ipapython import ipautil
+ from ipaserver.install import replication, dsinstance, installutils
+ from ipaserver.install import bindinstance, cainstance, certs
+-from ipaserver.install import opendnssecinstance, dnskeysyncinstance
+ from ipaserver.plugins import ldap2
+ from ipapython import version, ipaldap
+ from ipalib import api, errors, util
+@@ -695,14 +694,6 @@ def del_master(realm, hostname, options):
+             if not options.force and not ipautil.user_input("Continue to delete?", False):
+                 sys.exit("Deletion aborted")
+ 
+-        # test if replica is not DNSSEC master
+-        # allow to delete it if is last DNS server
+-        if 'DNS' in this_services and other_dns and not options.force:
+-            dnssec_masters = opendnssecinstance.get_dnssec_key_masters(delrepl.conn)
+-            if hostname in dnssec_masters:
+-                print "Replica is active DNSSEC key master. Uninstall could break your DNS system."
+-                sys.exit("Deletion aborted")
+-
+         # Pick CA renewal master
+         ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR)
+         if ca.is_renewal_master(hostname):
+@@ -757,9 +748,6 @@ def del_master(realm, hostname, options):
+             bind.remove_master_dns_records(hostname, realm, realm.lower())
+             bind.remove_ipa_ca_dns_records(hostname, realm.lower())
+             bind.remove_server_ns_records(hostname)
+-
+-            keysyncd = dnskeysyncinstance.DNSKeySyncInstance()
+-            keysyncd.remove_replica_public_keys(hostname)
+     except Exception, e:
+         print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
+         print "You may need to manually remove them from the tree"
+diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
+index 3b748aaab37fa8806ebc7a4983ed97cc8243a9c4..6bcb0a16dbdfc0258ab40c70ea94740dfb537d8a 100755
+--- a/install/tools/ipa-server-install
++++ b/install/tools/ipa-server-install
+@@ -49,9 +49,6 @@ except ImportError:
+ from ipaserver.install import dsinstance
+ from ipaserver.install import krbinstance
+ from ipaserver.install import bindinstance
+-from ipaserver.install import dnskeysyncinstance
+-from ipaserver.install import opendnssecinstance
+-from ipaserver.install import odsexporterinstance
+ from ipaserver.install import httpinstance
+ from ipaserver.install import ntpinstance
+ from ipaserver.install import certs
+@@ -272,8 +269,6 @@ def parse_options():
+                       action="append", default=[])
+     dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
+                       default=False, help="Do not create reverse DNS zone")
+-    dns_group.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true",
+-                      default=False, help="Disable DNSSEC validation")
+     dns_group.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
+                       type="string",
+                       help="DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN")
+@@ -297,6 +292,9 @@ def parse_options():
+     options.pkinit_pin = False
+     options.pkinit_cert_files = False
+ 
++    # Disable DNSSEC support
++    options.no_dnssec_validation = False
++
+     if options.dm_password is not None:
+         try:
+             validate_dm_password(options.dm_password)
+@@ -323,8 +321,6 @@ def parse_options():
+             parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
+         if options.no_reverse:
+             parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
+-        if options.no_dnssec_validation:
+-            parser.error("You cannot specify a --no-dnssec-validation option without the --setup-dns option")
+     elif options.forwarders and options.no_forwarders:
+         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
+     elif options.reverse_zones and options.no_reverse:
+@@ -564,17 +560,7 @@ def uninstall():
+         api.env.realm, certs.NSS_DIR, dogtag_constants=dogtag_constants)
+     if ca_instance.is_configured():
+         ca_instance.uninstall()
+-
+-    ods = opendnssecinstance.OpenDNSSECInstance(fstore)
+-    if ods.is_configured():
+-        ods.uninstall()
+-
+-    ods_exporter = odsexporterinstance.ODSExporterInstance(fstore)
+-    if ods_exporter.is_configured():
+-        ods_exporter.uninstall()
+-
+     bindinstance.BindInstance(fstore).uninstall()
+-    dnskeysyncinstance.DNSKeySyncInstance(fstore).uninstall()
+     httpinstance.HTTPInstance(fstore).uninstall()
+     krbinstance.KrbInstance(fstore).uninstall()
+     dsinstance.DsInstance(fstore=fstore).uninstall()
+@@ -737,20 +723,6 @@ def main():
+                    "agreements.\n\n")
+             print textwrap.fill(msg, width=80, replace_whitespace=False)
+         else:
+-
+-            # test if server is DNSSEC key master
+-            masters = opendnssecinstance.get_dnssec_key_masters(conn)
+-            if api.env.host in masters:
+-                print "This server is active DNSSEC key master. Uninstall could break your DNS system."
+-                if not (options.unattended or user_input("Are you sure you "
+-                                                         "want to continue "
+-                                                         "with the uninstall "
+-                                                         "procedure?",
+-                                                         False)):
+-                    print ""
+-                    print "Aborting uninstall operation."
+-                    sys.exit(1)
+-
+             rm = replication.ReplicationManager(
+                 realm=api.env.realm,
+                 hostname=api.env.host,
+@@ -899,8 +871,7 @@ def main():
+ 
+     # check bind packages are installed
+     if options.setup_dns:
+-        if not (bindinstance.check_inst(options.unattended) and
+-                dnskeysyncinstance.check_inst()):
++        if not bindinstance.check_inst(options.unattended):
+             sys.exit("Aborting installation")
+ 
+         # Don't require an external DNS to say who we are if we are
+@@ -1289,9 +1260,6 @@ def main():
+         api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password)
+ 
+         bind.create_instance()
+-        dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(fstore, dm_password)
+-        dnskeysyncd.create_instance(api.env.host, api.env.realm)
+-        dnskeysyncd.start_dnskeysyncd()
+         bind.start_named()
+         print ""
+         bind.check_global_configuration()
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index cd50edeecb055c71831fad806afde43c2779cdf8..cf85f58c26510fcd105b54126152a50474c869b5 100755
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -53,7 +53,6 @@ from ipaserver.install import cainstance
+ from ipaserver.install import certs
+ from ipaserver.install import otpdinstance
+ from ipaserver.install import sysupgrade
+-from ipaserver.install import dnskeysyncinstance
+ 
+ 
+ def parse_options():
+@@ -1421,14 +1420,6 @@ def main():
+         except ipalib.errors.DuplicateEntry:
+             pass
+ 
+-    # install DNSKeySync service only if DNS is configured on server
+-    if bindinstance.named_conf_exists():
+-            dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(fstore, ldapi=True)
+-            if not dnskeysyncd.is_configured():
+-                ds.start()
+-                dnskeysyncd.create_instance(fqdn, api.env.realm)
+-                dnskeysyncd.start_dnskeysyncd()
+-
+     cleanup_kdc(fstore)
+     cleanup_adtrust(fstore)
+     setup_firefox_extension(fstore)
+@@ -1447,7 +1438,6 @@ def main():
+                           named_bindkey_file_option(),
+                           named_managed_keys_dir_option(),
+                           named_root_key_include(),
+-                          mask_named_regular(),
+                          )
+ 
+     if any(named_conf_changes):
+diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
+index 34afc189866993481229bb68a5edd77e0a4eaff3..d01dde31ad37f7d7aa4044de77704f4d560f0d30 100644
+--- a/ipalib/plugins/dns.py
++++ b/ipalib/plugins/dns.py
+@@ -2362,7 +2362,9 @@ class dnszone(DNSZoneBase):
+             if options['idnssecinlinesigning'] is True:
+                 messages.add_message(options['version'], result,
+                     messages.DNSSECWarning(
+-                    additional_info=_("Visit 'http://www.freeipa.org/page/Releases/4.1.0#DNSSEC_Support'.")
++                    additional_info=_("Manual configuration needed, please "
++                    "visit 'http://www.freeipa.org/page/Releases/4.0.0#"
++                    "Experimental_DNSSEC_Support'")
+                 ))
+             else:
+                 messages.add_message(options['version'], result,
+diff --git a/ipaplatform/redhat/services.py b/ipaplatform/redhat/services.py
+index 20d0adec421ecd3285464e2a51b9d5c61a0e3d92..5c9bae56552cefec1f3b8a16a52b8704171d4024 100644
+--- a/ipaplatform/redhat/services.py
++++ b/ipaplatform/redhat/services.py
+@@ -69,7 +69,7 @@ redhat_system_units['ipa-otpd'] = 'ipa-otpd.socket'
+ redhat_system_units['ipa-dnskeysyncd'] = 'ipa-dnskeysyncd.service'
+ redhat_system_units['named-regular'] = 'named.service'
+ redhat_system_units['named-pkcs11'] = 'named-pkcs11.service'
+-redhat_system_units['named'] = redhat_system_units['named-pkcs11']
++redhat_system_units['named'] = redhat_system_units['named-regular']
+ redhat_system_units['ods-enforcerd'] = 'ods-enforcerd.service'
+ redhat_system_units['ods_enforcerd'] = redhat_system_units['ods-enforcerd']
+ redhat_system_units['ods-signerd'] = 'ods-signerd.service'
+@@ -242,10 +242,10 @@ class RedHatNamedService(RedHatService):
+         return u'named'
+ 
+     def get_binary_path(self):
+-        return paths.NAMED_PKCS11
++        return paths.NAMED
+ 
+     def get_package_name(self):
+-        return u"bind-pkcs11"
++        return u"bind"
+ 
+ 
+ class RedHatODSEnforcerdService(RedHatService):
+diff --git a/ipapython/Makefile b/ipapython/Makefile
+index b2cf719fdd580801a147def17e5a7483665b3d79..e09956ad32cf48d1ed585a494c8083e58c48d037 100644
+--- a/ipapython/Makefile
++++ b/ipapython/Makefile
+@@ -3,7 +3,7 @@ PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/ipa
+ CONFIGDIR ?= $(DESTDIR)/etc/ipa
+ TESTS = $(wildcard test/*.py)
+ 
+-SUBDIRS = py_default_encoding ipap11helper
++SUBDIRS = py_default_encoding
+ 
+ all:
+ 	@for subdir in $(SUBDIRS); do \
+diff --git a/ipapython/setup.py.in b/ipapython/setup.py.in
+index 6caf179051533e0db77a4091db5874bbdae426c9..a839f094ac0f9a2c303862e397bb4deb7589cc62 100644
+--- a/ipapython/setup.py.in
++++ b/ipapython/setup.py.in
+@@ -65,7 +65,7 @@ def setup_package():
+             classifiers=filter(None, CLASSIFIERS.split('\n')),
+             platforms = ["Linux", "Solaris", "Unix"],
+             package_dir = {'ipapython': ''},
+-            packages = [ "ipapython", "ipapython.dnssec" ],
++            packages = [ "ipapython" ],
+         )
+     finally:
+         del sys.path[0]
+diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
+index 547cf19ee36140b5f29fcf7d217933fa68e1952b..9085cf9b59a064d82c0df774a6fa961c9d158ccf 100644
+--- a/ipaserver/install/bindinstance.py
++++ b/ipaserver/install/bindinstance.py
+@@ -543,7 +543,6 @@ class BindInstance(service.Service):
+         self.sub_dict = None
+         self.reverse_zones = []
+         self.dm_password = dm_password
+-        self.named_regular = services.service('named-regular')
+ 
+         if fstore:
+             self.fstore = fstore
+@@ -652,8 +651,6 @@ class BindInstance(service.Service):
+             if self.get_state("running") is None:
+                 # first time store status
+                 self.backup_state("running", self.is_running())
+-                self.backup_state("named-regular-running",
+-                                  self.named_regular.is_running())
+             self.restart()
+         except Exception as e:
+             root_logger.error("Named service failed to start (%s)", e)
+@@ -662,8 +659,6 @@ class BindInstance(service.Service):
+     def __enable(self):
+         if self.get_state("enabled") is None:
+             self.backup_state("enabled", self.is_running())
+-            self.backup_state("named-regular-enabled",
+-                              self.named_regular.is_running())
+         # 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
+@@ -674,17 +669,6 @@ class BindInstance(service.Service):
+             # don't crash, just report error
+             root_logger.error("DNS service already exists")
+ 
+-        # disable named, we need to run named-pkcs11 only
+-        try:
+-            self.named_regular.stop()
+-        except Exception as e:
+-            root_logger.debug("Unable to stop named (%s)", e)
+-
+-        try:
+-            self.named_regular.mask()
+-        except Exception as e:
+-            root_logger.debug("Unable to mask named (%s)", e)
+-
+     def __setup_sub_dict(self):
+         if self.forwarders:
+             fwds = "\n"
+@@ -1167,8 +1151,6 @@ class BindInstance(service.Service):
+ 
+         running = self.restore_state("running")
+         enabled = self.restore_state("enabled")
+-        named_regular_running = self.restore_state("named-regular-running")
+-        named_regular_enabled = self.restore_state("named-regular-enabled")
+ 
+         self.dns_backup.clear_records(api.Backend.ldap2.isconnected())
+ 
+@@ -1187,10 +1169,3 @@ class BindInstance(service.Service):
+ 
+         if not running is None and running:
+             self.start()
+-
+-        self.named_regular.unmask()
+-        if named_regular_enabled:
+-            self.named_regular.enable()
+-
+-        if named_regular_running:
+-            self.named_regular.start()
+-- 
+2.1.0
+
diff --git a/SOURCES/1011-Disable-TLS-1.2-in-nss.conf-until-mod_nss-supports-i.patch b/SOURCES/1011-Disable-TLS-1.2-in-nss.conf-until-mod_nss-supports-i.patch
new file mode 100644
index 0000000..2dcc4c1
--- /dev/null
+++ b/SOURCES/1011-Disable-TLS-1.2-in-nss.conf-until-mod_nss-supports-i.patch
@@ -0,0 +1,59 @@
+From e1bac92634c2783b4003d496539810a2d993f71d Mon Sep 17 00:00:00 2001
+From: Jan Cholasta <jcholast@redhat.com>
+Date: Tue, 9 Dec 2014 10:33:20 +0000
+Subject: [PATCH] Disable TLS 1.2 in nss.conf until mod_nss supports it
+
+---
+ install/tools/ipa-upgradeconfig   | 8 ++++++--
+ ipaserver/install/httpinstance.py | 4 ++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
+index cf85f58c26510fcd105b54126152a50474c869b5..2691f0b0f217793243f7a0813f351c4364e2a951 100755
+--- a/install/tools/ipa-upgradeconfig
++++ b/install/tools/ipa-upgradeconfig
+@@ -1276,13 +1276,17 @@ def fix_trust_flags():
+ def update_mod_nss_protocol(http):
+     root_logger.info('[Updating mod_nss protocol versions]')
+ 
+-    if sysupgrade.get_upgrade_state('nss.conf', 'protocol_updated_tls12'):
++    if sysupgrade.get_upgrade_state('nss.conf', 'protocol_updated_tls11'):
+         root_logger.info("Protocol versions already updated")
+         return
+ 
+     http.set_mod_nss_protocol()
+ 
+-    sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12', True)
++    sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls11', True)
++
++    if sysupgrade.get_upgrade_state('nss.conf', 'protocol_updated_tls12'):
++        sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12',
++                                     False)
+ 
+ 
+ def main():
+diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
+index cda85ab02b8054748e671935fcfbc3993257c53e..13c44abf59dbaf6f4aef1425992fa8ff181a3007 100644
+--- a/ipaserver/install/httpinstance.py
++++ b/ipaserver/install/httpinstance.py
+@@ -119,7 +119,7 @@ class HTTPInstance(service.Service):
+ 
+ 
+         self.step("setting mod_nss port to 443", self.__set_mod_nss_port)
+-        self.step("setting mod_nss protocol list to TLSv1.0 - TLSv1.2",
++        self.step("setting mod_nss protocol list to TLSv1.0 - TLSv1.1",
+                   self.set_mod_nss_protocol)
+         self.step("setting mod_nss password file", self.__set_mod_nss_passwordfile)
+         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
+@@ -214,7 +214,7 @@ class HTTPInstance(service.Service):
+         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSNickname', nickname)
+ 
+     def set_mod_nss_protocol(self):
+-        installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSProtocol', 'TLSv1.0,TLSv1.1,TLSv1.2', False)
++        installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSProtocol', 'TLSv1.0,TLSv1.1', False)
+ 
+     def enable_mod_nss_renegotiate(self):
+         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRenegotiation', 'on', False)
+-- 
+2.1.0
+
diff --git a/SOURCES/1012-Expand-the-token-auth-sync-windows.patch b/SOURCES/1012-Expand-the-token-auth-sync-windows.patch
new file mode 100644
index 0000000..5c2e4ac
--- /dev/null
+++ b/SOURCES/1012-Expand-the-token-auth-sync-windows.patch
@@ -0,0 +1,43 @@
+From 8a76d55d4de3c7873089d168e4e02e6129bddce4 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Wed, 17 Dec 2014 14:05:42 +0000
+Subject: [PATCH] Expand the token auth/sync windows
+
+This is a workaround for RHEL 7.1 to give similar defaults to the
+configurable window patch that landed upstream. At some future point,
+when this upstream patch is merged into RHEL, this patch should be
+abandoned.
+---
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 2 +-
+ daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+index 96c55f39ba2a9dc1e9fc80d5f7d46787803ece47..4db6e4797a0eab4d92ef65bef60bf48fe9110106 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+@@ -68,7 +68,7 @@
+ #define IPAPWD_OP_ADD 1
+ #define IPAPWD_OP_MOD 2
+ 
+-#define OTP_VALIDATE_STEPS 3
++#define OTP_VALIDATE_STEPS 10
+ 
+ extern Slapi_PluginDesc ipapwd_plugin_desc;
+ extern void *ipapwd_plugin_id;
+diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+index 0aef438023e7f23d7219273e9f5efd5572e73c3f..b40fc66256abf14c4f6d9609f600747797c3c0ed 100644
+--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/syncreq.c
+@@ -40,7 +40,7 @@
+ #include "../libotp/otp_token.h"
+ #include "syncreq.h"
+ 
+-#define OTP_SYNC_MAX_STEPS 25
++#define OTP_SYNC_MAX_STEPS 100
+ 
+ bool sync_request_present(Slapi_PBlock *pb)
+ {
+-- 
+2.1.0
+
diff --git a/SOURCES/1013-ipa-kdb-reject-principals-from-disabled-domains-as-a.patch b/SOURCES/1013-ipa-kdb-reject-principals-from-disabled-domains-as-a.patch
new file mode 100644
index 0000000..7eba1a2
--- /dev/null
+++ b/SOURCES/1013-ipa-kdb-reject-principals-from-disabled-domains-as-a.patch
@@ -0,0 +1,27 @@
+From 50b420b5f8ec1c4a6696b387ee5f3378dd0257bc Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Wed, 10 Dec 2014 14:59:38 +0200
+Subject: [PATCH] ipa-kdb: reject principals from disabled domains as a KDC
+ policy
+
+Fixes https://fedorahosted.org/freeipa/ticket/4788
+---
+ 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 a4500070760e83994c8155a12ee6414b5ebee9e0..e3215db4ea11632dce8f039fc6b89c4a09acd87a 100644
+--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
+@@ -1375,7 +1375,7 @@ static krb5_error_code filter_logon_info(krb5_context context,
+                                    &domain->parent->sid_blacklist_incoming[k], true);
+             if (result) {
+                 filter_logon_info_log_message(info->info->info3.base.domain_sid);
+-                return EINVAL;
++                return KRB5KDC_ERR_POLICY;
+             }
+         }
+     }
+-- 
+2.1.0
+
diff --git a/SOURCES/ipa-centos-branding.patch b/SOURCES/ipa-centos-branding.patch
deleted file mode 100644
index 33b4609..0000000
--- a/SOURCES/ipa-centos-branding.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -uNrp freeipa-3.3.3.orig/ipaserver/install/ntpinstance.py freeipa-3.3.3/ipaserver/install/ntpinstance.py
---- freeipa-3.3.3.orig/ipaserver/install/ntpinstance.py	2013-11-01 10:34:30.000000000 -0500
-+++ freeipa-3.3.3/ipaserver/install/ntpinstance.py	2014-06-26 07:27:19.644718099 -0500
-@@ -43,6 +43,8 @@ class NTPInstance(service.Service):
-         os = ""
-         if ipautil.file_exists("/etc/fedora-release"):
-             os = "fedora"
-+        elif ipautil.file_exists("/etc/centos-release"):
-+            os = "centos"
-         elif ipautil.file_exists("/etc/redhat-release"):
-             os = "rhel"
- 
diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec
index 429f573..dbe9471 100644
--- a/SPECS/ipa.spec
+++ b/SPECS/ipa.spec
@@ -1,104 +1,165 @@
-# Define ONLY_CLIENT to only make the ipa-client and ipa-python subpackages
+# Define ONLY_CLIENT to only make the ipa-admintools, ipa-client and ipa-python
+# subpackages
 %{!?ONLY_CLIENT:%global ONLY_CLIENT 0}
 
+# RHEL spec file only: START
 %ifarch x86_64 %{ix86}
 # Nothing, we want to force just building client on non-Intel
 %else
 %global ONLY_CLIENT 1
 %endif
+%global VERSION 4.1.0
+# RHEL spec file only: END
+
+%global alt_name freeipa
+%if 0%{?rhel}
+%global samba_version 4.0.5-1
+%global selinux_policy_version 3.13.1-4
+%else
+%global samba_version 2:4.0.5-1
+%global selinux_policy_version 3.12.1-179
+%endif
 
 %global plugin_dir %{_libdir}/dirsrv/plugins
-%global POLICYCOREUTILSVER 2.1.14-37
 %global gettext_domain ipa
-%global VERSION 3.3.3
+%if 0%{?rhel}
+%global platform_module rhel
+%else
+%global platform_module fedora
+%endif
 
-%if (0%{?fedora} > 15 || 0%{?rhel} >= 7)
 %define _hardened_build 1
-%endif
 
 Name:           ipa
-Version:        3.3.3
-Release:        28.0.1%{?dist}.3
+Version:        4.1.0
+Release:        18%{?dist}
 Summary:        The Identity, Policy and Audit system
 
 Group:          System Environment/Base
 License:        GPLv3+
 URL:            http://www.freeipa.org/
 Source0:        http://www.freeipa.org/downloads/src/freeipa-%{VERSION}.tar.gz
-Source1:        rh-ipabanner.png
+# RHEL spec file only: START: Change branding to IPA and Identity-Management
+Source1:        header-logo.png
+Source2:        login-screen-background.jpg
+Source3:        login-screen-logo.png
+Source4:        product-name.png
+# RHEL spec file only: END: Change branding to IPA and Identity-Management
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
-Patch0001:      0001-Guard-import-of-adtrustinstance-for-case-without-tru.patch
-Patch0002:      0002-Server-does-not-detect-different-server-and-IPA-doma.patch
-Patch0003:      0003-Allow-kernel-keyring-CCACHE-when-supported.patch
-Patch0004:      0004-Fix-regression-which-prevents-creating-a-winsync-agr.patch
-Patch0005:      0005-trusts-Do-not-pass-base-id-to-the-subdomain-ranges.patch
-Patch0006:      0006-Map-NT_STATUS_INVALID_PARAMETER-to-most-likely-error.patch
-Patch0007:      0007-Remove-mod_ssl-port-workaround.patch
-Patch0008:      0008-subdomains-Use-AD-admin-credentials-when-trust-is-be.patch
-Patch0009:      0009-trusts-Always-stop-and-disable-smb-service-on-uninst.patch
-Patch0010:      0010-Use-hardening-flags-for-ipa-optd.patch
-Patch0011:      0011-test_integration-Support-external-names-for-hosts.patch
-Patch0012:      0012-ipa-client-install-Always-pass-hostname-to-the-ipa-j.patch
-Patch0013:      0013-trust-fix-get_dn-to-distinguish-creating-and-re-addi.patch
-Patch0014:      0014-ipa-cldap-Cut-NetBIOS-name-after-15-characters.patch
-Patch0015:      0015-Prevent-garbage-from-readline-on-standard-output-of-.patch
-Patch0016:      0016-Do-not-build-tests.patch
-Patch0017:      0017-PKI-service-restart-after-CA-renewal-failed.patch
-Patch0018:      0018-hbactest-does-not-work-for-external-users.patch
-Patch0019:      0019-Change-the-way-we-determine-if-the-host-has-a-passwo.patch
-Patch0020:      0020-sudoOrder-missing-in-sudoers.patch
-Patch0021:      0021-Add-missing-example-to-sudorule.patch
-Patch0022:      0022-Fix-ipa-client-automount-uninstall-when-fstore-is-em.patch
-Patch0023:      0023-trust-fetch-domains-create-ranges-for-new-child-doma.patch
-Patch0024:      0024-trustdomain-find-report-status-of-the-sub-domain.patch
-Patch0025:      0025-CLDAP-do-not-prepend.patch
-Patch0026:      0026-ipaserver-install-installutils-clean-up-properly-aft.patch
-Patch0027:      0027-Do-not-start-the-service-in-stopped_service-if-it-wa.patch
-Patch0028:      0028-Harmonize-policy-discovery-to-kdb-driver.patch
-Patch0029:      0029-Stop-adding-a-default-password-policy-reference.patch
-Patch0030:      0030-Increase-service-startup-timeout-default.patch
-Patch0031:      0031-cli.print_attribute-Convert-values-to-strings.patch
-Patch0032:      0032-group-show-resolve-external-members-of-the-groups.patch
-Patch0033:      0033-Remove-SID-resolve-call-from-Web-UI.patch
-Patch0034:      0034-ipa-adtrust-install-configure-host-netbios-name-by-d.patch
-Patch0035:      0035-Remove-missing-VERSION-warning-in-dnsrecord-mod.patch
-Patch0036:      0036-Hide-trust-resolve-command.patch
-Patch0037:      0037-Trust-domains-Web-UI.patch
-Patch0038:      0038-ipasam-delete-trusted-child-domains-before-removing-.patch
-Patch0039:      0039-CLDAP-generate-NetBIOS-name-like-ipa-adtrust-install.patch
-Patch0040:      0040-Fallback-to-global-policy-in-ipa-lockout-plugin.patch
-Patch0041:      0041-Migration-does-not-add-users-to-default-group.patch
-Patch0042:      0042-ipa-lockout-do-not-fail-when-default-realm-cannot-be.patch
-Patch0043:      0043-ipa-tool-Print-the-name-of-the-server-we-are-connect.patch
-Patch0044:      0044-Remove-sourcehostcategory-from-the-default-HBAC-rule.patch
-Patch0045:      0045-DNS-classless-support-for-reverse-domains.patch
-Patch0046:      0046-Move-ipa-otpd-socket-directory.patch
-Patch0047:      0047-bindinstance-make-sure-zone-manager-is-initialized-i.patch
-Patch0048:      0048-trustdomain_find-make-sure-we-skip-short-entries-whe.patch
-Patch0049:      0049-ipa-kdb-in-case-of-delegation-use-original-client-s-.patch
-Patch0050:      0050-ipa-kdb-make-sure-we-don-t-produce-MS-PAC-in-case-of.patch
-Patch0051:      0051-Too-big-font-in-input-fields.patch
-Patch0052:      0052-trust-make-sure-we-always-discover-topology-of-the-f.patch
-Patch0053:      0053-ipaserver-dcerpc-catch-the-case-of-insuffient-permis.patch
-Patch0054:      0054-fix-filtering-of-subdomain-based-trust-users.patch
-Patch0055:      0055-ipa-kdb-do-not-fetch-client-principal-if-it-is-the-s.patch
-Patch0056:      0056-ipa-replica-install-never-checks-for-7389-port.patch
-Patch0057:      0057-Avoid-passing-non-terminated-string-to-is_master_hos.patch
-Patch0058:      0058-ipa-sam-cache-gid-to-sid-and-uid-to-sid-requests-in-.patch
-Patch0059:      0059-ipaserver-dcerpc-make-sure-to-always-return-unicode-.patch
-Patch0060:      0060-trust-do-not-fetch-subdomains-in-case-shared-secret-.patch
-Patch0061:      0061-Update-Dogtag-9-database-during-replica-installation.patch
-Patch0062:      0062-Prohibit-deletion-of-active-subdomain-range.patch
-Patch0063:      0063-extdom-do-not-return-results-from-the-wrong-domain.patch
-Patch0064:      0064-Proxy-PKI-clone-ca-ee-ca-profileSubmit-URI.patch
-Patch0065:      0065-Make-ipa-client-automount-backwards-compatible.patch
-Patch0066:      0066-Convert-external-CA-chain-to-PKCS-7-before-passing-i.patch
-Patch0067:      0067-ipaserver-dcerpc.py-if-search-of-a-closest-GC-failed.patch
-Patch0068:      0068-ipaserver-dcerpc.py-make-PDC-discovery-more-robust.patch
-Patch0069:      0069-ipaserver-dcerpc.py-be-more-open-to-what-domains-can.patch
-Patch0070:      0070-ipaserver-dcerpc.py-Make-sure-trust-is-established-o.patch
-Patch0071:      0071-ipaserver-dcerpc.py-Avoid-hitting-issue-with-transit.patch
+# RHEL spec file only: START
+Patch0001:      0001-Do-not-check-if-port-8443-is-available-in-step-2-of-.patch
+Patch0002:      0002-Add-ipaSshPubkey-and-gidNumber-to-the-ACI-to-read-ID.patch
+Patch0003:      0003-Fix-dns-zonemgr-validation-regression.patch
+Patch0004:      0004-Handle-profile-changes-in-dogtag-ipa-ca-renew-agent.patch
+Patch0005:      0005-Do-not-wait-for-new-CA-certificate-to-appear-in-LDAP.patch
+Patch0006:      0006-Fail-if-certmonger-can-t-see-new-CA-certificate-in-L.patch
+Patch0007:      0007-Fix-possible-NULL-dereference-in-ipa-kdb.patch
+Patch0008:      0008-Fix-memory-leaks-in-ipa-extdom-extop.patch
+Patch0009:      0009-Fix-various-bugs-in-ipa-opt-counter-and-ipa-otp-last.patch
+Patch0010:      0010-Fix-memory-leak-in-ipa-pwd-extop.patch
+Patch0011:      0011-Fix-memory-leaks-in-ipa-join.patch
+Patch0012:      0012-Fix-various-bugs-in-ipap11helper.patch
+Patch0013:      0013-Deadlock-in-schema-compat-plugin-between-automember_.patch
+Patch0014:      0014-Stop-dirsrv-last-in-ipactl-stop.patch
+Patch0015:      0015-Fix-upgrade-do-not-use-invalid-ldap-connection.patch
+Patch0016:      0016-Ensure-that-a-password-exists-after-OTP-validation.patch
+Patch0017:      0017-ipa-restore-Don-t-crash-if-AD-trust-is-not-installed.patch
+Patch0018:      0018-ranges-prohibit-setting-rid-base-with-ipa-trust-ad-p.patch
+Patch0019:      0019-ldapupdater-set-baserid-to-0-for-ipa-ad-trust-posix-.patch
+Patch0020:      0020-idrange-include-raw-range-type-in-output.patch
+Patch0021:      0021-webui-prohibit-setting-rid-base-with-ipa-trust-ad-po.patch
+Patch0022:      0022-Fix-CA-certificate-backup-and-restore.patch
+Patch0023:      0023-Fix-DNS-installer-adds-invalid-zonemgr-email.patch
+Patch0024:      0024-ipaplatform-Use-the-dirsrv-service-not-target.patch
+Patch0025:      0025-Fix-DNS-policy-upgrade-raises-asertion-error.patch
+Patch0026:      0026-Fix-upgrade-referint-plugin.patch
+Patch0027:      0027-Upgrade-fix-trusts-objectclass-violationi.patch
+Patch0028:      0028-Produce-better-error-in-group-add-command.patch
+Patch0029:      0029-Search-using-proper-scope-when-connecting-CA-instanc.patch
+Patch0030:      0030-Fix-zonemgr-must-be-unicode-value.patch
+Patch0031:      0031-Fix-warning-message-should-not-contain-CLI-commands.patch
+Patch0032:      0032-Fix-wrong-expiration-date-on-renewed-IPA-CA-certific.patch
+Patch0033:      0033-Do-not-restore-SELinux-settings-that-were-not-backed.patch
+Patch0034:      0034-Improve-otptoken-help-messages.patch
+Patch0035:      0035-Ensure-users-exist-when-assigning-tokens-to-them.patch
+Patch0036:      0036-Enable-QR-code-display-by-default-in-otptoken-add.patch
+Patch0037:      0037-Show-warning-instead-of-error-if-CA-did-not-start.patch
+Patch0038:      0038-webui-fix-potential-XSS-vulnerabilities.patch
+Patch0039:      0039-Raise-right-exception-if-domain-name-is-not-valid.patch
+Patch0040:      0040-Restore-file-extended-attributes-and-SELinux-context.patch
+Patch0041:      0041-restore-clear-httpd-ccache-after-restore.patch
+Patch0042:      0042-Fix-user-group-ignore-attribute-in-migration-plugin.patch
+Patch0043:      0043-Fix-filtering-of-enctypes-in-server-code.patch
+Patch0044:      0044-Add-asn1c-generated-code-for-keytab-controls.patch
+Patch0045:      0045-Use-asn1c-helpers-to-encode-decode-the-getkeytab-con.patch
+Patch0046:      0046-Fix-read_ip_addresses-should-return-ipaddr-object.patch
+Patch0047:      0047-Use-correct-service-name-in-cainstance.backup_config.patch
+Patch0048:      0048-ipa-restore-Check-if-directory-is-provided-better-er.patch
+Patch0049:      0049-Stop-tracking-certificates-before-restoring-them-in-.patch
+Patch0050:      0050-Fix-detection-of-encoding-in-zonemgr-option.patch
+Patch0051:      0051-webui-use-domain-name-instead-of-domain-SID-in-idran.patch
+Patch0052:      0052-webui-normalize-idview-tab-labels.patch
+Patch0053:      0053-copy_schema_to_ca-Fallback-to-old-import-location-fo.patch
+Patch0054:      0054-Remove-redefinition-of-LOG-from-ipa-otp-lasttoken.patch
+Patch0055:      0055-Unload-P11_Helper-object-s-library-when-it-is-finali.patch
+Patch0056:      0056-Fix-Kerberos-error-handling-in-ipa-sam.patch
+Patch0057:      0057-Fix-unchecked-return-value-in-ipa-kdb.patch
+Patch0058:      0058-Fix-unchecked-return-values-in-ipa-winsync.patch
+Patch0059:      0059-Fix-unchecked-return-value-in-ipa-join.patch
+Patch0060:      0060-Fix-unchecked-return-value-in-krb5-common-utils.patch
+Patch0061:      0061-Fix-memory-leak-in-GetKeytabControl-asn1-code.patch
+Patch0062:      0062-AD-trust-improve-trust-validation.patch
+Patch0063:      0063-Add-TLS-1.2-to-the-protocol-list-in-mod_nss-config.patch
+Patch0064:      0064-webui-add-radius-fields-to-user-page.patch
+Patch0065:      0065-Fix-zonemgr-option-encoding-detection.patch
+Patch0066:      0066-Catch-USBError-during-YubiKey-location.patch
+Patch0067:      0067-Use-NSS-protocol-range-API-to-set-available-TLS-prot.patch
+Patch0068:      0068-Throw-zonemgr-error-message-before-installation-proc.patch
+Patch0069:      0069-certs-Fix-incorrect-flag-handling-in-load_cacert.patch
+Patch0070:      0070-Preliminary-refactoring-of-libotp-files.patch
+Patch0071:      0071-Move-authentication-configuration-cache-into-libotp.patch
+Patch0072:      0072-Enable-last-token-deletion-when-password-auth-type-i.patch
+Patch0073:      0073-add-hosts-and-hostgroup-options-to-allow-retrieve-ke.patch
+Patch0074:      0074-hosts-Display-assigned-ID-view-by-default-in-host-fi.patch
+Patch0075:      0075-Prefer-TCP-connections-to-UDP-in-krb5-clients.patch
+Patch0076:      0076-webui-fix-service-unprovisioning.patch
+Patch0077:      0077-webui-increase-duration-of-notification-messages.patch
+Patch0078:      0078-Fix-automatic-CA-cert-renewal-endless-loop-in-dogtag.patch
+Patch0079:      0079-Do-not-renew-the-IPA-CA-cert-by-serial-number-in-dog.patch
+Patch0080:      0080-Improve-validation-of-instance-and-backend-options-i.patch
+Patch0081:      0081-revert-removal-of-cn-attribute-from-idnsRecord.patch
+Patch0082:      0082-Check-subject-name-encoding-in-ipa-cacert-manage-ren.patch
+Patch0083:      0083-Refer-the-user-to-freeipa.org-when-something-goes-wr.patch
+Patch0084:      0084-Show-SSHFP-record-containing-space-in-fingerprint.patch
+Patch0085:      0085-Always-add-etc-hosts-record-when-DNS-is-being-config.patch
+Patch0086:      0086-Avoid-calling-ldap-functions-without-a-context.patch
+Patch0087:      0087-Remove-the-removal-of-the-ccache.patch
+Patch0088:      0088-Fix-Upgrade-forwardzones-zones-after-adding-newer-re.patch
+Patch0089:      0089-Fix-zone-find-during-forwardzone-upgrade.patch
+Patch0090:      0090-migrate-ds-fix-compat-plugin-check.patch
+Patch0091:      0091-rpcclient-use-json_encode_binary-for-verbose-output.patch
+Patch0092:      0092-Remove-ipanttrustauthincoming-ipanttrustauthoutgoing.patch
+Patch0093:      0093-Abort-backup-restoration-on-not-matching-host.patch
+Patch0094:      0094-Fix-ipa-restore-on-systems-without-IPA-installed.patch
+Patch0095:      0095-Remove-RUV-from-LDIF-files-before-using-them-in-ipa-.patch
+Patch0096:      0096-Fix-CA-certificate-renewal-syslog-alert.patch
+Patch0097:      0097-Do-not-crash-on-unknown-services-in-installutils.sto.patch
+Patch0098:      0098-Restart-dogtag-when-its-server-certificate-is-renewe.patch
+Patch0099:      0099-Make-certificate-renewal-process-synchronized.patch
+Patch0100:      0100-Fix-validation-of-ipa-restore-options.patch
+Patch0101:      0101-Allow-PassSync-user-to-locate-and-update-NT-users.patch
+Patch0102:      0102-Allow-Replication-Administrators-manipulate-Winsync-.patch
+Patch0103:      0103-Do-not-assume-certmonger-is-running-in-httpinstance.patch
+Patch0104:      0104-Replication-Administrators-cannot-remove-replication.patch
+Patch0105:      0105-Put-LDIF-files-to-their-original-location-in-ipa-res.patch
+Patch0106:      0106-Add-anonymous-read-ACI-for-DUA-profile.patch
+Patch0107:      0107-Revert-Make-all-ipatokenTOTP-attributes-mandatory.patch
+Patch0108:      0108-Create-correct-log-directories-during-full-restore-i.patch
+Patch0109:      0109-Do-not-crash-when-replica-is-unreachable-in-ipa-rest.patch
+Patch0110:      0110-idviews-Allow-setting-ssh-public-key-on-ipauseroverr.patch
+Patch0111:      0111-Fix-ipa-pwd-extop-global-configuration-caching.patch
+Patch0112:      0112-group-detach-does-not-add-correct-objectclasses.patch
 
 Patch1001:      1001-Hide-pkinit-functionality-from-production-version.patch
 Patch1002:      1002-Remove-pkinit-plugin.patch
@@ -106,15 +167,21 @@ Patch1003:      1003-Remove-pkinit-references-from-tool-man-pages.patch
 Patch1004:      1004-Change-branding-to-IPA-and-Identity-Management.patch
 Patch1005:      1005-Remove-pylint-from-build-process.patch
 Patch1006:      1006-Remove-i18test-from-build-process.patch
-Patch1007:      1007-Remove-ipa-backup-and-ipa-restore-functionality.patch
-Patch1008:      ipa-centos-branding.patch
+Patch1007:      1007-Do-not-build-tests.patch
+Patch1008:      1008-RCUE.patch
+Patch1009:      1009-Do-not-allow-installation-in-FIPS-mode.patch
+Patch1010:      1010-Disable-DNSSEC-support.patch
+Patch1011:      1011-Disable-TLS-1.2-in-nss.conf-until-mod_nss-supports-i.patch
+Patch1012:      1012-Expand-the-token-auth-sync-windows.patch
+Patch1013:      1013-ipa-kdb-reject-principals-from-disabled-domains-as-a.patch
+# RHEL spec file only: END
 
 %if ! %{ONLY_CLIENT}
-BuildRequires:  389-ds-base-devel >= 1.3.1
+BuildRequires:  389-ds-base-devel >= 1.3.3.1-10
 BuildRequires:  svrcore-devel
-BuildRequires:  policycoreutils >= %{POLICYCOREUTILSVER}
+BuildRequires:  policycoreutils >= 2.1.14-37
 BuildRequires:  systemd-units
-BuildRequires:  samba-devel >= 4.0.5-1
+BuildRequires:  samba-devel >= %{samba_version}
 BuildRequires:  samba-python
 BuildRequires:  libwbclient-devel
 BuildRequires:  libtalloc-devel
@@ -141,30 +208,34 @@ BuildRequires:  python-setuptools
 BuildRequires:  python-krbV
 BuildRequires:  python-nss
 BuildRequires:  python-netaddr
-BuildRequires:  python-kerberos
+BuildRequires:  python-kerberos >= 1.1-15
 BuildRequires:  python-rhsm
 BuildRequires:  pyOpenSSL
+# RHEL spec file only: DELETED: Remove pylint from build process
+# RHEL spec file only: DELETED: Remove i18test from build process
 BuildRequires:  libipa_hbac-python
 BuildRequires:  python-memcached
 BuildRequires:  sssd >= 1.9.2
 BuildRequires:  python-lxml
 BuildRequires:  python-pyasn1 >= 0.0.9a
-BuildRequires:  python-dns
+BuildRequires:  python-qrcode-core >= 5.0.0
+BuildRequires:  python-dns >= 1.11.1-2
 BuildRequires:  m2crypto
 BuildRequires:  check
 BuildRequires:  libsss_idmap-devel
-BuildRequires:  libsss_nss_idmap-devel
-BuildRequires:  java-1.7.0-openjdk
+BuildRequires:  libsss_nss_idmap-devel >= 1.12.2
+BuildRequires:  java-headless
 BuildRequires:  rhino
 BuildRequires:  libverto-devel
 BuildRequires:  systemd
 BuildRequires:  libunistring-devel
+# RHEL spec file only: START
 BuildRequires:  diffstat
-
-# Find out Kerberos middle version to infer ABI changes in DAL driver
-# We cannot load DAL driver into KDC with wrong ABI.
-# This is also needed to support ipa-devel repository where krb5 1.11 is available for F18
-%global krb5_dal_version %{expand:%(echo "#include <kdb.h>"|cpp -dM|grep KRB5_KDB_DAL_MAJOR_VERSION|cut -d' ' -f3)}
+# RHEL spec file only: END
+BuildRequires:  python-lesscpy
+BuildRequires:  python-yubico
+BuildRequires:  python-backports-ssl_match_hostname
+# RHEL spec file only: DELETED: Disable DNSSEC support
 
 %description
 IPA is an integrated solution to provide centrally managed Identity (machine,
@@ -179,21 +250,11 @@ Group: System Environment/Base
 Requires: %{name}-python = %{version}-%{release}
 Requires: %{name}-client = %{version}-%{release}
 Requires: %{name}-admintools = %{version}-%{release}
-Requires: 389-ds-base >= 1.3.1.3
+Requires: 389-ds-base >= 1.3.3.1-10
 Requires: openldap-clients > 2.4.35-4
 Requires: nss >= 3.14.3-12.0
 Requires: nss-tools >= 3.14.3-12.0
-%if 0%{?krb5_dal_version} >= 4
-Requires: krb5-server >= 1.11.3-46
-%else
-%if 0%{krb5_dal_version} == 3
-# krb5 1.11 bumped DAL interface major version, a rebuild is needed
-Requires: krb5-server < 1.11
-Requires: krb5-server >= 1.10
-%else
-Requires: krb5-server >= 1.10
-%endif
-%endif
+Requires: krb5-server >= 1.11.5-5
 Requires: krb5-pkinit-openssl
 Requires: cyrus-sasl-gssapi%{?_isa}
 Requires: ntp
@@ -201,40 +262,58 @@ Requires: httpd >= 2.4.6-7
 Requires: mod_wsgi
 Requires: mod_auth_kerb >= 5.4-16
 Requires: mod_nss >= 1.0.8-26
-Requires: python-ldap
+Requires: python-ldap >= 2.4.15
 Requires: python-krbV
 Requires: acl
 Requires: python-pyasn1
 Requires: memcached
 Requires: python-memcached
+Requires: dbus-python
 Requires: systemd-units >= 38
 Requires(pre): systemd-units
 Requires(post): systemd-units
-Requires: selinux-policy >= 3.12.1-65
+Requires: selinux-policy >= %{selinux_policy_version}
 Requires(post): selinux-policy-base
-Requires: slapi-nis >= 0.47.7
-Requires: pki-ca >= 10.0.4
+Requires: slapi-nis >= 0.54-2
+Requires: pki-ca >= 10.1.2-5
+%if 0%{?rhel}
+Requires: subscription-manager
+%endif
 Requires(preun): python systemd-units
 Requires(postun): python systemd-units
-Requires: python-dns
+Requires: python-dns >= 1.11.1-2
 Requires: zip
-Requires: policycoreutils >= %{POLICYCOREUTILSVER}
+Requires: policycoreutils >= 2.1.14-37
 Requires: tar
-Requires(pre): certmonger >= 0.65
-Requires(pre): 389-ds-base >= 1.3.1.3
+Requires(pre): certmonger >= 0.75.14-2
+Requires(pre): 389-ds-base >= 1.3.3.1-10
+Requires: fontawesome-fonts
+Requires: open-sans-fonts
+# RHEL spec file only: DELETED: Disable DNSSEC support
+# RHEL spec file only: START
+Requires: redhat-access-plugin-ipa
+# RHEL spec file only: END
+
+Conflicts: %{alt_name}-server
+Obsoletes: %{alt_name}-server < %{version}
+
+# RHEL spec file only: DELETED
 
 # We have a soft-requires on bind. It is an optional part of
 # IPA but if it is configured we need a way to require versions
 # that work for us.
-Conflicts: bind-dyndb-ldap < 3.5
+Conflicts: bind-dyndb-ldap < 5.0
 Conflicts: bind < 9.8.2-0.4.rc2
+# RHEL spec file only: DELETED: Disable DNSSEC support
 
 # Versions of nss-pam-ldapd < 0.8.4 require a mapping from uniqueMember to
 # member.
 Conflicts: nss-pam-ldapd < 0.8.4
 
+# RHEL spec file only: START: Do not build tests
 # ipa-tests subpackage was moved to separate srpm
 Conflicts: ipa-tests < 3.3.3-9
+# RHEL spec file only: END: Do not build tests
 
 %description server
 IPA is an integrated solution to provide centrally managed Identity (machine,
@@ -251,7 +330,7 @@ Group: System Environment/Base
 Requires: %{name}-server = %version-%release
 Requires: m2crypto
 Requires: samba-python
-Requires: samba >= 4.0.5-1
+Requires: samba >= %{samba_version}
 Requires: samba-winbind
 Requires: libsss_idmap
 Requires: libsss_nss_idmap-python
@@ -264,6 +343,9 @@ Requires(post): python
 Requires(postun): %{_sbindir}/update-alternatives
 Requires(preun): %{_sbindir}/update-alternatives
 
+Conflicts: %{alt_name}-server-trust-ad
+Obsoletes: %{alt_name}-server-trust-ad < %{version}
+
 %description server-trust-ad
 Cross-realm trusts with Active Directory in IPA require working Samba 4
 installation. This package is provided for convenience to install all required
@@ -285,19 +367,23 @@ Requires: pam_krb5
 Requires: wget
 Requires: libcurl >= 7.21.7-2
 Requires: xmlrpc-c >= 1.27.4
-Requires: sssd >= 1.11.1
-Requires: certmonger >= 0.65
+Requires: sssd >= 1.12.2-38
+Requires: certmonger >= 0.75.14-2
 Requires: nss-tools
 Requires: bind-utils
 Requires: oddjob-mkhomedir
 Requires: python-krbV
-Requires: python-dns
+Requires: python-dns >= 1.11.1
 Requires: libsss_autofs
 Requires: autofs
 Requires: libnfsidmap
 Requires: nfs-utils
+Requires: python-backports-ssl_match_hostname
 Requires(post): policycoreutils
 
+Conflicts: %{alt_name}-client
+Obsoletes: %{alt_name}-client < %{version}
+
 %description client
 IPA is an integrated solution to provide centrally managed Identity (machine,
 user, virtual machines, groups, authentication credentials), Policy
@@ -306,7 +392,6 @@ logs, analysis thereof). If your network uses IPA for authentication,
 this package should be installed on every client machine.
 
 
-%if ! %{ONLY_CLIENT}
 %package admintools
 Summary: IPA administrative tools
 Group: System Environment/Base
@@ -315,26 +400,35 @@ Requires: %{name}-client = %{version}-%{release}
 Requires: python-krbV
 Requires: python-ldap
 
+Conflicts: %{alt_name}-admintools
+Obsoletes: %{alt_name}-admintools < %{version}
+
 %description admintools
 IPA is an integrated solution to provide centrally managed Identity (machine,
 user, virtual machines, groups, authentication credentials), Policy
 (configuration settings, access control information) and Audit (events,
 logs, analysis thereof). This package provides command-line tools for
 IPA administrators.
-%endif # ONLY_CLIENT
 
 %package python
 Summary: Python libraries used by IPA
 Group: System Environment/Libraries
-Requires: python-kerberos
+Requires: python-kerberos >= 1.1-15
 Requires: gnupg
 Requires: iproute
 Requires: keyutils
 Requires: pyOpenSSL
-Requires: python-nss
+Requires: python-nss >= 0.16
 Requires: python-lxml
 Requires: python-netaddr
 Requires: libipa_hbac-python
+Requires: python-qrcode-core >= 5.0.0
+Requires: python-pyasn1
+Requires: python-dateutil
+Requires: python-yubico
+
+Conflicts: %{alt_name}-python
+Obsoletes: %{alt_name}-python < %{version}
 
 %description python
 IPA is an integrated solution to provide centrally managed Identity (machine,
@@ -343,6 +437,9 @@ user, virtual machines, groups, authentication credentials), Policy
 logs, analysis thereof). If you are using IPA you need to install this
 package.
 
+# RHEL spec file only: DELETED: Do not build tests
+
+
 %prep
 # RHEL spec file only: START
 # Update timestamps on the files touched by a patch, to avoid non-equal
@@ -366,16 +463,34 @@ for p in %patches ; do
     %__patch -p1 -i $p
     UpdateTimestamps -p1 $p
 done
+
+# Red Hat's Identity Management branding
+cp %SOURCE1 install/ui/images/header-logo.png
+cp %SOURCE2 install/ui/images/login-screen-background.jpg
+cp %SOURCE3 install/ui/images/login-screen-logo.png
+cp %SOURCE4 install/ui/images/product-name.png
 # RHEL spec file only: END
 
 %build
+# UI compilation segfaulted on some arches when the stack was lower (#1040576)
+export JAVA_STACK_SIZE="8m"
+
 export CFLAGS="%{optflags} $CFLAGS"
 export LDFLAGS="%{__global_ldflags} $LDFLAGS"
-# use fedora18 platform which is based on fedora16 platform with systemd
-# support + fedora18 changes
-export SUPPORTED_PLATFORM=fedora18
+export SUPPORTED_PLATFORM=%{platform_module}
+
 # Force re-generate of platform support
-rm -f ipapython/services.py
+export IPA_VENDOR_VERSION_SUFFIX=-%{release}
+rm -f ipapython/version.py
+rm -f ipaplatform/services.py
+rm -f ipaplatform/tasks.py
+rm -f ipaplatform/paths.py
+# RHEL spec file only: START: Disable DNSSEC support
+rm -f ipapython/p11helper.py
+rm -f ipaserver/install/dnskeysyncinstance.py
+rm -f ipaserver/install/odsexporterinstance.py
+rm -f ipaserver/install/opendnssecinstance.py
+# RHEL spec file only: END: Disable DNSSEC support
 make version-update
 cd ipa-client; ../autogen.sh --prefix=%{_usr} --sysconfdir=%{_sysconfdir} --localstatedir=%{_localstatedir} --libdir=%{_libdir} --mandir=%{_mandir}; cd ..
 %if ! %{ONLY_CLIENT}
@@ -391,22 +506,24 @@ make IPA_VERSION_IS_GIT_SNAPSHOT=no %{?_smp_mflags} client
 
 %install
 rm -rf %{buildroot}
-# use fedora18 platform which is based on fedora16 platform with systemd
-# support + fedora18 changes
-export SUPPORTED_PLATFORM=fedora18
+export SUPPORTED_PLATFORM=%{platform_module}
 # Force re-generate of platform support
-rm -f ipapython/services.py
+export IPA_VENDOR_VERSION_SUFFIX=-%{release}
+rm -f ipapython/version.py
+rm -f ipaplatform/services.py
+rm -f ipaplatform/tasks.py
+rm -f ipaplatform/paths.py
+make version-update
 %if ! %{ONLY_CLIENT}
 make install DESTDIR=%{buildroot}
-# Start RHEL-7.0: Red Hat's Identity Management branding
-cp %SOURCE1 %{buildroot}%{_usr}/share/ipa/ui/images/ipa-banner.png
-# End RHEL-7.0
 %else
 make client-install DESTDIR=%{buildroot}
 %endif # ONLY_CLIENT
 %find_lang %{gettext_domain}
 
 
+mkdir -p %{buildroot}%{_usr}/share/ipa
+
 %if ! %{ONLY_CLIENT}
 # Remove .la files from libtool - we don't want to package
 # these files
@@ -423,6 +540,8 @@ rm %{buildroot}/%{plugin_dir}/libipa_sidgen.la
 rm %{buildroot}/%{plugin_dir}/libipa_sidgen_task.la
 rm %{buildroot}/%{plugin_dir}/libipa_extdom_extop.la
 rm %{buildroot}/%{plugin_dir}/libipa_range_check.la
+rm %{buildroot}/%{plugin_dir}/libipa_otp_counter.la
+rm %{buildroot}/%{plugin_dir}/libipa_otp_lasttoken.la
 rm %{buildroot}/%{_libdir}/krb5/plugins/kdb/ipadb.la
 rm %{buildroot}/%{_libdir}/samba/pdb/ipasam.la
 
@@ -442,8 +561,6 @@ ln -s ../../../..%{_sysconfdir}/ipa/html/unauthorized.html \
     %{buildroot}%{_usr}/share/ipa/html/unauthorized.html
 ln -s ../../../..%{_sysconfdir}/ipa/html/browserconfig.html \
     %{buildroot}%{_usr}/share/ipa/html/browserconfig.html
-ln -s ../../../..%{_sysconfdir}/ipa/html/ipa_error.css \
-    %{buildroot}%{_usr}/share/ipa/html/ipa_error.css
 
 # So we can own our Apache configuration
 mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d/
@@ -462,13 +579,18 @@ mkdir -p %{buildroot}%{_usr}/share/ipa/html/
 mkdir -p %{buildroot}%{_initrddir}
 mkdir %{buildroot}%{_sysconfdir}/sysconfig/
 install -m 644 init/ipa_memcached.conf %{buildroot}%{_sysconfdir}/sysconfig/ipa_memcached
+# RHEL spec file only: DELETED: Disable DNSSEC support
+
+# dnssec daemons
+mkdir -p %{buildroot}%{_libexecdir}/ipa/
+# RHEL spec file only: DELETED: Disable DNSSEC support
 
 # Web UI plugin dir
 mkdir -p %{buildroot}%{_usr}/share/ipa/ui/js/plugins
 
 # NOTE: systemd specific section
-mkdir -p %{buildroot}%{_prefix}/lib/tmpfiles.d
-install -m 0644 init/systemd/ipa.conf.tmpfiles %{buildroot}%{_prefix}/lib/tmpfiles.d/%{name}.conf
+mkdir -p %{buildroot}%{_tmpfilesdir}
+install -m 0644 init/systemd/ipa.conf.tmpfiles %{buildroot}%{_tmpfilesdir}/%{name}.conf
 # END
 
 mkdir -p %{buildroot}%{_localstatedir}/run/
@@ -483,22 +605,27 @@ mkdir -p %{buildroot}%{_unitdir}
 install -m 644 init/systemd/ipa.service %{buildroot}%{_unitdir}/ipa.service
 install -m 644 init/systemd/ipa_memcached.service %{buildroot}%{_unitdir}/ipa_memcached.service
 # END
+mkdir -p %{buildroot}/%{_localstatedir}/lib/ipa/backup
 %endif # ONLY_CLIENT
 
 mkdir -p %{buildroot}%{_sysconfdir}/ipa/
 /bin/touch %{buildroot}%{_sysconfdir}/ipa/default.conf
 /bin/touch %{buildroot}%{_sysconfdir}/ipa/ca.crt
+mkdir -p %{buildroot}%{_sysconfdir}/ipa/dnssec
+mkdir -p %{buildroot}%{_sysconfdir}/ipa/nssdb
 mkdir -p %{buildroot}/%{_localstatedir}/lib/ipa-client/sysrestore
-
-%if ! %{ONLY_CLIENT}
 mkdir -p %{buildroot}%{_sysconfdir}/bash_completion.d
 install -pm 644 contrib/completion/ipa.bash_completion %{buildroot}%{_sysconfdir}/bash_completion.d/ipa
+
+%if ! %{ONLY_CLIENT}
 mkdir -p %{buildroot}%{_sysconfdir}/cron.d
 
 (cd %{buildroot}/%{python_sitelib}/ipaserver && find . -type f  | \
     grep -v dcerpc | grep -v adtrustinstance | \
     sed -e 's,\.py.*$,.*,g' | sort -u | \
     sed -e 's,\./,%%{python_sitelib}/ipaserver/,g' ) >server-python.list
+
+# RHEL spec file only: DELETED: Do not build tests
 %endif # ONLY_CLIENT
 
 %clean
@@ -521,10 +648,13 @@ fi
 
 # Restart IPA processes. This must be also run in postrans so that plugins
 # and software is in consistent state
-python -c "import sys; from ipaserver.install import installutils; sys.exit(0 if installutils.is_ipa_configured() else 1);" > /dev/null 2>&1
+python2 -c "import sys; from ipaserver.install import installutils; sys.exit(0 if installutils.is_ipa_configured() else 1);" > /dev/null 2>&1
 # NOTE: systemd specific section
 if [  $? -eq 0 ]; then
-    /bin/systemctl try-restart ipa.service >/dev/null 2>&1 || :
+    /bin/systemctl is-enabled ipa.service >/dev/null 2>&1
+    if [  $? -eq 0 ]; then
+        /bin/systemctl restart ipa.service >/dev/null 2>&1 || :
+    fi
 fi
 # END
 
@@ -557,7 +687,7 @@ fi
         winbind_krb5_locator.so /dev/null 90
 
 %posttrans server-trust-ad
-python -c "import sys; from ipaserver.install import installutils; sys.exit(0 if installutils.is_ipa_configured() else 1);" > /dev/null 2>&1
+python2 -c "import sys; from ipaserver.install import installutils; sys.exit(0 if installutils.is_ipa_configured() else 1);" > /dev/null 2>&1
 if [  $? -eq 0 ]; then
 # NOTE: systemd specific section
     /bin/systemctl try-restart httpd.service >/dev/null 2>&1 || :
@@ -568,6 +698,7 @@ fi
 if [ $1 -eq 0 ]; then
     %{_sbindir}/update-alternatives --remove winbind_krb5_locator.so /dev/null
 fi
+
 %endif # ONLY_CLIENT
 
 %post client
@@ -584,9 +715,30 @@ if [ $1 -gt 1 ] ; then
             /sbin/restorecon /etc/krb5.conf
         fi
     fi
+
+    if [ -f '/etc/sysconfig/ntpd' -a $restore -ge 2 ]; then
+        if grep -E -q 'OPTIONS=.*-u ntp:ntp' /etc/sysconfig/ntpd 2>/dev/null; then
+            sed -r '/OPTIONS=/ { s/\s+-u ntp:ntp\s+/ /; s/\s*-u ntp:ntp\s*// }' /etc/sysconfig/ntpd >/etc/sysconfig/ntpd.ipanew
+            mv /etc/sysconfig/ntpd.ipanew /etc/sysconfig/ntpd
+            /sbin/restorecon /etc/sysconfig/ntpd
+
+            /bin/systemctl condrestart ntpd.service 2>&1 || :
+        fi
+    fi
+
+    if [ ! -f '/etc/ipa/nssdb/cert8.db' -a $restore -ge 2 ]; then
+        python2 -c 'from ipapython.certdb import create_ipa_nssdb; create_ipa_nssdb()' >/dev/null 2>&1
+        tempfile=$(mktemp)
+        if certutil -L -d /etc/pki/nssdb -n 'IPA CA' -a >"$tempfile" 2>/var/log/ipaupgrade.log; then
+            certutil -A -d /etc/ipa/nssdb -n 'IPA CA' -t CT,C,C -a -i "$tempfile" >/var/log/ipaupgrade.log 2>&1
+        elif certutil -L -d /etc/pki/nssdb -n 'External CA cert' -a >"$tempfile" 2>/var/log/ipaupgrade.log; then
+            certutil -A -d /etc/ipa/nssdb -n 'External CA cert' -t C,, -a -i "$tempfile" >/var/log/ipaupgrade.log 2>&1
+        fi
+        rm -f "$tempfile"
+    fi
 fi
 
-%triggerin -n ipa-client -- openssh-server
+%triggerin -n %{name}-client -- openssh-server
 # Has the client been configured?
 restore=0
 test -f '/var/lib/ipa-client/sysrestore/sysrestore.index' && restore=$(wc -l '/var/lib/ipa-client/sysrestore/sysrestore.index' | awk '{print $1}')
@@ -626,6 +778,8 @@ fi
 %files server -f server-python.list
 %defattr(-,root,root,-)
 %doc COPYING README Contributors.txt
+%{_sbindir}/ipa-backup
+%{_sbindir}/ipa-restore
 %{_sbindir}/ipa-ca-install
 %{_sbindir}/ipa-dns-install
 %{_sbindir}/ipa-server-install
@@ -636,24 +790,31 @@ fi
 %{_sbindir}/ipa-csreplica-manage
 %{_sbindir}/ipa-server-certinstall
 %{_sbindir}/ipa-ldap-updater
+%{_sbindir}/ipa-otptoken-import
 %{_sbindir}/ipa-compat-manage
 %{_sbindir}/ipa-nis-manage
 %{_sbindir}/ipa-managed-entries
 %{_sbindir}/ipactl
 %{_sbindir}/ipa-upgradeconfig
 %{_sbindir}/ipa-advise
-%{_libexecdir}/certmonger/dogtag-ipa-retrieve-agent-submit
+%{_sbindir}/ipa-cacert-manage
+%{_libexecdir}/certmonger/dogtag-ipa-ca-renew-agent-submit
+%{_libexecdir}/certmonger/ipa-server-guard
 %{_libexecdir}/ipa-otpd
+%dir %{_libexecdir}/ipa
+# RHEL spec file only: DELETED: Disable DNSSEC support
 %config(noreplace) %{_sysconfdir}/sysconfig/ipa_memcached
+# RHEL spec file only: DELETED: Disable DNSSEC support
 %dir %attr(0700,apache,apache) %{_localstatedir}/run/ipa_memcached/
 %dir %attr(0700,root,root) %{_localstatedir}/run/ipa/
 # NOTE: systemd specific section
-%{_prefix}/lib/tmpfiles.d/%{name}.conf
+%{_tmpfilesdir}/%{name}.conf
 %attr(644,root,root) %{_unitdir}/ipa.service
 %attr(644,root,root) %{_unitdir}/ipa_memcached.service
-# END
 %attr(644,root,root) %{_unitdir}/ipa-otpd.socket
 %attr(644,root,root) %{_unitdir}/ipa-otpd@.service
+# RHEL spec file only: DELETED: Disable DNSSEC support
+# END
 %dir %{python_sitelib}/ipaserver
 %dir %{python_sitelib}/ipaserver/install
 %dir %{python_sitelib}/ipaserver/install/plugins
@@ -688,7 +849,6 @@ fi
 %{_usr}/share/ipa/html/ssbrowser.html
 %{_usr}/share/ipa/html/browserconfig.html
 %{_usr}/share/ipa/html/unauthorized.html
-%{_usr}/share/ipa/html/ipa_error.css
 %dir %{_usr}/share/ipa/migration
 %{_usr}/share/ipa/migration/error.html
 %{_usr}/share/ipa/migration/index.html
@@ -696,16 +856,13 @@ fi
 %{_usr}/share/ipa/migration/migration.py*
 %dir %{_usr}/share/ipa/ui
 %{_usr}/share/ipa/ui/index.html
-%{_usr}/share/ipa/ui/login.html
-%{_usr}/share/ipa/ui/logout.html
 %{_usr}/share/ipa/ui/reset_password.html
+%{_usr}/share/ipa/ui/sync_otp.html
 %{_usr}/share/ipa/ui/*.ico
 %{_usr}/share/ipa/ui/*.css
 %{_usr}/share/ipa/ui/*.js
-%{_usr}/share/ipa/ui/*.eot
-%{_usr}/share/ipa/ui/*.svg
-%{_usr}/share/ipa/ui/*.ttf
-%{_usr}/share/ipa/ui/*.woff
+%dir %{_usr}/share/ipa/ui/css
+%{_usr}/share/ipa/ui/css/*.css
 %dir %{_usr}/share/ipa/ui/js
 %dir %{_usr}/share/ipa/ui/js/dojo
 %{_usr}/share/ipa/ui/js/dojo/dojo.js
@@ -713,10 +870,11 @@ fi
 %{_usr}/share/ipa/ui/js/libs/*.js
 %dir %{_usr}/share/ipa/ui/js/freeipa
 %{_usr}/share/ipa/ui/js/freeipa/app.js
+%{_usr}/share/ipa/ui/js/freeipa/core.js
 %dir %{_usr}/share/ipa/ui/js/plugins
 %dir %{_usr}/share/ipa/ui/images
+%{_usr}/share/ipa/ui/images/*.jpg
 %{_usr}/share/ipa/ui/images/*.png
-%{_usr}/share/ipa/ui/images/*.gif
 %dir %{_usr}/share/ipa/wsgi
 %{_usr}/share/ipa/wsgi/plugins.py*
 %dir %{_sysconfdir}/ipa
@@ -724,13 +882,11 @@ fi
 %config(noreplace) %{_sysconfdir}/ipa/html/ffconfig.js
 %config(noreplace) %{_sysconfdir}/ipa/html/ffconfig_page.js
 %config(noreplace) %{_sysconfdir}/ipa/html/ssbrowser.html
-%config(noreplace) %{_sysconfdir}/ipa/html/ipa_error.css
 %config(noreplace) %{_sysconfdir}/ipa/html/unauthorized.html
 %config(noreplace) %{_sysconfdir}/ipa/html/browserconfig.html
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa.conf
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-pki-proxy.conf
-%{_usr}/share/ipa/ca_renewal
 %{_usr}/share/ipa/ipa.conf
 %{_usr}/share/ipa/ipa-rewrite.conf
 %{_usr}/share/ipa/ipa-pki-proxy.conf
@@ -754,11 +910,15 @@ fi
 %attr(755,root,root) %{plugin_dir}/libipa_cldap.so
 %attr(755,root,root) %{plugin_dir}/libipa_dns.so
 %attr(755,root,root) %{plugin_dir}/libipa_range_check.so
+%attr(755,root,root) %{plugin_dir}/libipa_otp_counter.so
+%attr(755,root,root) %{plugin_dir}/libipa_otp_lasttoken.so
 %dir %{_localstatedir}/lib/ipa
+%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/backup
 %attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore
 %attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysupgrade
 %attr(755,root,root) %dir %{_localstatedir}/lib/ipa/pki-ca
 %ghost %{_localstatedir}/lib/ipa/pki-ca/publish
+%ghost %{_localstatedir}/named/dyndb-ldap/ipa
 %attr(755,root,root) %{_libdir}/krb5/plugins/kdb/ipadb.so
 %{_mandir}/man1/ipa-replica-conncheck.1.gz
 %{_mandir}/man1/ipa-replica-install.1.gz
@@ -775,7 +935,11 @@ fi
 %{_mandir}/man1/ipa-ldap-updater.1.gz
 %{_mandir}/man8/ipactl.8.gz
 %{_mandir}/man8/ipa-upgradeconfig.8.gz
+%{_mandir}/man1/ipa-backup.1.gz
+%{_mandir}/man1/ipa-restore.1.gz
 %{_mandir}/man1/ipa-advise.1.gz
+%{_mandir}/man1/ipa-otptoken-import.1.gz
+%{_mandir}/man1/ipa-cacert-manage.1.gz
 
 %files server-trust-ad
 %{_sbindir}/ipa-adtrust-install
@@ -796,78 +960,236 @@ fi
 %doc COPYING README Contributors.txt
 %{_sbindir}/ipa-client-install
 %{_sbindir}/ipa-client-automount
+%{_sbindir}/ipa-certupdate
 %{_sbindir}/ipa-getkeytab
 %{_sbindir}/ipa-rmkeytab
 %{_sbindir}/ipa-join
 %dir %{_usr}/share/ipa
-%dir %{_usr}/share/ipa/ipaclient
 %dir %{_localstatedir}/lib/ipa-client
 %dir %{_localstatedir}/lib/ipa-client/sysrestore
-%{_usr}/share/ipa/ipaclient/ipa.cfg
-%{_usr}/share/ipa/ipaclient/ipa.js
 %dir %{python_sitelib}/ipaclient
 %{python_sitelib}/ipaclient/*.py*
 %{_mandir}/man1/ipa-getkeytab.1.gz
 %{_mandir}/man1/ipa-rmkeytab.1.gz
 %{_mandir}/man1/ipa-client-install.1.gz
 %{_mandir}/man1/ipa-client-automount.1.gz
+%{_mandir}/man1/ipa-certupdate.1.gz
 %{_mandir}/man1/ipa-join.1.gz
 %{_mandir}/man5/default.conf.5.gz
 
-%if ! %{ONLY_CLIENT}
 %files admintools
 %defattr(-,root,root,-)
 %doc COPYING README Contributors.txt
 %{_bindir}/ipa
 %config %{_sysconfdir}/bash_completion.d
 %{_mandir}/man1/ipa.1.gz
-%endif # ONLY_CLIENT
 
 %files python -f %{gettext_domain}.lang
 %defattr(-,root,root,-)
 %doc COPYING README Contributors.txt
 %dir %{python_sitelib}/ipapython
-%dir %{python_sitelib}/ipapython/platform
-%dir %{python_sitelib}/ipapython/platform/base
-%dir %{python_sitelib}/ipapython/platform/fedora16
-%dir %{python_sitelib}/ipapython/platform/fedora18
-%dir %{python_sitelib}/ipapython/platform/redhat
 %{python_sitelib}/ipapython/*.py*
-%{python_sitelib}/ipapython/platform/*.py*
-%{python_sitelib}/ipapython/platform/base/*.py*
-%{python_sitelib}/ipapython/platform/fedora16/*.py*
-%{python_sitelib}/ipapython/platform/fedora18/*.py*
-%{python_sitelib}/ipapython/platform/redhat/*.py*
+# RHEL spec file only: DELETED: Disable DNSSEC support
 %dir %{python_sitelib}/ipalib
 %{python_sitelib}/ipalib/*
+%dir %{python_sitelib}/ipaplatform
+%{python_sitelib}/ipaplatform/*
 %attr(0644,root,root) %{python_sitearch}/default_encoding_utf8.so
+# RHEL spec file only: DELETED: Disable DNSSEC support
 %{python_sitelib}/ipapython-*.egg-info
 %{python_sitelib}/freeipa-*.egg-info
+%{python_sitelib}/ipaplatform-*.egg-info
 %{python_sitearch}/python_default_encoding-*.egg-info
+# RHEL spec file only: DELETED: Disable DNSSEC support
 %dir %attr(0755,root,root) %{_sysconfdir}/ipa/
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt
+%dir %attr(0755,root,root) %{_sysconfdir}/ipa/nssdb
+%dir %attr(0755,root,root) %{_sysconfdir}/ipa/dnssec
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/cert8.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/key3.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/secmod.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/pwdfile.txt
+%ghost %config(noreplace) %{_sysconfdir}/pki/ca-trust/source/ipa.p11-kit
 
-%changelog
-* Tue Dec  2 2014 Johnny Hughes <johnny@centos.org> 3.3.3-28.el7_0.centos.3
-- remove Subscription Manager requirement
-
-* Mon Nov 10 2014 CentOS Sources <bugs@centos.org> - 3.3.3-28.el7.centos.3
-- Roll in CentOS Branding
+# RHEL spec file only: DELETED: Do not build tests
 
-* Fri Sep 19 2014 Jan Cholasta <jcholast@redhat.com> - 3.3.3-28.3
-- Add one missing patch for #1144031
-
-* Fri Sep 19 2014 Jan Cholasta <jcholast@redhat.com> - 3.3.3-28.2
-- Implement a fallback for situation where no closest server available during
-  trust setup (#1143779)
-- trust-add should not be run with DCs without PDC role (#1144030)
-- Improve handling of forest trust domains when establishing a cross-forest
-  trust (#1144031)
-
-* Thu Aug 14 2014 Martin Kosek <mkosek@redhat.com> - 3.3.3-28.1
+%changelog
+* Thu Jan 29 2015 Martin Kosek <mkosek@redhat.com> 4.1.0-18
+- Fix ipa-pwd-extop global configuration caching (#1187342)
+- group-detach does not add correct objectclasses (#1187540)
+
+* Tue Jan 27 2015 Jan Cholasta <jcholast@redhat.com> - 4.1.0-17
+- Wrong directories created on full restore (#1186398)
+- ipa-restore crashes if replica is unreachable (#1186396)
+- idoverrideuser-add option --sshpubkey does not work (#1185410)
+
+* Wed Jan 21 2015 Jan Cholasta <jcholast@redhat.com> - 4.1.0-16
+- PassSync does not sync passwords due to missing ACIs (#1181093)
+- ipa-replica-manage list does not list synced domain (#1181010)
+- Do not assume certmonger is running in httpinstance (#1181767)
+- ipa-replica-manage disconnect fails without password (#1183279)
+- Put LDIF files to their original location in ipa-restore (#1175277)
+- DUA profile not available anonymously (#1184149)
+- IPA replica missing data after master upgraded (#1176995)
+
+* Wed Jan 14 2015 Jan Cholasta <jcholast@redhat.com> - 4.1.0-15
+- Re-add accidentally removed patches for #1170695 and #1164896
+
+* Wed Jan 14 2015 Jan Cholasta <jcholast@redhat.com> - 4.1.0-14
+- IPA Replicate creation fails with error "Update failed! Status: [10 Total
+  update abortedLDAP error: Referral]" (#1166265)
+- running ipa-server-install --setup-dns results in a crash (#1072502)
+- DNS zones are not migrated into forward zones if 4.0+ replica is added
+  (#1175384)
+- gid is overridden by uid in default trust view (#1168904)
+- When migrating warn user if compat is enabled (#1177133)
+- Clean up debug log for trust-add (#1168376)
+- No error message thrown on restore(full kind) on replica from full backup
+  taken on master (#1175287)
+- ipa-restore proceed even IPA not configured (#1175326)
+- Data replication not working as expected after data restore from full backup
+  (#1175277)
+- IPA externally signed CA cert expiration warning missing from log (#1178128)
+- ipa-upgradeconfig fails in CA-less installs (#1181767)
+- IPA certs fail to autorenew simultaneouly (#1173207)
+- More validation required on ipa-restore's options (#1176034)
+
+* Wed Dec 17 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-13
+- Expand the token auth/sync windows (#919228)
+- Access is not rejected for disabled domain (#1172598)
+- krb5kdc crash in ldap_pvt_search (#1170695)
+- RHEL7.1 IPA server httpd avc denials after upgrade (#1164896)
+
+* Wed Dec 10 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-12
+- RHEL7.1 ipa-cacert-manage renewed certificate from MS ADCS not compatible
+  (#1169591)
+- CLI doesn't show SSHFP records with SHA256 added via nsupdate (regression)
+  (#1172578)
+
+* Tue Dec  9 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-11
+- Throw zonemgr error message before installation proceeds (#1163849)
+- Winsync: Setup is broken due to incorrect import of certificate (#1169867)
+- Enable last token deletion when password auth type is configured (#919228)
+- ipa-otp-lasttoken loads all user's tokens on every mod/del (#1166641)
+- add --hosts and --hostgroup options to allow/retrieve keytab methods
+  (#1007367)
+- Extend host-show to add the view attribute in set of default attributes
+  (#1168916)
+- Prefer TCP connections to UDP in krb5 clients (#919228)
+- [WebUI] Not able to unprovisioning service in IPA 4.1 (#1168214)
+- webui: increase notification duration (#1171089)
+- RHEL7.1 ipa automatic CA cert renewal stuck in submitting state (#1166931)
+- RHEL7.1 ipa-cacert-manage cannot change external to self-signed ca cert
+  (#1170003)
+- Improve validation of --instance and --backend options in ipa-restore
+  (#951581)
+- RHEL7.1 ipa replica unable to replicate to rhel6 master (#1167964)
+- Disable TLS 1.2 in nss.conf until mod_nss supports it (#1156466)
+
+* Wed Nov 26 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-10
+- Use NSS protocol range API to set available TLS protocols (#1156466)
+
+* Tue Nov 25 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-9
+- schema update on RHEL-6.6 using latest copy-schema-to-ca.py from RHEL-7.1
+  build fails (#1167196)
+- Investigate & fix Coverity defects in IPA DS/KDC plugins (#1160756)
+- "ipa trust-add ... " cmd says : (Trust status: Established and verified)
+  while in the logs we see "WERR_ACCESS_DENIED" during verification step.
+  (#1144121)
+- POODLE: force using safe ciphers (non-SSLv3) in IPA client and server
+  (#1156466)
+- Add support/hooks for a one-time password system like SecureID in IPA
+  (#919228)
+- Tracebacks with latest build for --zonemgr cli option (#1167270)
+- ID Views: Support migration from the sync solution to the trust solution
+  (#891984)
+
+* Mon Nov 24 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-8
+- Improve otptoken help messages (#919228)
+- Ensure users exist when assigning tokens to them (#919228)
+- Enable QR code display by default in otptoken-add (#919228)
+- Show warning instead of error if CA did not start (#1158410)
+- CVE-2014-7850 freeipa: XSS flaw can be used to escalate privileges (#1165774)
+- Traceback when adding zone with long name (#1164859)
+- Backup & Restore mechanism (#951581)
+- ignoring user attributes in migrate-ds does not work if uppercase characters
+  are returned by ldap (#1159816)
+- Allow ipa-getkeytab to optionally fetch existing keys (#1007367)
+- Failure when installing on dual stacked system with external ca (#1128380)
+- ipa-server should keep backup of CS.cfg (#1059135)
+- Tracebacks with latest build for --zonemgr cli option (#1167270)
+- webui: use domain name instead of domain SID in idrange adder dialog
+  (#891984)
+- webui: normalize idview tab labels (#891984)
+
+* Wed Nov 19 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-7
+- ipa-csreplica-manage connect fails (#1157735)
+- error message which is not understandable when IDNA2003 characters are
+  present in --zonemgr (#1163849)
+- Fix warning message should not contain CLI commands (#1114013)
+- Renewing the CA signing certificate does not extend its validity period end
+  (#1163498)
+- RHEL7.1 ipa-server-install --uninstall Could not set SELinux booleans for
+  httpd (#1159330)
+
+* Thu Nov 13 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-6
+- Fix: DNS installer adds invalid zonemgr email (#1056202)
+- ipaplatform: Use the dirsrv service, not target (#951581)
+- Fix: DNS policy upgrade raises asertion error (#1161128)
+- Fix upgrade referint plugin (#1161128)
+- Upgrade: fix trusts objectclass violationi (#1161128)
+- group-add doesn't accept gid parameter (#1149124)
+
+* Tue Nov 11 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-5
+- Update slapi-nis dependency to pull 0.54-2 (#891984)
+- ipa-restore: Don't crash if AD trust is not installed (#951581)
+- Prohibit setting --rid-base for ranges of ipa-trust-ad-posix type (#1138791)
+- Trust setting not restored for CA cert with ipa-restore command (#1159011)
+- ipa-server-install fails when restarting named (#1162340)
+
+* Thu Nov 06 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-4
+- Update Requires on pki-ca to 10.1.2-4 (#1129558)
+- build: increase java stack size for all arches
+- Add ipaSshPubkey and gidNumber to the ACI to read ID user overrides (#891984)
+- Fix dns zonemgr validation regression (#1056202)
+- Handle profile changes in dogtag-ipa-ca-renew-agent (#886645)
+- Do not wait for new CA certificate to appear in LDAP in ipa-certupdate
+  (#886645)
+- Add bind-dyndb-ldap working dir to IPA specfile
+- Fail if certmonger can't see new CA certificate in LDAP in ipa-cacert-manage
+  (#886645)
+- Investigate & fix Coverity defects in IPA DS/KDC plugins (#1160756)
+- Deadlock in schema compat plugin (#1161131)
+- ipactl stop should stop dirsrv last (#1161129)
+- Upgrade 3.3.5 to 4.1 failed (#1161128)
+- CVE-2014-7828 freeipa: password not required when OTP in use (#1160877)
+
+* Wed Oct 22 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-3
+- Do not check if port 8443 is available in step 2 of external CA install
+  (#1129481)
+
+* Wed Oct 22 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-2
+- Update Requires on selinux-policy to 3.13.1-4
+
+* Tue Oct 21 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-1
+- Update to upstream 4.1.0 (#1109726)
+
+* Mon Sep 29 2014 Jan Cholasta <jcholast@redhat.com> - 4.1.0-0.1.alpha1
+- Update to upstream 4.1.0 Alpha 1 (#1109726)
+
+* Fri Sep 26 2014 Petr Vobornik <pvoborni@redhat.com> - 4.0.3-3
+- Add redhat-access-plugin-ipa dependency
+
+* Thu Sep 25 2014 Jan Cholasta <jcholast@redhat.com> - 4.0.3-2
+- Re-enable otptoken_yubikey plugin
+
+* Mon Sep 15 2014 Jan Cholasta <jcholast@redhat.com> - 4.0.3-1
+- Update to upstream 4.0.3 (#1109726)
+
+* Thu Aug 14 2014 Martin Kosek <mkosek@redhat.com> - 3.3.3-29
 - Server installation fails using external signed certificates with
-  "IndexError: list index out of range" (#1130031)
+  "IndexError: list index out of range" (#1111320)
 - Add rhino to BuildRequires to fix Web UI build error
 
 * Tue Apr  1 2014 Martin Kosek <mkosek@redhat.com> - 3.3.3-28
@@ -1304,7 +1626,7 @@ fi
 - Rebuilt for glibc bug#747377
 
 * Wed Oct 19 2011 Alexander Bokovoy <abokovoy@redhat.com> - 2.1.3-4
-- clean up spec 
+- clean up spec
 - Depend on sssd >= 1.6.2 for better user experience
 
 * Tue Oct 18 2011 Alexander Bokovoy <abokovoy@redhat.com> - 2.1.3-3