summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorGoliathLabs2020-06-22 14:11:40 +0200
committerGoliathLabs2020-06-22 14:11:40 +0200
commitf440bcd34523ad4b2f8a1cd7d3d70c6eb14f9b6c (patch)
treeec3f8bd39172114b8a37e7dafc5aa5b9c6e48e12
parent3efd20d51255057cecd2d5b8852d923f0ad1d3a8 (diff)
downloadaur-f440bcd34523ad4b2f8a1cd7d3d70c6eb14f9b6c.tar.gz
Updated: patches
-rw-r--r--.SRCINFO66
-rw-r--r--0001-Add-missing-xsl-file-to-Makefile.am.patch27
-rw-r--r--0001-Find-NetBIOS-name-in-keytab-while-leaving.patch168
-rw-r--r--0001-Fix-issues-found-by-Coverity.patch42
-rw-r--r--0001-Fix-man-page-reference-in-systemd-service-file.patch24
-rw-r--r--0001-IPA-do-not-call-sssd-enable-logins.patch62
-rw-r--r--0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch112
-rw-r--r--0001-LDAP-don-t-close-LDAP-socket-twice.patch41
-rw-r--r--0001-Remove-support-for-deprecated-gtester-format.patch39
-rw-r--r--0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch47
-rw-r--r--0001-Use-current-idmap-options-for-smb.conf.patch185
-rw-r--r--0001-doc-make-sure-cross-reference-ids-are-predictable.patch1500
-rw-r--r--0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch96
-rw-r--r--0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch98
-rw-r--r--0001-switch-to-authselect.patch36
-rw-r--r--0001-tests-ignore-order-in-test_update_domain.patch82
-rw-r--r--0001-tests-run-tests-with-python3.patch374
-rw-r--r--0002-Change-qualified-names-default-for-IPA.patch113
-rw-r--r--0002-configure-do-not-inherit-DISTRO-from-the-environment.patch32
-rw-r--r--0002-tools-remove-duplicated-va_start.patch25
-rw-r--r--0003-discover-try-to-get-domain-name-from-hostname.patch76
-rw-r--r--0003-doc-extend-user-principal-section.patch75
-rw-r--r--0003-service-remove-dead-code.patch33
-rw-r--r--0004-doc-fix-discover-name-only.patch26
-rw-r--r--0004-service-check-return-value-of-fcntl.patch36
-rw-r--r--0005-doc-add-see-also-to-man-pages.patch46
-rw-r--r--0005-service-avoid-dereference-of-a-null-pointer.patch39
-rw-r--r--0006-doc-extend-description-of-config-handling.patch104
-rw-r--r--0006-service-avoid-dereferencing-a-NULL-pointer.patch24
-rw-r--r--0007-service-use-kerberos-method-secrets-and-keytab.patch30
-rw-r--r--PKGBUILD82
-rw-r--r--computer-ou.patch894
-rw-r--r--duplicate-test-path.patch26
-rw-r--r--install-diagnostic.patch29
34 files changed, 4682 insertions, 7 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 744a3dd0627d..7811611b537d 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = realmd
pkgdesc = DBus service for joining hosts to Active Directory and FreeIPA realms
pkgver = 0.16.3
- pkgrel = 1
+ pkgrel = 2
url = https://freedesktop.org/software/realmd/
arch = i686
arch = x86_64
@@ -21,9 +21,73 @@ pkgbase = realmd
optdepends = samba: traditional Active Directory client
source = https://www.freedesktop.org/software/realmd/releases/realmd-0.16.3.tar.gz
source = https://www.freedesktop.org/software/realmd/releases/realmd-0.16.3.tar.gz.sig
+ source = 0001-Add-missing-xsl-file-to-Makefile.am.patch
+ source = 0001-doc-make-sure-cross-reference-ids-are-predictable.patch
+ source = 0001-Find-NetBIOS-name-in-keytab-while-leaving.patch
+ source = 0001-Fix-issues-found-by-Coverity.patch
+ source = 0001-Fix-man-page-reference-in-systemd-service-file.patch
+ source = 0001-IPA-do-not-call-sssd-enable-logins.patch
+ source = 0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch
+ source = 0001-LDAP-don-t-close-LDAP-socket-twice.patch
+ source = 0001-Remove-support-for-deprecated-gtester-format.patch
+ source = 0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch
+ source = 0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch
+ source = 0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch
+ source = 0001-switch-to-authselect.patch
+ source = 0001-tests-ignore-order-in-test_update_domain.patch
+ source = 0001-tests-run-tests-with-python3.patch
+ source = 0001-Use-current-idmap-options-for-smb.conf.patch
+ source = 0002-Change-qualified-names-default-for-IPA.patch
+ source = 0002-configure-do-not-inherit-DISTRO-from-the-environment.patch
+ source = 0002-tools-remove-duplicated-va_start.patch
+ source = 0003-discover-try-to-get-domain-name-from-hostname.patch
+ source = 0003-doc-extend-user-principal-section.patch
+ source = 0003-service-remove-dead-code.patch
+ source = 0004-doc-fix-discover-name-only.patch
+ source = 0004-service-check-return-value-of-fcntl.patch
+ source = 0005-doc-add-see-also-to-man-pages.patch
+ source = 0005-service-avoid-dereference-of-a-null-pointer.patch
+ source = 0006-doc-extend-description-of-config-handling.patch
+ source = 0006-service-avoid-dereferencing-a-NULL-pointer.patch
+ source = 0007-service-use-kerberos-method-secrets-and-keytab.patch
+ source = computer-ou.patch
+ source = duplicate-test-path.patch
+ source = install-diagnostic.patch
validpgpkeys = C0F67099B808FB063E2C81117BFB1108D92765AF
sha256sums = d8943f66a2a666fee8be026d82a66904c0a5125aab7ef74504456ce269687dda
sha256sums = SKIP
+ sha256sums = 6db7704e9342efd801ec24949f1002a8e26ac67c4f04638ca51977940ef3ac1d
+ sha256sums = ea5a2b311f76ebfea0c88c2cf333c007ea5db32316935bbd5dd6883450edd5a3
+ sha256sums = faffd409b53b46c67d4f776e252e49025a63f9963796e12ef6f487d416310958
+ sha256sums = 262764b9acbe2c84348d8f9a7b759bd08d10c04ef779c4f390c3f6650ef6d96a
+ sha256sums = cb376d3b6e90be4aa84a1d42d4d395f5a8f0aedfbf719277e549f08928e3a985
+ sha256sums = 2c79e27e504d24b22a06bce567a3aa96348e1bb0682db4e042c96165f799c500
+ sha256sums = a56748ad07b75e346dccedead2ec50053bfe3c3084f9c804b8fae6d961977236
+ sha256sums = 65f4b0d4d8f51e55e9adc5b8d2896a3abf159f311fc9d3a99ae2df906181e04d
+ sha256sums = 440ae6ac9d7b4e08440dc1382cfc243e28d69dfcf010f8335e3699c40eda9d63
+ sha256sums = f25dd08914fb493d8b8e6ff5bd44d8398d0498116a874effb314f2cd6e26446d
+ sha256sums = 6b3a36fdb36655940194ec0b53dcec7e97a4a79a0427863c8a905ad67c9c1714
+ sha256sums = 512def4faeaa0cd283161fbb05f2bba16bd2d2373d681a99248e78ede958b0fe
+ sha256sums = 47d7a73329a7dbb4754ab7bd3ed436799cbd21b4f555a0a0ab50c27944817335
+ sha256sums = f408dc7c2263b01e97b66ec068fc48ba5597a3d13e55a60d26008ae309a7787d
+ sha256sums = f3a584270e3e0d6a76c9aeb1dbf078c864b78d948c3277d6899b0b40f8a58030
+ sha256sums = 8346081c5a8c1efbd5c33890e530fdd84906d394737a1a2cd5a8e2f5fb4f64b6
+ sha256sums = d93b5ba71204cbcb70bab02bf990068d04d4be1888f23c251e2c512c8bb0caeb
+ sha256sums = 86640fbf9a7f5d7606529584902dcee96fd13cb50c673d785ec04ab525364119
+ sha256sums = 1daa4159e6fe20131111112b6127ca823b2355a2ef7895840959168af00a5483
+ sha256sums = e4922a6c16c7fd41a2903a5857876c679fd9c257569fe35a4b08ffaabfd016e7
+ sha256sums = eeca4747df151ab624feeefdeda4274da3703681074f21789a69a2eb73da9ca4
+ sha256sums = d594af102566775b4bb0cf59554c69c20721d7db935ac69a3fbc86f28f1226bc
+ sha256sums = 6fc569eb9641503352fb5f19cb2c5dd16a0e8c888c7e4ea652b55a8e9e69ff6e
+ sha256sums = a962c7b5f3cf2dba39d16195ad7bb1a9d2db9d2292d74d6e65879c220791b871
+ sha256sums = 3ef0438e83ec4cefba482435d8c22d69bbb8e93b24032a83ad139481ecbda817
+ sha256sums = 76e511fe1033f19c8499b4edcc3410eede375ceff968f4ac08cd6333c7e33c2a
+ sha256sums = 77bad53ed4f36ae51f3c81b0195fb898fa6c9f79a377550f51551423c12dcff0
+ sha256sums = 682a5f7af3e4bdc0bfa5ed2f7ad654e9d311666995520ae2997898edb9264bdc
+ sha256sums = 950d252020635b4415551fcf9fcacc06ade8497a639b25661b138341b327ea24
+ sha256sums = 5e43d034348bdf3cb3f06ebd56d811b3427e43f9220fee9a104f50d3972cb5cd
+ sha256sums = a659dfcf8e4f91123832ae89b9ac92bbcc9ea8d90a698533ca25dff9ec610d90
+ sha256sums = e49fc613594d4fb540f0a562778e2fd45711548cbe3dc9769f5aa0773de16319
pkgname = realmd
diff --git a/0001-Add-missing-xsl-file-to-Makefile.am.patch b/0001-Add-missing-xsl-file-to-Makefile.am.patch
new file mode 100644
index 000000000000..33f26e6be15d
--- /dev/null
+++ b/0001-Add-missing-xsl-file-to-Makefile.am.patch
@@ -0,0 +1,27 @@
+From 81b5e3478269ea47d66ddb98f7cbebd06fe950e6 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 2 Aug 2019 13:18:37 +0200
+Subject: [PATCH 1/7] Add missing xsl file to Makefile.am
+
+In commit 4f3c02dc14300c0b8e51a55d627c57f73c108f64 it was forgotten to
+add the new file devhelp2.xsl to the Makefile to make sure it is
+include in the tar ball.
+---
+ doc/manual/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/doc/manual/Makefile.am b/doc/manual/Makefile.am
+index 39e1581..8b33fdd 100644
+--- a/doc/manual/Makefile.am
++++ b/doc/manual/Makefile.am
+@@ -37,6 +37,7 @@ MANUAL_XSLT = \
+ doc/manual/gdbus-fix-bugs.xsl \
+ doc/manual/gtk-doc.xsl \
+ doc/manual/version-greater-or-equal.xsl \
++ doc/manual/devhelp2.xsl \
+ $(NULL)
+
+ EXTRA_DIST += \
+--
+2.25.1
+
diff --git a/0001-Find-NetBIOS-name-in-keytab-while-leaving.patch b/0001-Find-NetBIOS-name-in-keytab-while-leaving.patch
new file mode 100644
index 000000000000..894fe9371948
--- /dev/null
+++ b/0001-Find-NetBIOS-name-in-keytab-while-leaving.patch
@@ -0,0 +1,168 @@
+From b11d891a50c2f70e3c02b880e0199583b8df186c Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 31 May 2018 16:16:08 +0200
+Subject: [PATCH] Find NetBIOS name in keytab while leaving
+
+If realmd is used with Samba as membership software, i.e. Samba's net
+utility, the NetBIOS name must be known when leaving a domain. The most
+reliable way to find it is by searching the keytab for NAME$@REALM type
+entries and use the NAME as the NetBIOS name.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1370457
+---
+ service/realm-kerberos.c | 64 ++++++++++++++++++++++++++++++++++++
+ service/realm-kerberos.h | 2 ++
+ service/realm-samba-enroll.c | 17 ++++++++--
+ 3 files changed, 80 insertions(+), 3 deletions(-)
+
+diff --git a/service/realm-kerberos.c b/service/realm-kerberos.c
+index 54d1ed7..d6d109f 100644
+--- a/service/realm-kerberos.c
++++ b/service/realm-kerberos.c
+@@ -1130,3 +1130,67 @@ realm_kerberos_flush_keytab (const gchar *realm_name,
+ return ret;
+
+ }
++
++gchar *
++realm_kerberos_get_netbios_name_from_keytab (const gchar *realm_name)
++{
++ krb5_error_code code;
++ krb5_keytab keytab = NULL;
++ krb5_context ctx;
++ krb5_kt_cursor cursor = NULL;
++ krb5_keytab_entry entry;
++ krb5_principal realm_princ = NULL;
++ gchar *princ_name = NULL;
++ gchar *netbios_name = NULL;
++ krb5_data *name_data;
++
++ code = krb5_init_context (&ctx);
++ if (code != 0) {
++ return NULL;
++ }
++
++ princ_name = g_strdup_printf ("user@%s", realm_name);
++ code = krb5_parse_name (ctx, princ_name, &realm_princ);
++ g_free (princ_name);
++
++ if (code == 0) {
++ code = krb5_kt_default (ctx, &keytab);
++ }
++
++ if (code == 0) {
++ code = krb5_kt_start_seq_get (ctx, keytab, &cursor);
++ }
++
++ if (code == 0) {
++ while (!krb5_kt_next_entry (ctx, keytab, &entry, &cursor) && netbios_name == NULL) {
++ if (krb5_realm_compare (ctx, realm_princ, entry.principal)) {
++ name_data = krb5_princ_component (ctx, entry.principal, 0);
++ if (name_data != NULL
++ && name_data->length > 0
++ && name_data->data[name_data->length - 1] == '$') {
++ netbios_name = g_strndup (name_data->data, name_data->length - 1);
++ if (netbios_name == NULL) {
++ code = krb5_kt_free_entry (ctx, &entry);
++ warn_if_krb5_failed (ctx, code);
++ break;
++ }
++ }
++ }
++ code = krb5_kt_free_entry (ctx, &entry);
++ warn_if_krb5_failed (ctx, code);
++ }
++ }
++
++ code = krb5_kt_end_seq_get (ctx, keytab, &cursor);
++ warn_if_krb5_failed (ctx, code);
++
++ code = krb5_kt_close (ctx, keytab);
++ warn_if_krb5_failed (ctx, code);
++
++ krb5_free_principal (ctx, realm_princ);
++
++ krb5_free_context (ctx);
++
++ return netbios_name;
++
++}
+diff --git a/service/realm-kerberos.h b/service/realm-kerberos.h
+index 0447e4d..58cfe07 100644
+--- a/service/realm-kerberos.h
++++ b/service/realm-kerberos.h
+@@ -88,6 +88,8 @@ gchar * realm_kerberos_format_login (RealmKerberos *self,
+ gboolean realm_kerberos_flush_keytab (const gchar *realm_name,
+ GError **error);
+
++gchar * realm_kerberos_get_netbios_name_from_keytab (const gchar *realm_name);
++
+ const gchar * realm_kerberos_get_name (RealmKerberos *self);
+
+ const gchar * realm_kerberos_get_realm_name (RealmKerberos *self);
+diff --git a/service/realm-samba-enroll.c b/service/realm-samba-enroll.c
+index 76e7b79..f5edca3 100644
+--- a/service/realm-samba-enroll.c
++++ b/service/realm-samba-enroll.c
+@@ -85,7 +85,8 @@ static JoinClosure *
+ join_closure_init (GTask *task,
+ RealmDisco *disco,
+ GVariant *options,
+- GDBusMethodInvocation *invocation)
++ GDBusMethodInvocation *invocation,
++ gboolean do_join)
+ {
+ JoinClosure *join;
+ gchar *workgroup;
+@@ -93,6 +94,7 @@ join_closure_init (GTask *task,
+ int temp_fd;
+ const gchar *explicit_computer_name = NULL;
+ const gchar *authid = NULL;
++ gchar *name_from_keytab = NULL;
+
+ join = g_new0 (JoinClosure, 1);
+ join->disco = realm_disco_ref (disco);
+@@ -106,6 +108,14 @@ join_closure_init (GTask *task,
+ else if (disco->explicit_netbios)
+ authid = disco->explicit_netbios;
+
++ /* try to get the NetBIOS name from the keytab while leaving the domain */
++ if (explicit_computer_name == NULL && !do_join) {
++ name_from_keytab = realm_kerberos_get_netbios_name_from_keytab(disco->kerberos_realm);
++ if (name_from_keytab != NULL) {
++ authid = name_from_keytab;
++ }
++ }
++
+ join->config = realm_ini_config_new (REALM_INI_NO_WATCH | REALM_INI_PRIVATE);
+ realm_ini_config_set (join->config, REALM_SAMBA_CONFIG_GLOBAL,
+ "security", "ads",
+@@ -151,6 +161,7 @@ join_closure_init (GTask *task,
+ g_warning ("Couldn't create temp file in: %s", g_get_tmp_dir ());
+ }
+
++ g_free (name_from_keytab);
+ return join;
+ }
+
+@@ -393,7 +404,7 @@ realm_samba_enroll_join_async (RealmDisco *disco,
+ g_return_if_fail (cred != NULL);
+
+ task = g_task_new (NULL, NULL, callback, user_data);
+- join = join_closure_init (task, disco, options, invocation);
++ join = join_closure_init (task, disco, options, invocation, TRUE);
+ explicit_computer_name = realm_options_computer_name (options, disco->domain_name);
+ if (explicit_computer_name != NULL) {
+ realm_diagnostics_info (invocation, "Joining using a manual netbios name: %s",
+@@ -462,7 +473,7 @@ realm_samba_enroll_leave_async (RealmDisco *disco,
+ JoinClosure *join;
+
+ task = g_task_new (NULL, NULL, callback, user_data);
+- join = join_closure_init (task, disco, options, invocation);
++ join = join_closure_init (task, disco, options, invocation, FALSE);
+
+ switch (cred->type) {
+ case REALM_CREDENTIAL_PASSWORD:
+--
+2.17.1
+
diff --git a/0001-Fix-issues-found-by-Coverity.patch b/0001-Fix-issues-found-by-Coverity.patch
new file mode 100644
index 000000000000..abb678220f48
--- /dev/null
+++ b/0001-Fix-issues-found-by-Coverity.patch
@@ -0,0 +1,42 @@
+From 1831748847715a13f0cc911a9a491eb8614d6682 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 14 Aug 2018 14:09:48 +0200
+Subject: [PATCH 1/3] Fix issues found by Coverity
+
+---
+ service/realm-kerberos.c | 5 ++++-
+ service/realm-packages.c | 2 +-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/service/realm-kerberos.c b/service/realm-kerberos.c
+index d6d109f..252e256 100644
+--- a/service/realm-kerberos.c
++++ b/service/realm-kerberos.c
+@@ -980,7 +980,10 @@ realm_kerberos_set_details (RealmKerberos *self,
+ if (name == NULL)
+ break;
+ value = va_arg (va, const gchar *);
+- g_return_if_fail (value != NULL);
++ if (value == NULL) {
++ va_end (va);
++ g_return_if_reached ();
++ }
+
+ values[0] = g_variant_new_string (name);
+ values[1] = g_variant_new_string (value);
+diff --git a/service/realm-packages.c b/service/realm-packages.c
+index 9a6984c..5976439 100644
+--- a/service/realm-packages.c
++++ b/service/realm-packages.c
+@@ -567,7 +567,7 @@ lookup_required_files_and_packages (const gchar **package_sets,
+ g_ptr_array_add (packages, NULL);
+ *result_packages = (gchar **)g_ptr_array_free (packages, FALSE);
+ } else {
+- g_ptr_array_free (files, TRUE);
++ g_ptr_array_free (packages, TRUE);
+ }
+
+ if (result_files) {
+--
+2.17.1
+
diff --git a/0001-Fix-man-page-reference-in-systemd-service-file.patch b/0001-Fix-man-page-reference-in-systemd-service-file.patch
new file mode 100644
index 000000000000..fe466209f1b2
--- /dev/null
+++ b/0001-Fix-man-page-reference-in-systemd-service-file.patch
@@ -0,0 +1,24 @@
+From e8d9d5e9817627dcf208ac742debcc9dc320752d Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 27 Jul 2016 19:06:29 +0200
+Subject: [PATCH] Fix man page reference in systemd service file
+
+---
+ dbus/realmd.service.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dbus/realmd.service.in b/dbus/realmd.service.in
+index b3bcf7a..64c1090 100644
+--- a/dbus/realmd.service.in
++++ b/dbus/realmd.service.in
+@@ -1,6 +1,6 @@
+ [Unit]
+ Description=Realm and Domain Configuration
+-Documentation=man:realmd(8)
++Documentation=man:realm(8)
+
+ [Service]
+ Type=dbus
+--
+2.7.4
+
diff --git a/0001-IPA-do-not-call-sssd-enable-logins.patch b/0001-IPA-do-not-call-sssd-enable-logins.patch
new file mode 100644
index 000000000000..01fdef86b305
--- /dev/null
+++ b/0001-IPA-do-not-call-sssd-enable-logins.patch
@@ -0,0 +1,62 @@
+From 373f2e03736dfd87d50f02208b99d462cf34d891 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 27 Sep 2018 13:04:47 +0200
+Subject: [PATCH] IPA: do not call sssd-enable-logins
+
+It is expected that ipa-client-install will do all PAM and NSS
+configuration. To avoid changing IPA default realmd will not try to
+update the related configuration.
+---
+ service/realm-sssd-ipa.c | 24 +-----------------------
+ 1 file changed, 1 insertion(+), 23 deletions(-)
+
+diff --git a/service/realm-sssd-ipa.c b/service/realm-sssd-ipa.c
+index 5029f6b..70f8b0e 100644
+--- a/service/realm-sssd-ipa.c
++++ b/service/realm-sssd-ipa.c
+@@ -109,41 +109,19 @@ enroll_closure_free (gpointer data)
+ g_free (enroll);
+ }
+
+-static void
+-on_enable_nss_done (GObject *source,
+- GAsyncResult *result,
+- gpointer user_data)
+-{
+- GTask *task = G_TASK (user_data);
+- GError *error = NULL;
+- gint status;
+-
+- status = realm_command_run_finish (result, NULL, &error);
+- if (error == NULL && status != 0)
+- g_set_error (&error, REALM_ERROR, REALM_ERROR_INTERNAL,
+- _("Enabling SSSD in nsswitch.conf and PAM failed."));
+- if (error != NULL)
+- g_task_return_error (task, error);
+- else
+- g_task_return_boolean (task, TRUE);
+- g_object_unref (task);
+-}
+-
+ static void
+ on_restart_done (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+ {
+ GTask *task = G_TASK (user_data);
+- EnrollClosure *enroll = g_task_get_task_data (task);
+ RealmSssd *sssd = g_task_get_source_object (task);
+ GError *error = NULL;
+
+ realm_service_enable_and_restart_finish (result, &error);
+ if (error == NULL) {
+ realm_sssd_update_properties (sssd);
+- realm_command_run_known_async ("sssd-enable-logins", NULL, enroll->invocation,
+- on_enable_nss_done, g_object_ref (task));
++ g_task_return_boolean (task, TRUE);
+ } else {
+ g_task_return_error (task, error);
+ }
+--
+2.17.1
+
diff --git a/0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch b/0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch
new file mode 100644
index 000000000000..a61b602a2720
--- /dev/null
+++ b/0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch
@@ -0,0 +1,112 @@
+From 6f0aa79c3e8dd93e723f29bf46e1b8b14403254f Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Mon, 5 Dec 2016 18:25:44 +0100
+Subject: [PATCH] Kerberos: fall back to tcp SRV lookup
+
+---
+ service/realm-kerberos-provider.c | 48 +++++++++++++++++++++++++++++++--------
+ 1 file changed, 39 insertions(+), 9 deletions(-)
+
+diff --git a/service/realm-kerberos-provider.c b/service/realm-kerberos-provider.c
+index 2b3a0f8..1477ae8 100644
+--- a/service/realm-kerberos-provider.c
++++ b/service/realm-kerberos-provider.c
+@@ -19,6 +19,7 @@
+ #include "realm-kerberos-provider.h"
+
+ #include <errno.h>
++#include <string.h>
+
+ struct _RealmKerberosProvider {
+ RealmProvider parent;
+@@ -38,28 +39,54 @@ realm_kerberos_provider_init (RealmKerberosProvider *self)
+
+ }
+
++typedef struct {
++ gchar *name;
++ const char *prot;
++} NameProtPair;
++
++static void
++name_prot_pair_free (gpointer data)
++{
++ NameProtPair *name_prot_pair = data;
++ g_free (name_prot_pair->name);
++ g_free (name_prot_pair);
++}
++
+ static void
+ on_kerberos_discover (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+ {
+ GTask *task = G_TASK (user_data);
+- const gchar *domain = g_task_get_task_data (task);
++ NameProtPair *name_prot_pair = g_task_get_task_data (task);
+ GError *error = NULL;
+ RealmDisco *disco;
+ GList *targets;
++ GResolver *resolver;
+
+ targets = g_resolver_lookup_service_finish (G_RESOLVER (source), result, &error);
+ if (targets) {
+ g_list_free_full (targets, (GDestroyNotify)g_srv_target_free);
+- disco = realm_disco_new (domain);
+- disco->kerberos_realm = g_ascii_strup (domain, -1);
++ disco = realm_disco_new (name_prot_pair->name);
++ disco->kerberos_realm = g_ascii_strup (name_prot_pair->name, -1);
+ g_task_return_pointer (task, disco, realm_disco_unref);
+
+ } else if (error) {
+- g_debug ("Resolving %s failed: %s", domain, error->message);
++ g_debug ("Resolving %s failed: %s", name_prot_pair->name, error->message);
+ g_error_free (error);
+- g_task_return_pointer (task, NULL, NULL);
++
++ if (strcmp (name_prot_pair->prot, "tcp") == 0) {
++ g_task_return_pointer (task, NULL, NULL);
++ } else {
++ /* Try tcp */
++ name_prot_pair->prot = "tcp";
++ resolver = g_resolver_get_default ();
++ g_resolver_lookup_service_async (resolver, "kerberos", name_prot_pair->prot,
++ name_prot_pair->name,
++ g_task_get_cancellable (task),
++ on_kerberos_discover, g_object_ref (task));
++ g_object_unref (resolver);
++ }
+ }
+
+ g_object_unref (task);
+@@ -76,7 +103,7 @@ realm_kerberos_provider_discover_async (RealmProvider *provider,
+ GTask *task;
+ const gchar *software;
+ GResolver *resolver;
+- gchar *name;
++ NameProtPair *name_prot_pair;
+
+ task = g_task_new (provider, NULL, callback, user_data);
+
+@@ -86,12 +113,15 @@ realm_kerberos_provider_discover_async (RealmProvider *provider,
+ g_task_return_pointer (task, NULL, NULL);
+
+ } else {
+- name = g_hostname_to_ascii (string);
++ name_prot_pair = g_new0 (NameProtPair, 1);
++ name_prot_pair->name = g_hostname_to_ascii (string);
++ name_prot_pair->prot = "udp";
+ resolver = g_resolver_get_default ();
+- g_resolver_lookup_service_async (resolver, "kerberos", "udp", name,
++ g_resolver_lookup_service_async (resolver, "kerberos", name_prot_pair->prot,
++ name_prot_pair->name,
+ realm_invocation_get_cancellable (invocation),
+ on_kerberos_discover, g_object_ref (task));
+- g_task_set_task_data (task, name, g_free);
++ g_task_set_task_data (task, name_prot_pair, name_prot_pair_free);
+ g_object_unref (resolver);
+ }
+
+--
+2.9.3
+
diff --git a/0001-LDAP-don-t-close-LDAP-socket-twice.patch b/0001-LDAP-don-t-close-LDAP-socket-twice.patch
new file mode 100644
index 000000000000..09e9ccf4760a
--- /dev/null
+++ b/0001-LDAP-don-t-close-LDAP-socket-twice.patch
@@ -0,0 +1,41 @@
+From 895e5b37d14090541480cebcb297846cbd3662ce Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 25 Nov 2016 17:35:11 +0100
+Subject: [PATCH] LDAP: don't close LDAP socket twice
+
+ldap_destroy() will call close() on the LDAP socket so with an explicit
+close() before the file descriptor will be closed twice. Even worse,
+since the file descriptor can be reused after the explicit call of
+close() by any other thread the close() called from ldap_destroy() might
+close a file descriptor used by a different thread as seen e.g. in
+https://bugzilla.redhat.com/show_bug.cgi?id=1398522.
+
+Additionally the patch makes sure that the closed connection cannot be
+used again.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1398522
+---
+ service/realm-ldap.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/service/realm-ldap.c b/service/realm-ldap.c
+index 061ed61..59817fb 100644
+--- a/service/realm-ldap.c
++++ b/service/realm-ldap.c
+@@ -159,10 +159,11 @@ ldap_source_finalize (GSource *source)
+ {
+ LdapSource *ls = (LdapSource *)source;
+
+- /* Yeah, this is pretty rough, but we don't want blocking here */
+- close (ls->sock);
+ ldap_destroy (ls->ldap);
+
++ ls->sock = -1;
++ ls->ldap = NULL;
++
+ if (ls->cancellable) {
+ g_cancellable_release_fd (ls->cancellable);
+ g_object_unref (ls->cancellable);
+--
+2.9.3
+
diff --git a/0001-Remove-support-for-deprecated-gtester-format.patch b/0001-Remove-support-for-deprecated-gtester-format.patch
new file mode 100644
index 000000000000..1302a382cce3
--- /dev/null
+++ b/0001-Remove-support-for-deprecated-gtester-format.patch
@@ -0,0 +1,39 @@
+From 5ae42c176e7bb550fc6cf10f29e75f58c733ae4f Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 2 Aug 2019 12:10:43 +0200
+Subject: [PATCH] Remove support for deprecated gtester format
+
+Support for the already deprecated gtester format was remove from recent
+versions of glib2 but the test still call the tab-gtester conversion
+tool.
+
+This patch removes tab-gtester and the tab format is used directly.
+
+Related to https://gitlab.freedesktop.org/realmd/realmd/issues/21
+---
+ Makefile.am | 3 +-
+ build/tap-gtester | 204 ----------------------------------------------
+ 2 files changed, 1 insertion(+), 206 deletions(-)
+ delete mode 100755 build/tap-gtester
+
+diff --git a/Makefile.am b/Makefile.am
+index 27e3494..4ffd5b4 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -161,7 +161,7 @@ endif
+ #
+
+ LOG_DRIVER = $(top_srcdir)/build/tap-driver
+-LOG_COMPILER = $(top_srcdir)/build/tap-gtester
++LOG_COMPILER = sh -c '"$$0" "$$@" --tap'
+
+ VALGRIND_ARGS = --trace-children=no --quiet --error-exitcode=33 \
+ --suppressions=valgrind-suppressions --gen-suppressions=all \
+@@ -183,7 +183,6 @@ recheck-memory: valgrind-suppressions
+
+ EXTRA_DIST += \
+ $(LOG_DRIVER) \
+- $(LOG_COMPILER) \
+ $(VALGRIND_SUPPRESSIONS) \
+ $(NULL)
+
diff --git a/0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch b/0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch
new file mode 100644
index 000000000000..e8ba689fd83a
--- /dev/null
+++ b/0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch
@@ -0,0 +1,47 @@
+From fa6dd59c5eaabc8c7e540f2aa2ded6f785de0a13 Mon Sep 17 00:00:00 2001
+From: Adam Williamson <awilliam@redhat.com>
+Date: Wed, 20 Feb 2019 11:12:04 -0800
+Subject: [PATCH] Set 'NEWEST' flag when resolving packages with PackageKit
+
+When resolving package names via PackageKit, realmd does not set
+the PK_FILTER_ENUM_NEWEST flag that asks PK to only give the
+*newest available* package for each package name. So if there
+are three different versions of the package available in three
+repositories, realmd winds up producing an array containing the
+package IDs for all three of those packages and calling
+InstallPackages on all of them. I don't know if PK's behaviour
+in this case is defined or predictable, but in practice in at
+least one case it reliably results in one of the older package
+versions being installed.
+
+This does not seem desirable, we should always want to install
+the newest available version. So let's set the NEWEST flag to
+ensure this.
+
+A possible consequence here is that, if a newer version of the
+package is not installable but an older version is, we will now
+fail where previously we did not. But even in that case I don't
+know if we would *reliably* succeed before, and silently
+installing an older version still doesn't necessarily seem like
+the right thing to do.
+
+Signed-off-by: Adam Williamson <awilliam@redhat.com>
+---
+ service/realm-packages.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/service/realm-packages.c b/service/realm-packages.c
+index 5976439..0309c57 100644
+--- a/service/realm-packages.c
++++ b/service/realm-packages.c
+@@ -343,6 +343,7 @@ packages_resolve_async (GDBusConnection *connection,
+ gpointer user_data)
+ {
+ guint64 flags = 1 << 18 /* PK_FILTER_ENUM_ARCH */;
++ flags |= 1 << 16 /* PK_FILTER_ENUM_NEWEST */;
+ package_transaction_create ("Resolve", g_variant_new ("(t^as)", flags, package_names),
+ connection, cancellable, callback, user_data);
+ }
+--
+2.20.1
+
diff --git a/0001-Use-current-idmap-options-for-smb.conf.patch b/0001-Use-current-idmap-options-for-smb.conf.patch
new file mode 100644
index 000000000000..ea34960f8c32
--- /dev/null
+++ b/0001-Use-current-idmap-options-for-smb.conf.patch
@@ -0,0 +1,185 @@
+From e683fb573bc09893ec541be29751560cea30ce3f Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 30 May 2018 13:10:57 +0200
+Subject: [PATCH] Use current idmap options for smb.conf
+
+Samba change some time ago the way how to configure id-mapping. With
+this patch realmd will use the current supported options when creating
+smb.conf.
+
+A new option --legacy-samba-config is added to use the old options if
+realmd is used with Samba 3.5 or earlier.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1484072
+---
+ dbus/realm-dbus-constants.h | 1 +
+ doc/manual/realmd.conf.xml | 17 ++++++++++++
+ service/realm-samba-enroll.c | 2 +-
+ service/realm-samba-enroll.h | 3 +++
+ service/realm-samba-winbind.c | 63 ++++++++++++++++++++++++++++++++++---------
+ 5 files changed, 72 insertions(+), 14 deletions(-)
+
+diff --git a/dbus/realm-dbus-constants.h b/dbus/realm-dbus-constants.h
+index 9cd30ef..40ffa2d 100644
+--- a/dbus/realm-dbus-constants.h
++++ b/dbus/realm-dbus-constants.h
+@@ -69,6 +69,7 @@ G_BEGIN_DECLS
+ #define REALM_DBUS_OPTION_COMPUTER_NAME "computer-name"
+ #define REALM_DBUS_OPTION_OS_NAME "os-name"
+ #define REALM_DBUS_OPTION_OS_VERSION "os-version"
++#define REALM_DBUS_OPTION_LEGACY_SMB_CONF "legacy-samba-config"
+
+ #define REALM_DBUS_IDENTIFIER_ACTIVE_DIRECTORY "active-directory"
+ #define REALM_DBUS_IDENTIFIER_WINBIND "winbind"
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index 7853230..a2b577c 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -192,6 +192,23 @@ automatic-install = no
+ </listitem>
+ </varlistentry>
+
++ <varlistentry>
++ <term><option>legacy-samba-config</option></term>
++ <listitem>
++ <para>Set this to <parameter>yes</parameter> to create a Samba
++ configuration file with id-mapping options used by Samba-3.5
++ and earlier version.</para>
++
++ <informalexample>
++<programlisting language="js">
++[service]
++legacy-samba-config = no
++# legacy-samba-config = yes
++</programlisting>
++ </informalexample>
++ </listitem>
++ </varlistentry>
++
+ </variablelist>
+ </refsect1>
+
+diff --git a/service/realm-samba-enroll.c b/service/realm-samba-enroll.c
+index c81aed2..76e7b79 100644
+--- a/service/realm-samba-enroll.c
++++ b/service/realm-samba-enroll.c
+@@ -69,7 +69,7 @@ join_closure_free (gpointer data)
+ g_free (join);
+ }
+
+-static gchar *
++gchar *
+ fallback_workgroup (const gchar *realm)
+ {
+ const gchar *pos;
+diff --git a/service/realm-samba-enroll.h b/service/realm-samba-enroll.h
+index 84e8b2f..310ec65 100644
+--- a/service/realm-samba-enroll.h
++++ b/service/realm-samba-enroll.h
+@@ -46,6 +46,9 @@ void realm_samba_enroll_leave_async (RealmDisco *disco,
+ gboolean realm_samba_enroll_leave_finish (GAsyncResult *result,
+ GError **error);
+
++gchar *
++fallback_workgroup (const gchar *realm);
++
+ G_END_DECLS
+
+ #endif /* __REALM_SAMBA_ENROLL_H__ */
+diff --git a/service/realm-samba-winbind.c b/service/realm-samba-winbind.c
+index a7ddec3..9335e26 100644
+--- a/service/realm-samba-winbind.c
++++ b/service/realm-samba-winbind.c
+@@ -21,8 +21,10 @@
+ #include "realm-options.h"
+ #include "realm-samba-config.h"
+ #include "realm-samba-winbind.h"
++#include "realm-samba-enroll.h"
+ #include "realm-settings.h"
+ #include "realm-service.h"
++#include "dbus/realm-dbus-constants.h"
+
+ #include <glib/gstdio.h>
+
+@@ -80,6 +82,10 @@ realm_samba_winbind_configure_async (RealmIniConfig *config,
+ RealmIniConfig *pwc;
+ GTask *task;
+ GError *error = NULL;
++ gchar *workgroup = NULL;
++ gchar *idmap_config_backend = NULL;
++ gchar *idmap_config_range = NULL;
++ gchar *idmap_config_schema_mode = NULL;
+
+ g_return_if_fail (config != NULL);
+ g_return_if_fail (invocation != NULL || G_IS_DBUS_METHOD_INVOCATION (invocation));
+@@ -100,23 +106,54 @@ realm_samba_winbind_configure_async (RealmIniConfig *config,
+ "template shell", realm_settings_string ("users", "default-shell"),
+ NULL);
+
+- if (realm_options_automatic_mapping (options, domain_name)) {
+- realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
+- "idmap uid", "10000-2000000",
+- "idmap gid", "10000-2000000",
+- "idmap backend", "tdb",
+- "idmap schema", NULL,
+- NULL);
++ if (realm_settings_boolean ("service", REALM_DBUS_OPTION_LEGACY_SMB_CONF, FALSE)) {
++ if (realm_options_automatic_mapping (options, domain_name)) {
++ realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
++ "idmap uid", "10000-2000000",
++ "idmap gid", "10000-2000000",
++ "idmap backend", "tdb",
++ "idmap schema", NULL,
++ NULL);
++ } else {
++ realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
++ "idmap uid", "500-4294967296",
++ "idmap gid", "500-4294967296",
++ "idmap backend", "ad",
++ "idmap schema", "rfc2307",
++ NULL);
++ }
+ } else {
+- realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
+- "idmap uid", "500-4294967296",
+- "idmap gid", "500-4294967296",
+- "idmap backend", "ad",
+- "idmap schema", "rfc2307",
+- NULL);
++ workgroup = realm_ini_config_get (config, REALM_SAMBA_CONFIG_GLOBAL, "workgroup");
++ if (workgroup == NULL) {
++ workgroup = fallback_workgroup (domain_name);
++ }
++ idmap_config_backend = g_strdup_printf ("idmap config %s : backend", workgroup != NULL ? workgroup : "PLEASE_REPLACE");
++ idmap_config_range = g_strdup_printf ("idmap config %s : range", workgroup != NULL ? workgroup : "PLEASE_REPLACE");
++ idmap_config_schema_mode = g_strdup_printf ("idmap config %s : schema_mode", workgroup != NULL ? workgroup : "PLEASE_REPLACE");
++ g_free (workgroup);
++
++ if (realm_options_automatic_mapping (options, domain_name)) {
++ realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
++ "idmap config * : backend", "tdb",
++ "idmap config * : range", "10000-999999",
++ idmap_config_backend != NULL ? idmap_config_backend : "idmap config PLEASE_REPLACE : backend", "rid",
++ idmap_config_range != NULL ? idmap_config_range: "idmap config PLEASE_REPLACE : range", "2000000-2999999",
++ idmap_config_schema_mode != NULL ? idmap_config_schema_mode: "idmap config PLEASE_REPLACE : schema_mode", NULL,
++ NULL);
++ } else {
++ realm_ini_config_set (config, REALM_SAMBA_CONFIG_GLOBAL,
++ "idmap config * : backend", "tdb",
++ "idmap config * : range", "10000000-10999999",
++ idmap_config_backend != NULL ? idmap_config_backend : "idmap config PLEASE_REPLACE : backend", "ad",
++ idmap_config_range != NULL ? idmap_config_range: "idmap config PLEASE_REPLACE : range", "500-999999",
++ idmap_config_schema_mode != NULL ? idmap_config_schema_mode: "idmap config PLEASE_REPLACE : schema_mode", "rfc2307",
++ NULL);
++ }
+ }
+
+ realm_ini_config_finish_change (config, &error);
++ g_free (idmap_config_backend);
++ g_free (idmap_config_range);
+ }
+
+ /* Setup pam_winbind.conf with decent defaults matching our expectations */
+--
+2.14.4
+
diff --git a/0001-doc-make-sure-cross-reference-ids-are-predictable.patch b/0001-doc-make-sure-cross-reference-ids-are-predictable.patch
new file mode 100644
index 000000000000..64e1f39e1c5b
--- /dev/null
+++ b/0001-doc-make-sure-cross-reference-ids-are-predictable.patch
@@ -0,0 +1,1500 @@
+From 4f3c02dc14300c0b8e51a55d627c57f73c108f64 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 10:36:19 +0200
+Subject: [PATCH 1/7] doc: make sure cross-reference ids are predictable
+
+To make sure the cross-reference ids are predictable in the
+auto-generated DBus documentation as well the xsl and css files form the
+gtk-doc package are updated as well.
+---
+ doc/manual/devhelp2.xsl | 173 ++++++++
+ doc/manual/gtk-doc.xsl | 436 ++++++++-----------
+ doc/manual/realm.xml | 14 +-
+ doc/manual/realmd-guide-active-directory.xml | 4 +-
+ doc/manual/realmd-guide-ipa.xml | 2 +-
+ doc/manual/realmd-guide-kerberos.xml | 2 +-
+ doc/manual/realmd.conf.xml | 4 +-
+ doc/manual/static/gtk-doc.css | 420 +++++++++++++-----
+ 8 files changed, 688 insertions(+), 367 deletions(-)
+ create mode 100644 doc/manual/devhelp2.xsl
+
+diff --git a/doc/manual/devhelp2.xsl b/doc/manual/devhelp2.xsl
+new file mode 100644
+index 0000000..bab6692
+--- /dev/null
++++ b/doc/manual/devhelp2.xsl
+@@ -0,0 +1,173 @@
++<?xml version='1.0'?> <!--*- mode: xml -*-->
++<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
++ version='1.0'
++ xmlns="http://www.devhelp.net/book"
++ xmlns:str="http://exslt.org/strings"
++ exclude-result-prefixes="str">
++
++ <xsl:template name="generate.devhelp2">
++ <xsl:call-template name="write.chunk">
++ <xsl:with-param name="filename">
++ <xsl:choose>
++ <xsl:when test="$gtkdoc.bookname">
++ <xsl:value-of select="$gtkdoc.bookname"/>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:text>book</xsl:text>
++ </xsl:otherwise>
++ </xsl:choose>
++ <xsl:text>.devhelp2</xsl:text>
++ </xsl:with-param>
++ <xsl:with-param name="method" select="'xml'"/>
++ <xsl:with-param name="indent" select="'yes'"/>
++ <xsl:with-param name="encoding" select="'utf-8'"/>
++ <xsl:with-param name="doctype-public"/>
++ <xsl:with-param name="content">
++ <xsl:call-template name="devhelp2"/>
++ </xsl:with-param>
++ </xsl:call-template>
++ </xsl:template>
++
++ <xsl:variable name="gtkdoc.refsect2" select="//refsect2"/>
++
++ <xsl:template name="devhelp2">
++ <xsl:variable name="title">
++ <xsl:apply-templates select="." mode="generate.devhelp2.toc.title.mode"/>
++ </xsl:variable>
++ <xsl:variable name="link">
++ <xsl:call-template name="href.target"/>
++ </xsl:variable>
++ <xsl:variable name="author">
++ <xsl:if test="articleinfo|bookinfo">
++ <xsl:apply-templates mode="generate.devhelp2.authors"
++ select="articleinfo|bookinfo"/>
++ </xsl:if>
++ </xsl:variable>
++ <xsl:variable name="online">
++ <xsl:value-of select="/book/bookinfo/releaseinfo/ulink[@role='online-location']/@url"/>
++ </xsl:variable>
++ <xsl:variable name="toc.nodes" select="part|reference|preface|chapter|
++ appendix|article|bibliography|
++ glossary|index|refentry|
++ bridgehead|sect1"/>
++
++ <book title="{$title}" link="{$link}" author="{$author}" name="{$gtkdoc.bookname}" version="2" language="c">
++ <xsl:if test="$online != ''">
++ <xsl:attribute name="online"><xsl:value-of select="$online"/></xsl:attribute>
++ </xsl:if>
++ <xsl:if test="$toc.nodes">
++ <chapters>
++ <xsl:apply-templates select="$toc.nodes"
++ mode="generate.devhelp2.toc.mode"/>
++ </chapters>
++ </xsl:if>
++ <functions>
++ <xsl:apply-templates select="$gtkdoc.refsect2[@role]"
++ mode="generate.devhelp2.index.mode"/>
++ <xsl:apply-templates select="$gtkdoc.refsect2/refsect3[@role='enum_members']/informaltable/tgroup/tbody/row[@role='constant']"
++ mode="generate.devhelp2.index.mode"/>
++ <xsl:apply-templates select="$gtkdoc.refsect2/refsect3[@role='struct_members']/informaltable/tgroup/tbody/row[@role='member']"
++ mode="generate.devhelp2.index.mode"/>
++ </functions>
++ </book>
++ </xsl:template>
++
++ <xsl:template match="*" mode="generate.devhelp2.toc.mode">
++ <xsl:variable name="title">
++ <xsl:apply-templates select="." mode="generate.devhelp2.toc.title.mode"/>
++ </xsl:variable>
++ <xsl:variable name="target">
++ <xsl:variable name="anchor" select="title/anchor"/>
++ <xsl:choose>
++ <xsl:when test="$anchor">
++ <xsl:call-template name="href.target">
++ <xsl:with-param name="object" select="$anchor"/>
++ </xsl:call-template>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:call-template name="href.target"/>
++ </xsl:otherwise>
++ </xsl:choose>
++ </xsl:variable>
++
++ <sub name="{$title}" link="{$target}">
++ <xsl:apply-templates select="section|sect1|
++ refentry|refsect|
++ bridgehead|part|chapter|glossary|index"
++ mode="generate.devhelp2.toc.mode"/>
++ </sub>
++ </xsl:template>
++
++ <xsl:template match="*" mode="generate.devhelp2.index.mode">
++ <xsl:variable name="title" select="title|
++ term/literal|
++ entry[@role='enum_member_name']/para|
++ entry[@role='struct_member_name']/para/structfield/@id"/>
++ <xsl:variable name="anchor" select="title/anchor|
++ entry[@role='enum_member_name']/para|
++ entry[@role='struct_member_name']/para/structfield"/>
++ <xsl:variable name="type" select="@role"/>
++ <xsl:variable name="condition" select="@condition"/>
++ <xsl:variable name="target">
++ <xsl:choose>
++ <xsl:when test="$anchor">
++ <xsl:call-template name="href.target">
++ <xsl:with-param name="object" select="$anchor"/>
++ </xsl:call-template>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:call-template name="href.target"/>
++ </xsl:otherwise>
++ </xsl:choose>
++ </xsl:variable>
++ <keyword type="{$type}" name="{$title}" link="{$target}">
++ <xsl:if test="$condition">
++ <xsl:for-each select="str:split($condition,'|')">
++ <xsl:variable name="attrname">
++ <xsl:value-of select="substring-before(.,':')"/>
++ </xsl:variable>
++ <xsl:choose>
++ <xsl:when test="string-length($attrname)=0">
++ <xsl:variable name="attrname2">
++ <xsl:value-of select="."/>
++ </xsl:variable>
++ <xsl:attribute name="{$attrname2}"/>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:attribute name="{$attrname}">
++ <xsl:value-of select="substring-after(.,':')"/>
++ </xsl:attribute>
++ </xsl:otherwise>
++ </xsl:choose>
++ </xsl:for-each>
++ </xsl:if>
++ </keyword>
++ </xsl:template>
++
++ <!-- get title -->
++ <xsl:template match="article" mode="generate.devhelp2.toc.title.mode">
++ <xsl:value-of select="articleinfo/title"/>
++ </xsl:template>
++ <xsl:template match="book" mode="generate.devhelp2.toc.title.mode">
++ <xsl:value-of select="bookinfo/title"/>
++ </xsl:template>
++ <xsl:template match="refentry" mode="generate.devhelp2.toc.title.mode">
++ <xsl:value-of select="refmeta/refentrytitle"/>
++ </xsl:template>
++ <xsl:template match="*" mode="generate.devhelp2.toc.title.mode">
++ <xsl:value-of select="title"/>
++ </xsl:template>
++
++ <!-- generate list of authors ... -->
++ <xsl:template match="articleinfo|bookinfo" mode="generate.devhelp2.authors">
++ <xsl:for-each select="authorgroup/author">
++ <xsl:value-of select="firstname"/>
++ <xsl:text> </xsl:text>
++ <xsl:value-of select="surname"/>
++ <xsl:if test="not(last())">
++ <xsl:text>, </xsl:text>
++ </xsl:if>
++ </xsl:for-each>
++ </xsl:template>
++
++</xsl:stylesheet>
+diff --git a/doc/manual/gtk-doc.xsl b/doc/manual/gtk-doc.xsl
+index 9c0901b..3471e6c 100644
+--- a/doc/manual/gtk-doc.xsl
++++ b/doc/manual/gtk-doc.xsl
+@@ -5,20 +5,19 @@
+ version="1.0">
+
+ <!-- import the chunked XSL stylesheet -->
+- <!-- http://www.sagehill.net/docbookxsl/Chunking.html says we should use
+- "chunkfast.xsl", but I can see a difference -->
++ <!-- http://www.sagehill.net/docbookxsl/Chunking.html#FastChunking says we should use
++ "chunkfast.xsl", but I can't see a difference. Also it is not clear wheter
++ one should still set "chunk.fast". Again, no meassuable difference. -->
+ <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>
++ <xsl:include href="devhelp2.xsl"/>
+ <xsl:include href="version-greater-or-equal.xsl"/>
+
+- <xsl:key name="acronym.key"
+- match="glossentry/glossterm"
+- use="."/>
+- <xsl:key name="gallery.key"
+- match="para[@role='gallery']/link"
+- use="@linkend"/>
++ <xsl:key name="acronym.key" match="glossentry/glossterm" use="."/>
++ <xsl:key name="gallery.key" match="para[@role='gallery']/link" use="@linkend"/>
+
+ <!-- change some parameters -->
+ <!-- http://docbook.sourceforge.net/release/xsl/current/doc/html/index.html -->
++ <xsl:param name="admon.style"/>
+ <xsl:param name="toc.section.depth">2</xsl:param>
+ <xsl:param name="generate.toc">
+ book toc
+@@ -28,16 +27,17 @@
+ part toc
+ reference toc
+ </xsl:param>
++ <xsl:param name="process.empty.source.toc">1</xsl:param>
+
+ <xsl:param name="chunker.output.encoding" select="'UTF-8'"/>
+ <xsl:param name="chunker.output.indent" select="'yes'"/>
+ <xsl:param name="chunker.output.doctype-public" select="'-//W3C//DTD HTML 4.01 Transitional//EN'"/>
+ <xsl:param name="chunk.fast" select="1"/>
+- <xsl:param name="chunk.quietly" select="1"/>
+
+ <xsl:param name="default.encoding" select="'UTF-8'"/>
+ <xsl:param name="chapter.autolabel" select="0"/>
+ <xsl:param name="use.id.as.filename" select="1"/>
++ <xsl:param name="generate.consistent.ids" select="1"/>
+ <xsl:param name="html.ext" select="'.html'"/>
+ <xsl:param name="refentry.generate.name" select="0"/>
+ <xsl:param name="refentry.generate.title" select="1"/>
+@@ -60,6 +60,9 @@
+ <xsl:param name="gtkdoc.version" select="''"/>
+ <xsl:param name="gtkdoc.bookname" select="''"/>
+
++ <!-- Override the typical template to prevent showing titles -->
++ <xsl:param name="admon.textlabel" select="0"/>
++
+ <!-- ========================================================= -->
+
+ <!-- l10n is slow, we don't ue it, so we'd like to turn it off
+@@ -68,12 +71,8 @@
+
+ <xsl:param name="gtkdoc.l10n.xml" select="document('http://docbook.sourceforge.net/release/xsl/current/common/en.xml')"/>
+
+- <xsl:key name="gtkdoc.gentext.key"
+- match="l:gentext[@key]"
+- use="@key"/>
+- <xsl:key name="gtkdoc.context.key"
+- match="l:context[@name]"
+- use="@name"/>
++ <xsl:key name="gtkdoc.gentext.key" match="l:gentext[@key]" use="@key"/>
++ <xsl:key name="gtkdoc.context.key" match="l:context[@name]" use="@name"/>
+
+ <xsl:template name="gentext">
+ <xsl:param name="key" select="local-name(.)"/>
+@@ -250,7 +249,6 @@
+ </xsl:if>
+ </xsl:variable>
+
+-
+ <xsl:variable name="is.title-unnumbered">
+ <xsl:if test="$is.title = 0 and $is.title-numbered = 0">
+ <xsl:call-template name="gentext.template.exists">
+@@ -309,52 +307,8 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ </xsl:if>
+ <xsl:apply-imports/>
+
+- <!-- generate the index.sgml href index -->
+- <xsl:call-template name="generate.index"/>
+- </xsl:template>
+-
+- <xsl:template name="generate.index">
+- <xsl:call-template name="write.text.chunk">
+- <xsl:with-param name="filename" select="'index.sgml'"/>
+- <xsl:with-param name="content">
+- <xsl:apply-templates select="/book/bookinfo/releaseinfo/ulink"
+- mode="generate.index.mode"/>
+- <!-- check all anchor and refentry elements -->
+- <!--
+- The obvious way to write this is //anchor|//refentry|etc...
+- The obvious way is slow because it causes multiple traversals
+- in libxslt. This take about half the time.
+- -->
+- <xsl:apply-templates select="//*[name()='anchor' or name()='refentry' or name()='refsect1' or
+- name() = 'refsect2' or name()='refsynopsisdiv' or
+- name()='varlistentry']"
+- mode="generate.index.mode"/>
+- </xsl:with-param>
+- <xsl:with-param name="default.encoding" select="'UTF-8'"/>
+- <xsl:with-param name="chunker.output.indent" select="'no'"/>
+- </xsl:call-template>
+- </xsl:template>
+-
+- <xsl:template match="*" mode="generate.index.mode">
+- <xsl:if test="not(@href) and count(@id) > 0">
+- <xsl:text>&lt;ANCHOR id=&quot;</xsl:text>
+- <xsl:value-of select="@id"/>
+- <xsl:text>&quot; href=&quot;</xsl:text>
+- <xsl:if test="$gtkdoc.bookname">
+- <xsl:value-of select="$gtkdoc.bookname"/>
+- <xsl:text>/</xsl:text>
+- </xsl:if>
+- <xsl:call-template name="href.target"/>
+- <xsl:text>&quot;&gt;&#10;</xsl:text>
+- </xsl:if>
+- </xsl:template>
+-
+- <xsl:template match="/book/bookinfo/releaseinfo/ulink" mode="generate.index.mode">
+- <xsl:if test="@role='online-location'">
+- <xsl:text>&lt;ONLINE href=&quot;</xsl:text>
+- <xsl:value-of select="@url"/>
+- <xsl:text>&quot;&gt;&#10;</xsl:text>
+- </xsl:if>
++ <!-- generate $book.devhelp2 -->
++ <xsl:call-template name="generate.devhelp2"/>
+ </xsl:template>
+
+ <!-- ========================================================= -->
+@@ -387,6 +341,15 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <xsl:apply-imports/>
+ </xsl:template>
+
++ <xsl:template name="user.head.title">
++ <xsl:param name="node" select="."/>
++ <xsl:param name="title"/>
++ <xsl:variable name="home" select="/*[1]"/>
++ <title>
++ <xsl:copy-of select="$title"/>: <xsl:apply-templates select="$home" mode="object.title.markup"/>
++ </title>
++ </xsl:template>
++
+ <xsl:template name="user.head.content">
+ <xsl:if test="$gtkdoc.version">
+ <meta name="generator" content="GTK-Doc V{$gtkdoc.version} (XML mode)"/>
+@@ -399,10 +362,10 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <hr />
+ <xsl:choose>
+ <xsl:when test="$gtkdoc.version">
+- Generated by GTK-Doc V<xsl:copy-of select="$gtkdoc.version" />
++ <xsl:text>Generated by GTK-Doc V</xsl:text><xsl:copy-of select="$gtkdoc.version" />
+ </xsl:when>
+ <xsl:otherwise>
+- Generated by GTK-Doc
++ <xsl:text>Generated by GTK-Doc</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+@@ -451,21 +414,119 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+
+ <xsl:if test="$suppress.navigation = '0' and $home != .">
+ <table class="navigation" id="top" width="100%"
+- summary = "Navigation header" cellpadding="2" cellspacing="2">
++ summary = "Navigation header" cellpadding="2" cellspacing="5">
+ <tr valign="middle">
++ <td width="100%" align="left" class="shortcuts">
++ <!--<xsl:if test="name()='refentry'"-->
++ <xsl:choose>
++ <xsl:when test="count($refsections) > 0">
++ <a href="#" class="shortcut">Top</a>
++ <xsl:if test="count($sect_desc) > 0">
++ <span id="nav_description">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.description" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='desc']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_object_hierarchy) > 0">
++ <span id="nav_hierarchy">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.object-hierarchy" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='object_hierarchy']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_impl_interfaces) > 0">
++ <span id="nav_interfaces">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.implemented-interfaces" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='impl_interfaces']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_prerequisites) > 0">
++ <span id="nav_prerequisites">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.prerequisites" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='prerequisites']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_derived_interfaces) > 0">
++ <span id="nav_derived_interfaces">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.derived-interfaces" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='derived_interfaces']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_implementations) > 0">
++ <span id="nav_implementations">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.implementations" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='implementations']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_properties) > 0">
++ <span id="nav_properties">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.properties" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='properties']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_child_properties) > 0">
++ <span id="nav_child_properties">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.child-properties" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='child_properties']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_style_properties) > 0">
++ <span id="nav_style_properties">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.style-properties" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='style_properties']/title"/>
++ </a></span>
++ </xsl:if>
++ <xsl:if test="count($sect_signal_proto) > 0">
++ <span id="nav_signals">&#160;&#160;<span class="dim">|</span>&#160;
++ <a href="#{$section_id}.signals" class="shortcut">
++ <xsl:value-of select="./refsect1[@role='signal_proto']/title"/>
++ </a></span>
++ </xsl:if>
++ </xsl:when>
++ <!-- this is not yet very nice, as it requires all glossdic/indexdiv
++ elements having a anchor element. maybe we can customize the xsl
++ to automaticaly create local anchors
++ -->
++ <xsl:when test="count($glssections) > 0">
++ <span id="nav_glossary">
++ <xsl:for-each select="./glossdiv">
++ <xsl:if test="position() > 1">
++ &#160;<span class="dim">|</span>&#160;
++ </xsl:if>
++ <a class="shortcut">
++ <xsl:attribute name="href">#gls<xsl:value-of select="./title"/></xsl:attribute>
++ <xsl:value-of select="./title"/>
++ </a>
++ </xsl:for-each>
++ </span>
++ </xsl:when>
++ <xsl:when test="count($idxsections) > 0">
++ <span id="nav_index">
++ <xsl:for-each select="./indexdiv/indexdiv">
++ <xsl:if test="position() > 1">
++ &#160;<span class="dim">|</span>&#160;
++ </xsl:if>
++ <a class="shortcut">
++ <xsl:attribute name="href">#idx<xsl:value-of select="./title"/></xsl:attribute>
++ <xsl:value-of select="./title"/>
++ </a>
++ </xsl:for-each>
++ </span>
++ </xsl:when>
++ </xsl:choose>
++ </td>
+ <xsl:choose>
+- <xsl:when test="count($prev) > 0">
++ <xsl:when test="$home != .">
+ <td>
+- <a accesskey="p">
++ <a accesskey="h">
+ <xsl:attribute name="href">
+ <xsl:call-template name="href.target">
+- <xsl:with-param name="object" select="$prev"/>
++ <xsl:with-param name="object" select="$home"/>
+ </xsl:call-template>
+ </xsl:attribute>
+- <img src="left.png" width="24" height="24" border="0">
++ <img src="home.png" width="16" height="16" border="0">
+ <xsl:attribute name="alt">
+ <xsl:call-template name="gentext">
+- <xsl:with-param name="key">nav-prev</xsl:with-param>
++ <xsl:with-param name="key">nav-home</xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+ </img>
+@@ -485,7 +546,7 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <xsl:with-param name="object" select="$up"/>
+ </xsl:call-template>
+ </xsl:attribute>
+- <img src="up.png" width="24" height="24" border="0">
++ <img src="up.png" width="16" height="16" border="0">
+ <xsl:attribute name="alt">
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key">nav-up</xsl:with-param>
+@@ -496,22 +557,22 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ </td>
+ </xsl:when>
+ <xsl:otherwise>
+- <td>&#160;</td>
++ <td><img src="up-insensitive.png" width="16" height="16" border="0"/></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+- <xsl:when test="$home != .">
++ <xsl:when test="count($prev) > 0">
+ <td>
+- <a accesskey="h">
++ <a accesskey="p">
+ <xsl:attribute name="href">
+ <xsl:call-template name="href.target">
+- <xsl:with-param name="object" select="$home"/>
++ <xsl:with-param name="object" select="$prev"/>
+ </xsl:call-template>
+ </xsl:attribute>
+- <img src="home.png" width="24" height="24" border="0">
++ <img src="left.png" width="16" height="16" border="0">
+ <xsl:attribute name="alt">
+ <xsl:call-template name="gentext">
+- <xsl:with-param name="key">nav-home</xsl:with-param>
++ <xsl:with-param name="key">nav-prev</xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+ </img>
+@@ -519,12 +580,9 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ </td>
+ </xsl:when>
+ <xsl:otherwise>
+- <td>&#160;</td>
++ <td><img src="left-insensitive.png" width="16" height="16" border="0"/></td>
+ </xsl:otherwise>
+ </xsl:choose>
+- <th width="100%" align="center">
+- <xsl:apply-templates select="$home" mode="object.title.markup"/>
+- </th>
+ <xsl:choose>
+ <xsl:when test="count($next) > 0">
+ <td>
+@@ -534,7 +592,7 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <xsl:with-param name="object" select="$next"/>
+ </xsl:call-template>
+ </xsl:attribute>
+- <img src="right.png" width="24" height="24" border="0">
++ <img src="right.png" width="16" height="16" border="0">
+ <xsl:attribute name="alt">
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key">nav-next</xsl:with-param>
+@@ -545,148 +603,10 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ </td>
+ </xsl:when>
+ <xsl:otherwise>
+- <td>&#160;</td>
++ <td><img src="right-insensitive.png" width="16" height="16" border="0"/></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ </tr>
+- <!--<xsl:if test="name()='refentry'"-->
+- <xsl:choose>
+- <xsl:when test="count($refsections) > 0">
+- <tr>
+- <td colspan="5" class="shortcuts">
+- <xsl:if test="count($sect_synopsis) > 0">
+- <a href="#{$section_id}.synopsis" class="shortcut">Top</a>
+- </xsl:if>
+- <xsl:if test="count($sect_desc) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.description" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='desc']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_object_hierarchy) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.object-hierarchy" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='object_hierarchy']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_impl_interfaces) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.implemented-interfaces" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='impl_interfaces']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_prerequisites) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.prerequisites" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='prerequisites']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_derived_interfaces) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.derived-interfaces" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='derived_interfaces']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_implementations) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.implementations" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='implementations']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_properties) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.properties" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='properties']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_child_properties) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.child-properties" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='child_properties']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_style_properties) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.style-properties" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='style_properties']/title"/>
+- </a>
+- </xsl:if>
+- <xsl:if test="count($sect_signal_proto) > 0">
+- &#160;|&#160;
+- <a href="#{$section_id}.signals" class="shortcut">
+- <xsl:value-of select="./refsect1[@role='signal_proto']/title"/>
+- </a>
+- </xsl:if>
+- <!--
+- <xsl:if test="count($sect_details) > 0">
+- <a href="#details" class="shortcut">
+- <xsl:value-of select="./refsect1[@id='details']/title"/>
+- </a>
+- &#160;|&#160;
+- </xsl:if>
+- <xsl:if test="count($sect_property_details) > 0">
+- <a href="#property_details" class="shortcut">
+- <xsl:value-of select="./refsect1[@id='property_details']/title"/>
+- </a>
+- &#160;|&#160;
+- </xsl:if>
+- <xsl:if test="count($sect_child_property_details) > 0">
+- <a href="#child_property_details" class="shortcut">
+- <xsl:value-of select="./refsect1[@id='property_child_details']/title"/>
+- </a>
+- &#160;|&#160;
+- </xsl:if>
+- <xsl:if test="count($sect_style_property_details) > 0">
+- <a href="#style_property_details" class="shortcut">
+- <xsl:value-of select="./refsect1[@id='style_property_details']/title"/>
+- </a>
+- &#160;|&#160;
+- </xsl:if>
+- <xsl:if test="count($sect_signals) > 0">
+- <a href="#signals" class="shortcut">
+- <xsl:value-of select="./refsect1[@id='signals']/title"/>
+- </a>
+- &#160;|&#160;
+- </xsl:if>
+- -->
+- </td>
+- </tr>
+- </xsl:when>
+- <!-- this is not yet very nice, as it requires all glossdic/indexdiv
+- elements having a anchor element. maybe we can customize the xsl
+- to automaticaly create local anchors
+- -->
+- <xsl:when test="count($glssections) > 0">
+- <tr>
+- <td colspan="5" class="shortcuts">
+- <xsl:for-each select="./glossdiv">
+- <xsl:if test="position() > 1">
+- &#160;|&#160;
+- </xsl:if>
+- <a class="shortcut">
+- <xsl:attribute name="href">#gls<xsl:value-of select="./title"/></xsl:attribute>
+- <xsl:value-of select="./title"/>
+- </a>
+- </xsl:for-each>
+- </td>
+- </tr>
+- </xsl:when>
+- <xsl:when test="count($idxsections) > 0">
+- <tr>
+- <td colspan="5" class="shortcuts">
+- <xsl:for-each select="./indexdiv/indexdiv">
+- <xsl:if test="position() > 1">
+- &#160;|&#160;
+- </xsl:if>
+- <a class="shortcut">
+- <xsl:attribute name="href">#idx<xsl:value-of select="./title"/></xsl:attribute>
+- <xsl:value-of select="./title"/>
+- </a>
+- </xsl:for-each>
+- </td>
+- </tr>
+- </xsl:when>
+- </xsl:choose>
+ </table>
+ </xsl:if>
+ </xsl:template>
+@@ -758,32 +678,32 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <table width="100%">
+ <tr><td valign="top">
+ <xsl:call-template name="anchor"/>
+- <xsl:choose>
+- <xsl:when test="$refentry.generate.name != 0">
+- <h2>
+- <xsl:call-template name="gentext">
+- <xsl:with-param name="key" select="'RefName'"/>
+- </xsl:call-template>
+- </h2>
+- </xsl:when>
+- <xsl:when test="$refentry.generate.title != 0">
+- <h2>
+- <xsl:choose>
+- <xsl:when test="../refmeta/refentrytitle">
+- <xsl:apply-templates select="../refmeta/refentrytitle"/>
+- </xsl:when>
+- <xsl:otherwise>
+- <xsl:apply-templates select="refname[1]"/>
+- </xsl:otherwise>
+- </xsl:choose>
+- </h2>
+- </xsl:when>
+- </xsl:choose>
+- <p>
++ <xsl:choose>
++ <xsl:when test="$refentry.generate.name != 0">
++ <h2>
++ <xsl:call-template name="gentext">
++ <xsl:with-param name="key" select="'RefName'"/>
++ </xsl:call-template>
++ </h2>
++ </xsl:when>
++ <xsl:when test="$refentry.generate.title != 0">
++ <h2>
++ <xsl:choose>
++ <xsl:when test="../refmeta/refentrytitle">
++ <xsl:apply-templates select="../refmeta/refentrytitle"/>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:apply-templates select="refname[1]"/>
++ </xsl:otherwise>
++ </xsl:choose>
++ </h2>
++ </xsl:when>
++ </xsl:choose>
++ <p>
+ <xsl:apply-templates/>
+ </p>
+ </td>
+- <td valign="top" align="right">
++ <td class="gallery_image" valign="top" align="right">
+ <xsl:choose>
+ <xsl:when test="../refmeta/refmiscinfo/inlinegraphic">
+ <xsl:apply-templates select="../refmeta/refmiscinfo/inlinegraphic"/>
+@@ -795,7 +715,7 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ - use it here
+ -->
+ <xsl:variable name="refentryid" select="../@id"/>
+- <xsl:apply-templates select="key('gallery.key', $refentryid)/inlinegraphic"/>
++ <xsl:apply-templates select="key('gallery.key', $refentryid)/inlinegraphic"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td></tr>
+@@ -803,6 +723,21 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ </div>
+ </xsl:template>
+
++ <!-- a copy from refentry.xsl to add the missing mode attribute,
++ see bug/729911, https://sourceforge.net/p/docbook/bugs/1358/
++ fixed in: https://sourceforge.net/p/docbook/code/9962/
++ -->
++ <xsl:template match="refpurpose" mode="no.anchor.mode">
++ <xsl:if test="node()">
++ <xsl:text> </xsl:text>
++ <xsl:call-template name="dingbat">
++ <xsl:with-param name="dingbat">em-dash</xsl:with-param>
++ </xsl:call-template>
++ <xsl:text> </xsl:text>
++ <xsl:apply-templates mode="no.anchor.mode"/>
++ </xsl:if>
++ </xsl:template>
++
+ <!-- add anchors for index sections -->
+ <xsl:template match="indexdiv">
+ <a><xsl:attribute name="name">idx<xsl:value-of select="./title"/></xsl:attribute></a>
+@@ -825,12 +760,12 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <span class="extralinks">
+ <xsl:for-each select="../ulink[@role='extralinks']">
+ <xsl:if test="position() = 1">[&#160;</xsl:if>
+- <xsl:if test="position() > 1">&#160;|&#160;</xsl:if>
++ <xsl:if test="position() > 1">&#160;&#160;<span class="dim">|</span>&#160;</xsl:if>
+ <a>
+ <xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute>
+ <xsl:copy-of select="text()" />
+ </a>
+- <xsl:if test="position() = last()">&#160;]</xsl:if>
++ <xsl:if test="position() = last()">&#160;&#160;]</xsl:if>
+ </xsl:for-each>
+ </span>
+ </xsl:if>
+@@ -861,11 +796,6 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <xsl:param name="acronym">
+ <xsl:apply-templates/>
+ </xsl:param>
+- <!--
+- We use for-each to change context to the database document because key()
+- only locates elements in the same document as the context node!
+- -->
+-
+ <xsl:param name="value" >
+ <xsl:value-of select="key('acronym.key', $acronym)/../glossdef/para[1]" />
+ </xsl:param>
+@@ -878,7 +808,7 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/
+ <a>
+ <xsl:attribute name="href">
+ <xsl:text>http://foldoc.org/</xsl:text>
+- <xsl:value-of select="$acronym"/>
++ <xsl:value-of select="$acronym"/>
+ </xsl:attribute>
+ <xsl:call-template name="inline.charseq"/>
+ </a>
+diff --git a/doc/manual/realm.xml b/doc/manual/realm.xml
+index 9d9136a..7b73331 100644
+--- a/doc/manual/realm.xml
++++ b/doc/manual/realm.xml
+@@ -49,7 +49,7 @@
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+-<refsect1>
++<refsect1 id="man-description">
+ <title>Description</title>
+ <para><command>realm</command> is a command line tool that
+ can be used to manage enrollment in kerberos realms, like Active
+@@ -81,7 +81,7 @@
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-discover">
+ <title>Discover</title>
+
+ <para>Discover a realm and its capabilities.</para>
+@@ -138,7 +138,7 @@ $ realm discover domain.example.com
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-join">
+ <title>Join</title>
+
+ <para>Configure the local machine for use with a realm.</para>
+@@ -263,7 +263,7 @@ $ realm join --user=admin --computer-ou=OU=Special domain.example.com
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-leave">
+ <title>Leave</title>
+
+ <para>Deconfigure the local machine for use with a realm.</para>
+@@ -313,7 +313,7 @@ $ realm leave domain.example.com
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-list">
+ <title>List</title>
+
+ <para>List all the discovered and configured realms.</para>
+@@ -345,7 +345,7 @@ $ realm list
+ </variablelist>
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-permit">
+ <title>Permit</title>
+
+ <para>Permit local login by users of the realm.</para>
+@@ -392,7 +392,7 @@ $ realm permit --withdraw user@example.com
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="man-deny">
+ <title>Deny</title>
+
+ <para>Deny local login by realm accounts.</para>
+diff --git a/doc/manual/realmd-guide-active-directory.xml b/doc/manual/realmd-guide-active-directory.xml
+index 362cf94..c88e8af 100644
+--- a/doc/manual/realmd-guide-active-directory.xml
++++ b/doc/manual/realmd-guide-active-directory.xml
+@@ -69,7 +69,7 @@ $ <command>realm discover --verbose domain.example.com</command>
+ <ulink url="http://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/winbind.html">Winbind</ulink>.
+ By default SSSD is used.</para>
+
+- <section>
++ <section id="using-sssd-with-active-directory">
+ <title>Using SSSD with Active Directory</title>
+ <para><ulink url="https://fedorahosted.org/sssd/">SSSD</ulink>
+ provides client software for various kerberos and/or LDAP
+@@ -91,7 +91,7 @@ $ <command>realm join --client-software=sssd domain.example.com</command>
+ </informalexample>
+ </section>
+
+- <section>
++ <section id="using-winbind-with-active-directory">
+ <title>Using Winbind with Active Directory</title>
+ <para>Samba
+ <ulink url="http://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/winbind.html">Winbind</ulink>
+diff --git a/doc/manual/realmd-guide-ipa.xml b/doc/manual/realmd-guide-ipa.xml
+index bba6504..c3ad450 100644
+--- a/doc/manual/realmd-guide-ipa.xml
++++ b/doc/manual/realmd-guide-ipa.xml
+@@ -13,7 +13,7 @@
+ users locally, and log into the local machine with IPA domain
+ credentials.</para>
+
+- <section>
++ <section id="discovering-ipa-domains">
+ <title>Discovering IPA domains</title>
+ <para><command>realmd</command> discovers which domains or
+ realms it can use or configure. It can discover and identify
+diff --git a/doc/manual/realmd-guide-kerberos.xml b/doc/manual/realmd-guide-kerberos.xml
+index a57e964..5b9d4b1 100644
+--- a/doc/manual/realmd-guide-kerberos.xml
++++ b/doc/manual/realmd-guide-kerberos.xml
+@@ -12,7 +12,7 @@
+ Since there is no standard way to enroll a computer against a Kerberos
+ server, it is not possible to do this with <command>realmd</command>.</para>
+
+- <section>
++ <section id="discovering-kerberos-realms">
+ <title>Discovering Kerberos realms</title>
+ <para><command>realmd</command> discovers which domains or
+ realms it can use or configure. It can discover and identify
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index a2b577c..f0b0879 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -28,7 +28,7 @@
+ <refpurpose>Tweak behavior of realmd</refpurpose>
+ </refnamediv>
+
+-<refsect1>
++<refsect1 id="realmd-conf-file">
+ <title>Configuration File</title>
+
+ <para><command>realmd</command> can be tweaked by network administrators
+@@ -297,7 +297,7 @@ DOMAIN\user:*:13445:13446:Name:/home/DOMAIN/user:/bin/bash
+
+ </refsect1>
+
+-<refsect1>
++<refsect1 id="realmd-conf-specific-settings">
+ <title>Realm specific settings</title>
+ <para>These options should go in an section with the same name
+ as the realm in the <filename>/etc/realmd.conf</filename> file.
+diff --git a/doc/manual/static/gtk-doc.css b/doc/manual/static/gtk-doc.css
+index 5618926..af6ce9c 100644
+--- a/doc/manual/static/gtk-doc.css
++++ b/doc/manual/static/gtk-doc.css
+@@ -1,15 +1,23 @@
++body
++{
++ font-family: cantarell, sans-serif;
++}
+ .synopsis, .classsynopsis
+ {
+ /* tango:aluminium 1/2 */
+ background: #eeeeec;
+- border: solid 1px #d3d7cf;
++ background: rgba(238, 238, 236, 0.5);
++ border: solid 1px rgb(238, 238, 236);
+ padding: 0.5em;
+ }
+ .programlisting
+ {
+ /* tango:sky blue 0/1 */
++ /* fallback for no rgba support */
+ background: #e6f3ff;
+ border: solid 1px #729fcf;
++ background: rgba(114, 159, 207, 0.1);
++ border: solid 1px rgba(114, 159, 207, 0.2);
+ padding: 0.5em;
+ }
+ .variablelist
+@@ -22,86 +30,8 @@
+ vertical-align: top;
+ }
+
+-@media screen {
+- sup a.footnote
+- {
+- position: relative;
+- top: 0em ! important;
+- }
+- /* this is needed so that the local anchors are displayed below the naviagtion */
+- div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name]
+- {
+- display: inline-block;
+- position: relative;
+- top:-5em;
+- }
+- /* this seems to be a bug in the xsl style sheets when generating indexes */
+- div.index div.index
+- {
+- top: 0em;
+- }
+- /* make space for the fixed navigation bar and add space at the bottom so that
+- * link targets appear somewhat close to top
+- */
+- body
+- {
+- padding-top: 3.2em;
+- padding-bottom: 20em;
+- }
+- /* style and size the navigation bar */
+- table.navigation#top
+- {
+- position: fixed;
+- /* tango:scarlet red 0/1 */
+- background: #ffe6e6;
+- border: solid 1px #ef2929;
+- margin-top: 0;
+- margin-bottom: 0;
+- top: 0;
+- left: 0;
+- height: 3em;
+- z-index: 10;
+- }
+- .navigation a, .navigation a:visited
+- {
+- /* tango:scarlet red 3 */
+- color: #a40000;
+- }
+- .navigation a:hover
+- {
+- /* tango:scarlet red 1 */
+- color: #ef2929;
+- }
+- td.shortcuts
+- {
+- /* tango:scarlet red 1 */
+- color: #ef2929;
+- font-size: 80%;
+- white-space: nowrap;
+- }
+-}
+-@media print {
+- table.navigation {
+- visibility: collapse;
+- display: none;
+- }
+- div.titlepage table.navigation {
+- visibility: visible;
+- display: table;
+- /* tango:scarlet red 0/1 */
+- background: #ffe6e6;
+- border: solid 1px #ef2929;
+- margin-top: 0;
+- margin-bottom: 0;
+- top: 0;
+- left: 0;
+- height: 3em;
+- }
+-}
+-
+-.navigation .title
+-{
+- font-size: 200%;
++span.nowrap {
++ white-space: nowrap;
+ }
+
+ div.gallery-float
+@@ -131,6 +61,72 @@ a:hover
+ color: #729fcf;
+ }
+
++div.informaltable table
++{
++ border-collapse: separate;
++ border-spacing: 1em 0.3em;
++ border: none;
++}
++
++div.informaltable table td, div.informaltable table th
++{
++ vertical-align: top;
++}
++
++.function_type,
++.variable_type,
++.property_type,
++.signal_type,
++.parameter_name,
++.struct_member_name,
++.union_member_name,
++.define_keyword,
++.datatype_keyword,
++.typedef_keyword
++{
++ text-align: right;
++}
++
++/* dim non-primary columns */
++.c_punctuation,
++.function_type,
++.variable_type,
++.property_type,
++.signal_type,
++.define_keyword,
++.datatype_keyword,
++.typedef_keyword,
++.property_flags,
++.signal_flags,
++.parameter_annotations,
++.enum_member_annotations,
++.struct_member_annotations,
++.union_member_annotations
++{
++ color: #888a85;
++}
++
++.function_type a,
++.function_type a:visited,
++.function_type a:hover,
++.property_type a,
++.property_type a:visited,
++.property_type a:hover,
++.signal_type a,
++.signal_type a:visited,
++.signal_type a:hover,
++.signal_flags a,
++.signal_flags a:visited,
++.signal_flags a:hover
++{
++ color: #729fcf;
++}
++
++td p
++{
++ margin: 0.25em;
++}
++
+ div.table table
+ {
+ border-collapse: collapse;
+@@ -153,14 +149,44 @@ div.table table th
+ background-color: #d3d7cf;
+ }
+
++h4
++{
++ color: #555753;
++ margin-top: 1em;
++ margin-bottom: 1em;
++}
++
+ hr
+ {
+- /* tango:aluminium 3 */
+- color: #babdb6;
+- background: #babdb6;
++ /* tango:aluminium 1 */
++ color: #d3d7cf;
++ background: #d3d7cf;
+ border: none 0px;
+ height: 1px;
+ clear: both;
++ margin: 2.0em 0em 2.0em 0em;
++}
++
++dl.toc dt
++{
++ padding-bottom: 0.25em;
++}
++
++dl.toc > dt
++{
++ padding-top: 0.25em;
++ padding-bottom: 0.25em;
++ font-weight: bold;
++}
++
++dl.toc > dl
++{
++ padding-bottom: 0.5em;
++}
++
++.parameter
++{
++ font-style: normal;
+ }
+
+ .footer
+@@ -172,31 +198,70 @@ hr
+ font-size: 80%;
+ }
+
++.informalfigure,
++.figure
++{
++ margin: 1em;
++}
++
++.informalexample,
++.example
++{
++ margin-top: 1em;
++ margin-bottom: 1em;
++}
++
+ .warning
+ {
+ /* tango:orange 0/1 */
+ background: #ffeed9;
++ background: rgba(252, 175, 62, 0.1);
+ border-color: #ffb04f;
++ border-color: rgba(252, 175, 62, 0.2);
+ }
+ .note
+ {
+ /* tango:chameleon 0/0.5 */
+ background: #d8ffb2;
++ background: rgba(138, 226, 52, 0.1);
+ border-color: #abf562;
++ border-color: rgba(138, 226, 52, 0.2);
+ }
+-.note, .warning
++div.blockquote
++{
++ border-color: #eeeeec;
++}
++.note, .warning, div.blockquote
+ {
+ padding: 0.5em;
+ border-width: 1px;
+ border-style: solid;
++ margin: 2em;
+ }
+-.note h3, .warning h3
++.note p, .warning p
+ {
+- margin-top: 0.0em
++ margin: 0;
+ }
+-.note p, .warning p
++
++div.warning h3.title,
++div.note h3.title
++{
++ display: none;
++}
++
++p + div.section
++{
++ margin-top: 1em;
++}
++
++div.refnamediv,
++div.refsynopsisdiv,
++div.refsect1,
++div.refsect2,
++div.toc,
++div.section
+ {
+- margin-bottom: 0.0em
++ margin-bottom: 1em;
+ }
+
+ /* blob links */
+@@ -209,33 +274,52 @@ h2 .extralinks, h3 .extralinks
+ font-weight: normal;
+ }
+
++.lineart
++{
++ color: #d3d7cf;
++ font-weight: normal;
++}
++
+ .annotation
+ {
+ /* tango:aluminium 5 */
+ color: #555753;
+- font-size: 80%;
+ font-weight: normal;
+ }
+
++.structfield
++{
++ font-style: normal;
++ font-weight: normal;
++}
++
++acronym,abbr
++{
++ border-bottom: 1px dotted gray;
++}
++
+ /* code listings */
+
+-.listing_code .programlisting .cbracket { color: #a40000; } /* tango: scarlet red 3 */
+-.listing_code .programlisting .comment { color: #a1a39d; } /* tango: aluminium 4 */
+-.listing_code .programlisting .function { color: #000000; font-weight: bold; }
+-.listing_code .programlisting .function a { color: #11326b; font-weight: bold; } /* tango: sky blue 4 */
+-.listing_code .programlisting .keyword { color: #4e9a06; } /* tango: chameleon 3 */
++.listing_code .programlisting .normal,
++.listing_code .programlisting .normal a,
++.listing_code .programlisting .number,
++.listing_code .programlisting .cbracket,
++.listing_code .programlisting .symbol { color: #555753; }
++.listing_code .programlisting .comment,
+ .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */
+-.listing_code .programlisting .normal { color: #000000; }
+-.listing_code .programlisting .number { color: #75507b; } /* tango: plum 2 */
++.listing_code .programlisting .function,
++.listing_code .programlisting .function a,
+ .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */
+-.listing_code .programlisting .string { color: #c17d11; } /* tango: chocolate 2 */
+-.listing_code .programlisting .type { color: #000000; }
+-.listing_code .programlisting .type a { color: #11326b; } /* tango: sky blue 4 */
+-.listing_code .programlisting .symbol { color: #ce5c00; } /* tango: orange 3 */
++.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */
++.listing_code .programlisting .keyword,
++.listing_code .programlisting .usertype,
++.listing_code .programlisting .type,
++.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */
+
+ .listing_frame {
+ /* tango:sky blue 1 */
+ border: solid 1px #729fcf;
++ border: solid 1px rgba(114, 159, 207, 0.2);
+ padding: 0px;
+ }
+
+@@ -247,18 +331,152 @@ h2 .extralinks, h3 .extralinks
+ .listing_lines {
+ /* tango:sky blue 0.5 */
+ background: #a6c5e3;
++ background: rgba(114, 159, 207, 0.2);
+ /* tango:aluminium 6 */
+ color: #2e3436;
+ }
+ .listing_code {
+ /* tango:sky blue 0 */
+ background: #e6f3ff;
++ background: rgba(114, 159, 207, 0.1);
+ }
+ .listing_code .programlisting {
+ /* override from previous */
+ border: none 0px;
+ padding: 0px;
++ background: none;
+ }
+ .listing_lines pre, .listing_code pre {
+ margin: 0px;
+ }
++
++@media screen {
++ /* these have a <sup> as a first child, but since there are no parent selectors
++ * we can't use that. */
++ a.footnote
++ {
++ position: relative;
++ top: 0em ! important;
++ }
++ /* this is needed so that the local anchors are displayed below the naviagtion */
++ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name]
++ {
++ display: inline-block;
++ position: relative;
++ top:-5em;
++ }
++ /* this seems to be a bug in the xsl style sheets when generating indexes */
++ div.index div.index
++ {
++ top: 0em;
++ }
++ /* make space for the fixed navigation bar and add space at the bottom so that
++ * link targets appear somewhat close to top
++ */
++ body
++ {
++ padding-top: 2.5em;
++ padding-bottom: 500px;
++ max-width: 60em;
++ }
++ p
++ {
++ max-width: 60em;
++ }
++ /* style and size the navigation bar */
++ table.navigation#top
++ {
++ position: fixed;
++ background: #e2e2e2;
++ border-bottom: solid 1px #babdb6;
++ border-spacing: 5px;
++ margin-top: 0;
++ margin-bottom: 0;
++ top: 0;
++ left: 0;
++ z-index: 10;
++ }
++ table.navigation#top td
++ {
++ padding-left: 6px;
++ padding-right: 6px;
++ }
++ .navigation a, .navigation a:visited
++ {
++ /* tango:sky blue 3 */
++ color: #204a87;
++ }
++ .navigation a:hover
++ {
++ /* tango:sky blue 2 */
++ color: #3465a4;
++ }
++ td.shortcuts
++ {
++ /* tango:sky blue 2 */
++ color: #3465a4;
++ font-size: 80%;
++ white-space: nowrap;
++ }
++ td.shortcuts .dim
++ {
++ color: #babdb6;
++ }
++ .navigation .title
++ {
++ font-size: 80%;
++ max-width: none;
++ margin: 0px;
++ font-weight: normal;
++ }
++}
++@media screen and (min-width: 60em) {
++ /* screen larger than 60em */
++ body { margin: auto; }
++}
++@media screen and (max-width: 60em) {
++ /* screen less than 60em */
++ #nav_hierarchy { display: none; }
++ #nav_interfaces { display: none; }
++ #nav_prerequisites { display: none; }
++ #nav_derived_interfaces { display: none; }
++ #nav_implementations { display: none; }
++ #nav_child_properties { display: none; }
++ #nav_style_properties { display: none; }
++ #nav_index { display: none; }
++ #nav_glossary { display: none; }
++ .gallery_image { display: none; }
++ .property_flags { display: none; }
++ .signal_flags { display: none; }
++ .parameter_annotations { display: none; }
++ .enum_member_annotations { display: none; }
++ .struct_member_annotations { display: none; }
++ .union_member_annotations { display: none; }
++ /* now that a column is hidden, optimize space */
++ col.parameters_name { width: auto; }
++ col.parameters_description { width: auto; }
++ col.struct_members_name { width: auto; }
++ col.struct_members_description { width: auto; }
++ col.enum_members_name { width: auto; }
++ col.enum_members_description { width: auto; }
++ col.union_members_name { width: auto; }
++ col.union_members_description { width: auto; }
++ .listing_lines { display: none; }
++}
++@media print {
++ table.navigation {
++ visibility: collapse;
++ display: none;
++ }
++ div.titlepage table.navigation {
++ visibility: visible;
++ display: table;
++ background: #e2e2e2;
++ border: solid 1px #babdb6;
++ margin-top: 0;
++ margin-bottom: 0;
++ top: 0;
++ left: 0;
++ height: 3em;
++ }
++}
+--
+2.25.1
+
diff --git a/0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch b/0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch
new file mode 100644
index 000000000000..8b8f633a8977
--- /dev/null
+++ b/0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch
@@ -0,0 +1,96 @@
+From 402cbab6e8267fcd959bcfa84a47f4871b59944d Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Fri, 28 Oct 2016 20:27:48 +0200
+Subject: [PATCH] service: Add nss and pam sssd.conf services after joining
+
+After adding a domain to sssd.conf add the nss and pam services
+to the [sssd] block.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=98479
+---
+ service/realm-sssd-ad.c | 3 +++
+ service/realm-sssd-config.c | 2 --
+ service/realm-sssd-ipa.c | 3 +++
+ tests/test-sssd-config.c | 4 ++--
+ 4 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/service/realm-sssd-ad.c b/service/realm-sssd-ad.c
+index 5ed384d..5fa81ce 100644
+--- a/service/realm-sssd-ad.c
++++ b/service/realm-sssd-ad.c
+@@ -160,6 +160,7 @@ configure_sssd_for_domain (RealmIniConfig *config,
+ gboolean use_adcli,
+ GError **error)
+ {
++ const gchar *services[] = { "nss", "pam", NULL };
+ GString *realmd_tags;
+ const gchar *access_provider;
+ const gchar *shell;
+@@ -206,6 +207,8 @@ configure_sssd_for_domain (RealmIniConfig *config,
+ "ldap_sasl_authid", authid,
+ NULL);
+
++ realm_ini_config_set_list_diff (config, "sssd", "services", ", ", services, NULL);
++
+ g_free (authid);
+ g_string_free (realmd_tags, TRUE);
+
+diff --git a/service/realm-sssd-config.c b/service/realm-sssd-config.c
+index 2096afd..d4398b9 100644
+--- a/service/realm-sssd-config.c
++++ b/service/realm-sssd-config.c
+@@ -154,8 +154,6 @@ realm_sssd_config_add_domain (RealmIniConfig *config,
+ g_strfreev (already);
+
+ /* Setup a default sssd section */
+- if (!realm_ini_config_have (config, "section", "services"))
+- realm_ini_config_set (config, "sssd", "services", "nss, pam", NULL);
+ if (!realm_ini_config_have (config, "sssd", "config_file_version"))
+ realm_ini_config_set (config, "sssd", "config_file_version", "2", NULL);
+
+diff --git a/service/realm-sssd-ipa.c b/service/realm-sssd-ipa.c
+index b12136e..001870d 100644
+--- a/service/realm-sssd-ipa.c
++++ b/service/realm-sssd-ipa.c
+@@ -156,6 +156,7 @@ on_ipa_client_do_restart (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+ {
++ const gchar *services[] = { "nss", "pam", NULL };
+ GTask *task = G_TASK (user_data);
+ EnrollClosure *enroll = g_task_get_task_data (task);
+ RealmSssd *sssd = g_task_get_source_object (task);
+@@ -207,6 +208,8 @@ on_ipa_client_do_restart (GObject *source,
+ "realmd_tags", realmd_tags,
+ NULL);
+
++ realm_ini_config_set_list_diff (config, "sssd", "services", ", ", services, NULL);
++
+ g_free (home);
+ }
+
+diff --git a/tests/test-sssd-config.c b/tests/test-sssd-config.c
+index 59eab75..892b9d5 100644
+--- a/tests/test-sssd-config.c
++++ b/tests/test-sssd-config.c
+@@ -90,7 +90,7 @@ test_add_domain (Test *test,
+ gconstpointer unused)
+ {
+ const gchar *data = "[domain/one]\nval=1\n[sssd]\ndomains=one";
+- const gchar *check = "[domain/one]\nval=1\n[sssd]\ndomains = one, two\nconfig_file_version = 2\nservices = nss, pam\n\n[domain/two]\ndos = 2\n";
++ const gchar *check = "[domain/one]\nval=1\n[sssd]\ndomains = one, two\nconfig_file_version = 2\n\n[domain/two]\ndos = 2\n";
+ GError *error = NULL;
+ gchar *output;
+ gboolean ret;
+@@ -140,7 +140,7 @@ static void
+ test_add_domain_only (Test *test,
+ gconstpointer unused)
+ {
+- const gchar *check = "\n[sssd]\ndomains = two\nconfig_file_version = 2\nservices = nss, pam\n\n[domain/two]\ndos = 2\n";
++ const gchar *check = "\n[sssd]\ndomains = two\nconfig_file_version = 2\n\n[domain/two]\ndos = 2\n";
+ GError *error = NULL;
+ gchar *output;
+ gboolean ret;
+--
+2.9.3
+
diff --git a/0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch b/0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch
new file mode 100644
index 000000000000..6c44727a2f71
--- /dev/null
+++ b/0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch
@@ -0,0 +1,98 @@
+From 9d5b6f5c88df582fb94edcf5cc05a8cfaa63cf6a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
+Date: Tue, 25 Apr 2017 07:20:17 +0200
+Subject: [PATCH] service: Add "pam" and "nss" services in
+ realm_sssd_config_add_domain()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+realm_sssd_config_add_domain() must setup the services line in sssd.conf
+otherwise SSSD won't be able to start any of its services.
+
+It's a regression caused by 402cbab which leaves SSSD with no services
+line when joining to an ad client doing "realm join ad.example".
+
+https://bugs.freedesktop.org/show_bug.cgi?id=98479
+
+Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
+---
+ service/realm-sssd-ad.c | 3 ++-
+ service/realm-sssd-config.c | 2 ++
+ service/realm-sssd-ipa.c | 3 ++-
+ tests/test-sssd-config.c | 4 ++--
+ 4 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/service/realm-sssd-ad.c b/service/realm-sssd-ad.c
+index 5fa81ce..8543ca8 100644
+--- a/service/realm-sssd-ad.c
++++ b/service/realm-sssd-ad.c
+@@ -207,7 +207,8 @@ configure_sssd_for_domain (RealmIniConfig *config,
+ "ldap_sasl_authid", authid,
+ NULL);
+
+- realm_ini_config_set_list_diff (config, "sssd", "services", ", ", services, NULL);
++ if (ret)
++ ret = realm_ini_config_change_list (config, "sssd", "services", ", ", services, NULL, error);
+
+ g_free (authid);
+ g_string_free (realmd_tags, TRUE);
+diff --git a/service/realm-sssd-config.c b/service/realm-sssd-config.c
+index d4398b9..140d7dc 100644
+--- a/service/realm-sssd-config.c
++++ b/service/realm-sssd-config.c
+@@ -130,6 +130,7 @@ realm_sssd_config_add_domain (RealmIniConfig *config,
+ gchar **already;
+ gboolean ret;
+ gchar *section;
++ const gchar *services[] = { "nss", "pam", NULL };
+ va_list va;
+ gint i;
+
+@@ -154,6 +155,7 @@ realm_sssd_config_add_domain (RealmIniConfig *config,
+ g_strfreev (already);
+
+ /* Setup a default sssd section */
++ realm_ini_config_set_list_diff (config, "sssd", "services", ", ", services, NULL);
+ if (!realm_ini_config_have (config, "sssd", "config_file_version"))
+ realm_ini_config_set (config, "sssd", "config_file_version", "2", NULL);
+
+diff --git a/service/realm-sssd-ipa.c b/service/realm-sssd-ipa.c
+index 001870d..ff1dc8a 100644
+--- a/service/realm-sssd-ipa.c
++++ b/service/realm-sssd-ipa.c
+@@ -208,7 +208,8 @@ on_ipa_client_do_restart (GObject *source,
+ "realmd_tags", realmd_tags,
+ NULL);
+
+- realm_ini_config_set_list_diff (config, "sssd", "services", ", ", services, NULL);
++ if (error == NULL)
++ realm_ini_config_change_list (config, "sssd", "services", ", ", services, NULL, &error);
+
+ g_free (home);
+ }
+diff --git a/tests/test-sssd-config.c b/tests/test-sssd-config.c
+index 892b9d5..59eab75 100644
+--- a/tests/test-sssd-config.c
++++ b/tests/test-sssd-config.c
+@@ -90,7 +90,7 @@ test_add_domain (Test *test,
+ gconstpointer unused)
+ {
+ const gchar *data = "[domain/one]\nval=1\n[sssd]\ndomains=one";
+- const gchar *check = "[domain/one]\nval=1\n[sssd]\ndomains = one, two\nconfig_file_version = 2\n\n[domain/two]\ndos = 2\n";
++ const gchar *check = "[domain/one]\nval=1\n[sssd]\ndomains = one, two\nconfig_file_version = 2\nservices = nss, pam\n\n[domain/two]\ndos = 2\n";
+ GError *error = NULL;
+ gchar *output;
+ gboolean ret;
+@@ -140,7 +140,7 @@ static void
+ test_add_domain_only (Test *test,
+ gconstpointer unused)
+ {
+- const gchar *check = "\n[sssd]\ndomains = two\nconfig_file_version = 2\n\n[domain/two]\ndos = 2\n";
++ const gchar *check = "\n[sssd]\ndomains = two\nconfig_file_version = 2\nservices = nss, pam\n\n[domain/two]\ndos = 2\n";
+ GError *error = NULL;
+ gchar *output;
+ gboolean ret;
+--
+2.9.3
+
diff --git a/0001-switch-to-authselect.patch b/0001-switch-to-authselect.patch
new file mode 100644
index 000000000000..d750d6dbf3bf
--- /dev/null
+++ b/0001-switch-to-authselect.patch
@@ -0,0 +1,36 @@
+From 32645f2fc1ddfb2eed7069fd749602619f26ed37 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Mon, 19 Feb 2018 11:51:06 +0100
+Subject: [PATCH] switch to authselect
+
+---
+ service/realmd-redhat.conf | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/service/realmd-redhat.conf b/service/realmd-redhat.conf
+index e39fad525c716d1ed99715280cd5d497b9039427..26cf6147f352e1b48c3261fa42707d816428f879 100644
+--- a/service/realmd-redhat.conf
++++ b/service/realmd-redhat.conf
+@@ -23,15 +23,15 @@ adcli = /usr/sbin/adcli
+ freeipa-client = /usr/sbin/ipa-client-install
+
+ [commands]
+-winbind-enable-logins = /usr/bin/sh -c "/usr/sbin/authconfig --update --enablewinbind --enablewinbindauth --enablemkhomedir --nostart && /usr/bin/systemctl enable oddjobd.service && /usr/bin/systemctl start oddjobd.service"
+-winbind-disable-logins = /usr/sbin/authconfig --update --disablewinbind --disablewinbindauth --nostart
++winbind-enable-logins = /usr/bin/sh -c "/usr/bin/authselect select winbind with-mkhomedir --force && /usr/bin/systemctl enable oddjobd.service && /usr/bin/systemctl start oddjobd.service"
++winbind-disable-logins = /usr/bin/authselect select sssd with-mkhomedir
+ winbind-enable-service = /usr/bin/systemctl enable winbind.service
+ winbind-disable-service = /usr/bin/systemctl disable winbind.service
+ winbind-restart-service = /usr/bin/systemctl restart winbind.service
+ winbind-stop-service = /usr/bin/systemctl stop winbind.service
+
+-sssd-enable-logins = /usr/bin/sh -c "/usr/sbin/authconfig --update --enablesssd --enablesssdauth --enablemkhomedir --nostart && /usr/bin/systemctl enable oddjobd.service && /usr/bin/systemctl start oddjobd.service"
+-sssd-disable-logins = /usr/sbin/authconfig --update --disablesssdauth --nostart
++sssd-enable-logins = /usr/bin/sh -c "/usr/bin/authselect select sssd with-mkhomedir --force && /usr/bin/systemctl enable oddjobd.service && /usr/bin/systemctl start oddjobd.service"
++sssd-disable-logins = /usr/bin/authselect select sssd with-mkhomedir
+ sssd-enable-service = /usr/bin/systemctl enable sssd.service
+ sssd-disable-service = /usr/bin/systemctl disable sssd.service
+ sssd-restart-service = /usr/bin/systemctl restart sssd.service
+--
+2.9.3
+
diff --git a/0001-tests-ignore-order-in-test_update_domain.patch b/0001-tests-ignore-order-in-test_update_domain.patch
new file mode 100644
index 000000000000..2a84abac57b3
--- /dev/null
+++ b/0001-tests-ignore-order-in-test_update_domain.patch
@@ -0,0 +1,82 @@
+From b6753bd048b4012b11d60c094d1ab6ca181ee50d Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 21 Feb 2019 21:16:26 +0100
+Subject: [PATCH] tests: ignore order in test_update_domain
+
+Individual options of a domain or in general for a section in an ini
+file are stored by realmd in a hash table. When writing out the ini file
+the options can show up in any order and the unit tests should be aware
+of it.
+
+Resolves: https://gitlab.freedesktop.org/realmd/realmd/issues/19
+---
+ tests/test-sssd-config.c | 41 ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 39 insertions(+), 2 deletions(-)
+
+diff --git a/tests/test-sssd-config.c b/tests/test-sssd-config.c
+index 59eab75..8f3fec5 100644
+--- a/tests/test-sssd-config.c
++++ b/tests/test-sssd-config.c
+@@ -163,12 +163,49 @@ test_add_domain_only (Test *test,
+ g_free (output);
+ }
+
++static void check_for_test_update_domain (char *new)
++{
++ char *token;
++ char *saveptr;
++ size_t c;
++ int result = 0;
++
++ token = strtok_r (new, "\n", &saveptr);
++ g_assert_nonnull (token);
++ g_assert_cmpstr (token, ==, "[domain/one]");
++
++ for (c = 0; c < 3; c++) {
++ token = strtok_r (NULL, "\n", &saveptr);
++ g_assert_nonnull (token);
++ if (strcmp (token, "val=1") == 0) {
++ result += 1;
++ } else if (strcmp (token, "uno = 1") == 0) {
++ result += 2;
++ } else if (strcmp (token, "eins = one") == 0) {
++ result += 4;
++ } else {
++ g_assert_not_reached ();
++ }
++ }
++ g_assert_cmpint (result, ==, 7);
++
++ token = strtok_r (NULL, "\n", &saveptr);
++ g_assert_nonnull (token);
++ g_assert_cmpstr (token, ==, "[sssd]");
++
++ token = strtok_r (NULL, "\n", &saveptr);
++ g_assert_nonnull (token);
++ g_assert_cmpstr (token, ==, "domains=one");
++
++ token = strtok_r (NULL, "\n", &saveptr);
++ g_assert_null (token);
++}
++
+ static void
+ test_update_domain (Test *test,
+ gconstpointer unused)
+ {
+ const gchar *data = "[domain/one]\nval=1\n[sssd]\ndomains=one";
+- const gchar *check = "[domain/one]\nval=1\nuno = 1\neins = one\n[sssd]\ndomains=one";
+ GError *error = NULL;
+ gchar *output;
+ gboolean ret;
+@@ -190,7 +227,7 @@ test_update_domain (Test *test,
+ g_assert_no_error (error);
+ g_assert (ret == TRUE);
+
+- g_assert_cmpstr (check, ==, output);
++ check_for_test_update_domain (output);
+ g_free (output);
+ }
+
+--
+2.20.1
+
diff --git a/0001-tests-run-tests-with-python3.patch b/0001-tests-run-tests-with-python3.patch
new file mode 100644
index 000000000000..607afa44655a
--- /dev/null
+++ b/0001-tests-run-tests-with-python3.patch
@@ -0,0 +1,374 @@
+From c257850912897a07e20f205faecf3c1b692fa9e9 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 4 Jul 2018 16:41:16 +0200
+Subject: [PATCH] tests: run tests with python3
+
+To allow the test to run with python3 build/tap-driver and
+build/tap-gtester are updated to the latest version provided by the
+cockpit project https://github.com/cockpit-project/cockpit.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1595813
+---
+ build/tap-driver | 104 +++++++++++++++++++++++++++++++++++++++++++-----------
+ build/tap-gtester | 59 ++++++++++++++++++++++---------
+ 2 files changed, 125 insertions(+), 38 deletions(-)
+
+diff --git a/build/tap-driver b/build/tap-driver
+index 42f57c8..241fd50 100755
+--- a/build/tap-driver
++++ b/build/tap-driver
+@@ -1,4 +1,5 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
++# This can also be run with Python 2.
+
+ # Copyright (C) 2013 Red Hat, Inc.
+ #
+@@ -29,20 +30,58 @@
+ #
+
+ import argparse
++import fcntl
+ import os
+ import select
++import struct
+ import subprocess
+ import sys
++import termios
++import errno
++
++_PY3 = sys.version[0] >= '3'
++_str = _PY3 and str or unicode
++
++def out(data, stream=None, flush=False):
++ if not isinstance(data, bytes):
++ data = data.encode("UTF-8")
++ if not stream:
++ stream = _PY3 and sys.stdout.buffer or sys.stdout
++ while True:
++ try:
++ if data:
++ stream.write(data)
++ data = None
++ if flush:
++ stream.flush()
++ flush = False
++ break
++ except IOError as e:
++ if e.errno == errno.EAGAIN:
++ continue
++ raise
++
++def terminal_width():
++ try:
++ h, w, hp, wp = struct.unpack('HHHH',
++ fcntl.ioctl(1, termios.TIOCGWINSZ,
++ struct.pack('HHHH', 0, 0, 0, 0)))
++ return w
++ except IOError as e:
++ if e.errno != errno.ENOTTY:
++ sys.stderr.write("%i %s %s\n" % (e.errno, e.strerror, sys.exc_info()))
++ return sys.maxsize
+
+ class Driver:
+ def __init__(self, args):
+ self.argv = args.command
+ self.test_name = args.test_name
+- self.log = open(args.log_file, "w")
+- self.log.write("# %s\n" % " ".join(sys.argv))
++ self.log = open(args.log_file, "wb")
++ self.log.write(("# %s\n" % " ".join(sys.argv)).encode("UTF-8"))
+ self.trs = open(args.trs_file, "w")
+ self.color_tests = args.color_tests
+ self.expect_failure = args.expect_failure
++ self.width = terminal_width() - 9
+
+ def report(self, code, *args):
+ CODES = {
+@@ -57,17 +96,18 @@ class Driver:
+ # Print out to console
+ if self.color_tests:
+ if code in CODES:
+- sys.stdout.write(CODES[code])
+- sys.stdout.write(code)
++ out(CODES[code])
++ out(code)
+ if self.color_tests:
+- sys.stdout.write('\x1b[m')
+- sys.stdout.write(": ")
+- sys.stdout.write(self.test_name)
+- sys.stdout.write(" ")
+- for arg in args:
+- sys.stdout.write(str(arg))
+- sys.stdout.write("\n")
+- sys.stdout.flush()
++ out('\x1b[m')
++ out(": ")
++ msg = "".join([ self.test_name + " " ] + list(map(_str, args)))
++ if code == "PASS" and len(msg) > self.width:
++ out(msg[:self.width])
++ out("...")
++ else:
++ out(msg)
++ out("\n", flush=True)
+
+ # Book keeping
+ if code in CODES:
+@@ -100,12 +140,14 @@ class Driver:
+ def execute(self):
+ try:
+ proc = subprocess.Popen(self.argv, close_fds=True,
++ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+- except OSError, ex:
++ except OSError as ex:
+ self.report_error("Couldn't run %s: %s" % (self.argv[0], str(ex)))
+ return
+
++ proc.stdin.close()
+ outf = proc.stdout.fileno()
+ errf = proc.stderr.fileno()
+ rset = [outf, errf]
+@@ -113,18 +155,25 @@ class Driver:
+ ret = select.select(rset, [], [], 10)
+ if outf in ret[0]:
+ data = os.read(outf, 1024)
+- if data == "":
++ if data == b"":
+ rset.remove(outf)
+ self.log.write(data)
+ self.process(data)
+ if errf in ret[0]:
+ data = os.read(errf, 1024)
+- if data == "":
++ if data == b"":
+ rset.remove(errf)
+ self.log.write(data)
+- sys.stderr.write(data)
++ stream = _PY3 and sys.stderr.buffer or sys.stderr
++ out(data, stream=stream, flush=True)
+
+ proc.wait()
++
++ # Make sure the test didn't change blocking output
++ assert fcntl.fcntl(0, fcntl.F_GETFL) & os.O_NONBLOCK == 0
++ assert fcntl.fcntl(1, fcntl.F_GETFL) & os.O_NONBLOCK == 0
++ assert fcntl.fcntl(2, fcntl.F_GETFL) & os.O_NONBLOCK == 0
++
+ return proc.returncode
+
+
+@@ -137,6 +186,7 @@ class TapDriver(Driver):
+ self.late_plan = False
+ self.errored = False
+ self.bail_out = False
++ self.skip_all_reason = None
+
+ def report(self, code, num, *args):
+ if num:
+@@ -170,13 +220,19 @@ class TapDriver(Driver):
+ else:
+ self.result_fail(num, description)
+
+- def consume_test_plan(self, first, last):
++ def consume_test_plan(self, line):
+ # Only one test plan is supported
+ if self.test_plan:
+ self.report_error("Get a second TAP test plan")
+ return
+
++ if line.lower().startswith('1..0 # skip'):
++ self.skip_all_reason = line[5:].strip()
++ self.bail_out = True
++ return
++
+ try:
++ (first, unused, last) = line.partition("..")
+ first = int(first)
+ last = int(last)
+ except ValueError:
+@@ -192,7 +248,7 @@ class TapDriver(Driver):
+
+ def process(self, output):
+ if output:
+- self.output += output
++ self.output += output.decode("UTF-8")
+ elif self.output:
+ self.output += "\n"
+ (ready, unused, self.output) = self.output.rpartition("\n")
+@@ -202,8 +258,7 @@ class TapDriver(Driver):
+ elif line.startswith("not ok "):
+ self.consume_test_line(False, line[7:])
+ elif line and line[0].isdigit() and ".." in line:
+- (first, unused, last) = line.partition("..")
+- self.consume_test_plan(first, last)
++ self.consume_test_plan(line)
+ elif line.lower().startswith("bail out!"):
+ self.consume_bail_out(line)
+
+@@ -213,6 +268,13 @@ class TapDriver(Driver):
+ failed = False
+ skipped = True
+
++ if self.skip_all_reason is not None:
++ self.result_skip("skipping:", self.skip_all_reason)
++ self.trs.write(":global-test-result: SKIP\n")
++ self.trs.write(":test-global-result: SKIP\n")
++ self.trs.write(":recheck: no\n")
++ return 0
++
+ # Basic collation of results
+ for (num, code) in self.reported.items():
+ if code == "ERROR":
+diff --git a/build/tap-gtester b/build/tap-gtester
+index 7e667d4..bbda266 100755
+--- a/build/tap-gtester
++++ b/build/tap-gtester
+@@ -1,4 +1,5 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
++# This can also be run with Python 2.
+
+ # Copyright (C) 2014 Red Hat, Inc.
+ #
+@@ -30,9 +31,19 @@
+ import argparse
+ import os
+ import select
++import signal
+ import subprocess
+ import sys
+
++# Yes, it's dumb, but strsignal is not exposed in python
++# In addition signal numbers varify heavily from arch to arch
++def strsignal(sig):
++ for name in dir(signal):
++ if name.startswith("SIG") and sig == getattr(signal, name):
++ return name
++ return str(sig)
++
++
+ class NullCompiler:
+ def __init__(self, command):
+ self.command = command
+@@ -76,22 +87,22 @@ class GTestCompiler(NullCompiler):
+ elif cmd == "result":
+ if self.test_name:
+ if data == "OK":
+- print "ok %d %s" % (self.test_num, self.test_name)
++ print("ok %d %s" % (self.test_num, self.test_name))
+ if data == "FAIL":
+- print "not ok %d %s", (self.test_num, self.test_name)
++ print("not ok %d %s" % (self.test_num, self.test_name))
+ self.test_name = None
+ elif cmd == "skipping":
+ if "/subprocess" not in data:
+- print "ok %d # skip -- %s" % (self.test_num, data)
++ print("ok %d # skip -- %s" % (self.test_num, data))
+ self.test_name = None
+ elif data:
+- print "# %s: %s" % (cmd, data)
++ print("# %s: %s" % (cmd, data))
+ else:
+- print "# %s" % cmd
++ print("# %s" % cmd)
+ elif line.startswith("(MSG: "):
+- print "# %s" % line[6:-1]
++ print("# %s" % line[6:-1])
+ elif line:
+- print "# %s" % line
++ print("# %s" % line)
+ sys.stdout.flush()
+
+ def run(self, proc, output=""):
+@@ -106,22 +117,26 @@ class GTestCompiler(NullCompiler):
+ if line.startswith("/"):
+ self.test_remaining.append(line.strip())
+ if not self.test_remaining:
+- print "Bail out! No tests found in GTest: %s" % self.command[0]
++ print("Bail out! No tests found in GTest: %s" % self.command[0])
+ return 0
+
+- print "1..%d" % len(self.test_remaining)
++ print("1..%d" % len(self.test_remaining))
+
+ # First try to run all the tests in a batch
+- proc = subprocess.Popen(self.command + ["--verbose" ], close_fds=True, stdout=subprocess.PIPE)
++ proc = subprocess.Popen(self.command + ["--verbose" ], close_fds=True,
++ stdout=subprocess.PIPE, universal_newlines=True)
+ result = self.process(proc)
+ if result == 0:
+ return 0
+
++ if result < 0:
++ sys.stderr.write("%s terminated with %s\n" % (self.command[0], strsignal(-result)))
++
+ # Now pick up any stragglers due to failures
+ while True:
+ # Assume that the last test failed
+ if self.test_name:
+- print "not ok %d %s" % (self.test_num, self.test_name)
++ print("not ok %d %s" % (self.test_num, self.test_name))
+ self.test_name = None
+
+ # Run any tests which didn't get run
+@@ -129,7 +144,8 @@ class GTestCompiler(NullCompiler):
+ break
+
+ proc = subprocess.Popen(self.command + ["--verbose", "-p", self.test_remaining[0]],
+- close_fds=True, stdout=subprocess.PIPE)
++ close_fds=True, stdout=subprocess.PIPE,
++ universal_newlines=True)
+ result = self.process(proc)
+
+ # The various exit codes and signals we continue for
+@@ -139,24 +155,32 @@ class GTestCompiler(NullCompiler):
+ return result
+
+ def main(argv):
+- parser = argparse.ArgumentParser(description='Automake TAP compiler')
++ parser = argparse.ArgumentParser(description='Automake TAP compiler',
++ usage="tap-gtester [--format FORMAT] command ...")
+ parser.add_argument('--format', metavar='FORMAT', choices=[ "auto", "gtest", "tap" ],
+ default="auto", help='The input format to compile')
+ parser.add_argument('--verbose', action='store_true',
+ default=True, help='Verbose mode (ignored)')
+- parser.add_argument('command', nargs='+', help="A test command to run")
++ parser.add_argument('command', nargs=argparse.REMAINDER, help="A test command to run")
+ args = parser.parse_args(argv[1:])
+
+ output = None
+ format = args.format
+ cmd = args.command
++ if not cmd:
++ sys.stderr.write("tap-gtester: specify a command to run\n")
++ return 2
++ if cmd[0] == '--':
++ cmd.pop(0)
++
+ proc = None
+
+ os.environ['HARNESS_ACTIVE'] = '1'
+
+ if format in ["auto", "gtest"]:
+ list_cmd = cmd + ["-l", "--verbose"]
+- proc = subprocess.Popen(list_cmd, close_fds=True, stdout=subprocess.PIPE)
++ proc = subprocess.Popen(list_cmd, close_fds=True, stdout=subprocess.PIPE,
++ universal_newlines=True)
+ output = proc.stdout.readline()
+ # Smell whether we're dealing with GTest list output from first line
+ if "random seed" in output or "GTest" in output or output.startswith("/"):
+@@ -164,7 +188,8 @@ def main(argv):
+ else:
+ format = "tap"
+ else:
+- proc = subprocess.Popen(cmd, close_fds=True, stdout=subprocess.PIPE)
++ proc = subprocess.Popen(cmd, close_fds=True, stdout=subprocess.PIPE,
++ universal_newlines=True)
+
+ if format == "gtest":
+ compiler = GTestCompiler(cmd)
+--
+2.14.4
+
diff --git a/0002-Change-qualified-names-default-for-IPA.patch b/0002-Change-qualified-names-default-for-IPA.patch
new file mode 100644
index 000000000000..4ac6c6d413d9
--- /dev/null
+++ b/0002-Change-qualified-names-default-for-IPA.patch
@@ -0,0 +1,113 @@
+From 21ab1fdd127d242a9b4e95c3c90dd2bf3159d149 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 14 Aug 2018 16:44:39 +0200
+Subject: [PATCH 2/3] Change qualified names default for IPA
+
+In a FreeIPA domain it is typically expected that the IPA accounts use
+sort names while accounts from trusted domains have fully qualified
+names. This is automatically done by SSSD's IPA provider so there is no
+need to force fully qualified names in the SSSD configuration.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1575538
+---
+ service/realm-options.c | 9 +++++----
+ service/realm-options.h | 3 ++-
+ service/realm-samba-winbind.c | 2 +-
+ service/realm-sssd-ad.c | 2 +-
+ service/realm-sssd-ipa.c | 2 +-
+ 5 files changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/service/realm-options.c b/service/realm-options.c
+index bd804ea..34a209f 100644
+--- a/service/realm-options.c
++++ b/service/realm-options.c
+@@ -98,7 +98,7 @@ realm_options_automatic_mapping (GVariant *options,
+
+ if (realm_name && !option) {
+ section = g_utf8_casefold (realm_name, -1);
+- mapping = realm_settings_boolean (realm_name, REALM_DBUS_OPTION_AUTOMATIC_ID_MAPPING, TRUE);
++ mapping = realm_settings_boolean (section, REALM_DBUS_OPTION_AUTOMATIC_ID_MAPPING, TRUE);
+ g_free (section);
+ }
+
+@@ -112,20 +112,21 @@ realm_options_automatic_join (const gchar *realm_name)
+ gboolean mapping;
+
+ section = g_utf8_casefold (realm_name, -1);
+- mapping = realm_settings_boolean (realm_name, "automatic-join", FALSE);
++ mapping = realm_settings_boolean (section, "automatic-join", FALSE);
+ g_free (section);
+
+ return mapping;
+ }
+
+ gboolean
+-realm_options_qualify_names (const gchar *realm_name)
++realm_options_qualify_names (const gchar *realm_name,
++ gboolean def)
+ {
+ gchar *section;
+ gboolean qualify;
+
+ section = g_utf8_casefold (realm_name, -1);
+- qualify = realm_settings_boolean (realm_name, "fully-qualified-names", TRUE);
++ qualify = realm_settings_boolean (section, "fully-qualified-names", def);
+ g_free (section);
+
+ return qualify;
+diff --git a/service/realm-options.h b/service/realm-options.h
+index 7a1355e..b71d219 100644
+--- a/service/realm-options.h
++++ b/service/realm-options.h
+@@ -37,7 +37,8 @@ const gchar * realm_options_user_principal (GVariant *options,
+ gboolean realm_options_automatic_mapping (GVariant *options,
+ const gchar *realm_name);
+
+-gboolean realm_options_qualify_names (const gchar *realm_name);
++gboolean realm_options_qualify_names (const gchar *realm_name,
++ gboolean def);
+
+ gboolean realm_options_check_domain_name (const gchar *domain_name);
+
+diff --git a/service/realm-samba-winbind.c b/service/realm-samba-winbind.c
+index 9335e26..61988eb 100644
+--- a/service/realm-samba-winbind.c
++++ b/service/realm-samba-winbind.c
+@@ -102,7 +102,7 @@ realm_samba_winbind_configure_async (RealmIniConfig *config,
+ "winbind enum groups", "no",
+ "winbind offline logon", "yes",
+ "winbind refresh tickets", "yes",
+- "winbind use default domain", realm_options_qualify_names (domain_name )? "no" : "yes",
++ "winbind use default domain", realm_options_qualify_names (domain_name, TRUE )? "no" : "yes",
+ "template shell", realm_settings_string ("users", "default-shell"),
+ NULL);
+
+diff --git a/service/realm-sssd-ad.c b/service/realm-sssd-ad.c
+index 8543ca8..de7ce30 100644
+--- a/service/realm-sssd-ad.c
++++ b/service/realm-sssd-ad.c
+@@ -172,7 +172,7 @@ configure_sssd_for_domain (RealmIniConfig *config,
+ gchar *home;
+
+ home = realm_sssd_build_default_home (realm_settings_string ("users", "default-home"));
+- qualify = realm_options_qualify_names (disco->domain_name);
++ qualify = realm_options_qualify_names (disco->domain_name, TRUE);
+ shell = realm_settings_string ("users", "default-shell");
+ explicit_computer_name = realm_options_computer_name (options, disco->domain_name);
+ realmd_tags = g_string_new ("");
+diff --git a/service/realm-sssd-ipa.c b/service/realm-sssd-ipa.c
+index ff1dc8a..5029f6b 100644
+--- a/service/realm-sssd-ipa.c
++++ b/service/realm-sssd-ipa.c
+@@ -201,7 +201,7 @@ on_ipa_client_do_restart (GObject *source,
+
+ realm_sssd_config_update_domain (config, domain, &error,
+ "cache_credentials", "True",
+- "use_fully_qualified_names", realm_options_qualify_names (domain) ? "True" : "False",
++ "use_fully_qualified_names", realm_options_qualify_names (domain, FALSE) ? "True" : "False",
+ "krb5_store_password_if_offline", "True",
+ "default_shell", shell,
+ "fallback_homedir", home,
+--
+2.17.1
+
diff --git a/0002-configure-do-not-inherit-DISTRO-from-the-environment.patch b/0002-configure-do-not-inherit-DISTRO-from-the-environment.patch
new file mode 100644
index 000000000000..addff4cae319
--- /dev/null
+++ b/0002-configure-do-not-inherit-DISTRO-from-the-environment.patch
@@ -0,0 +1,32 @@
+From 506887297ea33339d8ad8b274be643d220bf22f8 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 28 Nov 2019 18:51:30 +0100
+Subject: [PATCH 2/7] configure: do not inherit DISTRO from the environment
+
+The argument of the --with-distro configure option is stored in the
+variable DISTRO. If DISTRO is already set in the build environment it
+should not be used hence DISTRO must be cleared by the configure script
+if not set by --with-distro.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1638396
+---
+ configure.ac | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index e335247..a424a49 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -31,7 +31,8 @@ AC_ARG_WITH([distro],
+ [AS_HELP_STRING([--with-distro],
+ [Configure for a specific distribution (eg: redhat)]
+ )],
+- [DISTRO=$withval])
++ [DISTRO=$withval],
++ [DISTRO=])
+
+ if test -z $DISTRO; then
+ AC_CHECK_FILE(/etc/redhat-release, [DISTRO="redhat"])
+--
+2.25.1
+
diff --git a/0002-tools-remove-duplicated-va_start.patch b/0002-tools-remove-duplicated-va_start.patch
new file mode 100644
index 000000000000..4d1441cad2db
--- /dev/null
+++ b/0002-tools-remove-duplicated-va_start.patch
@@ -0,0 +1,25 @@
+From 6b41b3292bb826d90fd7986e4a66b20b6fb658b3 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 10:39:13 +0200
+Subject: [PATCH 2/7] tools: remove duplicated va_start()
+
+---
+ tools/realm.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/tools/realm.c b/tools/realm.c
+index ed8ab3e..4d76a94 100644
+--- a/tools/realm.c
++++ b/tools/realm.c
+@@ -52,8 +52,6 @@ realm_print_error (const gchar *format,
+ GString *message;
+ va_list va;
+
+- va_start (va, format);
+-
+ message = g_string_new ("");
+ g_string_append_printf (message, "%s: ", g_get_prgname ());
+
+--
+2.25.1
+
diff --git a/0003-discover-try-to-get-domain-name-from-hostname.patch b/0003-discover-try-to-get-domain-name-from-hostname.patch
new file mode 100644
index 000000000000..b611d6c8ada8
--- /dev/null
+++ b/0003-discover-try-to-get-domain-name-from-hostname.patch
@@ -0,0 +1,76 @@
+From 5e28cf702ad338e399f8fff0b3fa18736a297318 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 21 Aug 2018 13:09:20 +0200
+Subject: [PATCH 3/3] discover: try to get domain name from hostname
+
+If there is no domain name returned by DHCP check if the hostname
+contains a domain part and use this to discover a realm.
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1619162
+---
+ service/realm-provider.c | 28 +++++++++++++++++++++++++++-
+ 1 file changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/service/realm-provider.c b/service/realm-provider.c
+index d647c7a..258e8e1 100644
+--- a/service/realm-provider.c
++++ b/service/realm-provider.c
+@@ -28,6 +28,8 @@
+ #include <glib/gi18n.h>
+ #include <gio/gio.h>
+
++#include <errno.h>
++
+ #define TIMEOUT_SECONDS 15
+
+ G_DEFINE_TYPE (RealmProvider, realm_provider, G_TYPE_DBUS_OBJECT_SKELETON);
+@@ -181,6 +183,25 @@ on_discover_complete (GObject *source,
+ return_discover_result (method, realms, relevance, error);
+ }
+
++static gchar *
++get_domain_from_hostname (void)
++{
++ gchar hostname[HOST_NAME_MAX + 1];
++ gchar *dot;
++
++ if (gethostname (hostname, sizeof (hostname)) < 0) {
++ g_warning ("Couldn't get the computer host name: %s", g_strerror (errno));
++ return NULL;
++ }
++
++ dot = strchr (hostname, '.');
++ if (dot != NULL) {
++ return g_strdup (dot + 1);
++ }
++
++ return NULL;
++}
++
+ static void
+ on_discover_default (GObject *source,
+ GAsyncResult *result,
+@@ -195,6 +216,10 @@ on_discover_default (GObject *source,
+ g_clear_error (&error);
+ }
+
++ if (method->string == NULL) {
++ method->string = get_domain_from_hostname ();
++ }
++
+ if (method->string) {
+ g_strstrip (method->string);
+ if (g_str_equal (method->string, "")) {
+@@ -210,7 +235,8 @@ on_discover_default (GObject *source,
+ on_discover_complete, method);
+
+ } else {
+- realm_diagnostics_info (method->invocation, "No default domain received via DHCP");
++ realm_diagnostics_info (method->invocation,
++ "No default domain received via DHCP or given by hostname");
+ return_discover_result (method, NULL, 0, NULL);
+ }
+ }
+--
+2.17.1
+
diff --git a/0003-doc-extend-user-principal-section.patch b/0003-doc-extend-user-principal-section.patch
new file mode 100644
index 000000000000..6384944d124c
--- /dev/null
+++ b/0003-doc-extend-user-principal-section.patch
@@ -0,0 +1,75 @@
+From d6d1ce2f8b1c81903115b018973c61fc71235b7b Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 29 Nov 2019 18:10:03 +0100
+Subject: [PATCH 3/7] doc: extend user-principal section
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1643814
+---
+ doc/manual/realm.xml | 21 +++++++++++++++++++--
+ doc/manual/realmd.conf.xml | 15 ++++++++++-----
+ 2 files changed, 29 insertions(+), 7 deletions(-)
+
+diff --git a/doc/manual/realm.xml b/doc/manual/realm.xml
+index 7b73331..55a7640 100644
+--- a/doc/manual/realm.xml
++++ b/doc/manual/realm.xml
+@@ -238,10 +238,27 @@ $ realm join --user=admin --computer-ou=OU=Special domain.example.com
+ </varlistentry>
+ <varlistentry>
+ <term><option>--user-principal=<parameter>host/name@REALM</parameter></option></term>
+- <listitem><para>Set the userPrincipalName field of the
++ <listitem><para>Set the
++ <option>userPrincipalName</option> field of the
+ computer account to this kerberos principal. If you omit
+ the value for this option, then a principal will be set
+- in the form of <literal>host/shortname@REALM</literal></para></listitem>
++ based on the defaults of the membership software.</para>
++ <para>AD makes a distinction between user and service
++ principals. Only with user principals you can request a
++ Kerberos Ticket-Granting-Ticket (TGT), i.e. only user
++ principals can be used with the <command>kinit</command>
++ command. By default the user principal and the canonical
++ principal name of an AD computer account is
++ <code>shortname$@AD.DOMAIN</code>, where shortname is
++ the NetBIOS name which is limited to 15 characters.</para>
++ <para>If there are applications which are not aware of
++ the AD default and are using a hard-coded default
++ principal the <option>--user-principal</option> can be
++ used to make AD aware of this principal. Please note
++ that <option>userPrincipalName</option> is a single
++ value LDAP attribute, i.e. only one alternative user
++ principal besides the AD default user principal can be
++ set.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--os-name=xxx</option></term>
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index f0b0879..a26a60c 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -365,12 +365,17 @@ computer-name = SERVER01
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+- <term><option>user-prinicpal</option></term>
++ <term><option>user-principal</option></term>
+ <listitem>
+- <para>Set the <option>user-prinicpal</option> to <code>yes</code>
+- to create <option>userPrincipalName</option> attributes for the
+- computer account in the realm, in the form
+- <code>host/computer@REALM</code></para>
++ <para>Set the <option>user-principal</option> to <code>yes</code>
++ to create <option>userPrincipalName</option> attribute for the
++ computer accounts in the realm. The exact value depends on the
++ defaults of the used membership software. To have full control
++ over the value please use the
++ <option>--user-principal</option> option of the
++ <command>realm</command> command, see
++ <citerefentry><refentrytitle>realm</refentrytitle>
++ <manvolnum>8</manvolnum></citerefentry> for details.</para>
+
+ <informalexample>
+ <programlisting language="js">
+--
+2.25.1
+
diff --git a/0003-service-remove-dead-code.patch b/0003-service-remove-dead-code.patch
new file mode 100644
index 000000000000..82061cff6b32
--- /dev/null
+++ b/0003-service-remove-dead-code.patch
@@ -0,0 +1,33 @@
+From 4cd0cc0ace4a346444dd34e7f3c6a23fd654fef4 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 11:00:13 +0200
+Subject: [PATCH 3/7] service: remove dead code
+
+---
+ service/realm-samba.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/service/realm-samba.c b/service/realm-samba.c
+index 5cf2aa8..e2a3608 100644
+--- a/service/realm-samba.c
++++ b/service/realm-samba.c
+@@ -180,7 +180,6 @@ on_join_do_winbind (GObject *source,
+ GTask *task = G_TASK (user_data);
+ EnrollClosure *enroll = g_task_get_task_data (task);
+ RealmSamba *self = g_task_get_source_object (task);
+- GHashTable *settings = NULL;
+ GError *error = NULL;
+ const gchar *name;
+ const gchar *computer_name;
+@@ -215,8 +214,6 @@ on_join_do_winbind (GObject *source,
+ g_task_return_error (task, error);
+ }
+
+- if (settings)
+- g_hash_table_unref (settings);
+ g_object_unref (task);
+ }
+
+--
+2.25.1
+
diff --git a/0004-doc-fix-discover-name-only.patch b/0004-doc-fix-discover-name-only.patch
new file mode 100644
index 000000000000..36667126062b
--- /dev/null
+++ b/0004-doc-fix-discover-name-only.patch
@@ -0,0 +1,26 @@
+From 878e40f5a3b50d37a0ed981a4f0872a9d5d99e6b Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 29 Nov 2019 18:49:15 +0100
+Subject: [PATCH 4/7] doc: fix discover name-only
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1625001
+---
+ doc/manual/realmd.conf.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index a26a60c..fc6a785 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -308,7 +308,7 @@ DOMAIN\user:*:13445:13446:Name:/home/DOMAIN/user:/bin/bash
+
+ <informalexample>
+ <screen>
+-$ <command>realm discover --name DOMAIN.example.com</command>
++$ <command>realm discover --name-only DOMAIN.example.com</command>
+ domain.example.com
+ ...
+ </screen>
+--
+2.25.1
+
diff --git a/0004-service-check-return-value-of-fcntl.patch b/0004-service-check-return-value-of-fcntl.patch
new file mode 100644
index 000000000000..a274de822f53
--- /dev/null
+++ b/0004-service-check-return-value-of-fcntl.patch
@@ -0,0 +1,36 @@
+From f4636827818d514ebc2f73df2a55b22e7bc8ab89 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 11:00:30 +0200
+Subject: [PATCH 4/7] service: check return value of fcntl()
+
+---
+ service/realm-command.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/service/realm-command.c b/service/realm-command.c
+index 2fe02ab..5257caa 100644
+--- a/service/realm-command.c
++++ b/service/realm-command.c
+@@ -361,6 +361,7 @@ on_unix_process_child_setup (gpointer user_data)
+ int *child_fds = user_data;
+ long val;
+ guint i;
++ int ret;
+
+ /*
+ * Become a process leader in order to close the controlling terminal.
+@@ -378,7 +379,10 @@ on_unix_process_child_setup (gpointer user_data)
+ for (i = 0; i < NUM_FDS; i++) {
+ if (child_fds[i] >= 0) {
+ val = fcntl (child_fds[i], F_GETFD);
+- fcntl (child_fds[i], F_SETFD, val & ~FD_CLOEXEC);
++ ret = fcntl (child_fds[i], F_SETFD, val & ~FD_CLOEXEC);
++ if (ret != 0) {
++ /* ignore */
++ }
+ }
+ }
+ }
+--
+2.25.1
+
diff --git a/0005-doc-add-see-also-to-man-pages.patch b/0005-doc-add-see-also-to-man-pages.patch
new file mode 100644
index 000000000000..788dbc8cb3cd
--- /dev/null
+++ b/0005-doc-add-see-also-to-man-pages.patch
@@ -0,0 +1,46 @@
+From 799821650c538754aae842d400df75d3bd8864bf Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 29 Nov 2019 18:49:51 +0100
+Subject: [PATCH 5/7] doc: add see also to man pages
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1625001
+---
+ doc/manual/realm.xml | 7 +++++++
+ doc/manual/realmd.conf.xml | 7 +++++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/doc/manual/realm.xml b/doc/manual/realm.xml
+index 55a7640..e5d4608 100644
+--- a/doc/manual/realm.xml
++++ b/doc/manual/realm.xml
+@@ -440,4 +440,11 @@ $ realm deny --all
+
+ </refsect1>
+
++<refsect1 id='realm_see_also'>
++ <title>SEE ALSO</title>
++
++ <para><citerefentry><refentrytitle>realmd.conf</refentrytitle>
++ <manvolnum>5</manvolnum></citerefentry></para>
++</refsect1>
++
+ </refentry>
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index fc6a785..1592291 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -471,4 +471,11 @@ fully-qualified-names = no
+ </variablelist>
+ </refsect1>
+
++<refsect1 id='realmd_conf_see_also'>
++ <title>SEE ALSO</title>
++
++ <para><citerefentry><refentrytitle>realm</refentrytitle>
++ <manvolnum>8</manvolnum></citerefentry></para>
++</refsect1>
++
+ </refentry>
+--
+2.25.1
+
diff --git a/0005-service-avoid-dereference-of-a-null-pointer.patch b/0005-service-avoid-dereference-of-a-null-pointer.patch
new file mode 100644
index 000000000000..76f3acfc5543
--- /dev/null
+++ b/0005-service-avoid-dereference-of-a-null-pointer.patch
@@ -0,0 +1,39 @@
+From 7a1711b180a746ba574bdbfc814ec706a474cda8 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 11:07:03 +0200
+Subject: [PATCH 5/7] service: avoid dereference of a null pointer
+
+---
+ service/realm-kerberos.c | 2 +-
+ service/realm-provider.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/service/realm-kerberos.c b/service/realm-kerberos.c
+index 252e256..a8b3553 100644
+--- a/service/realm-kerberos.c
++++ b/service/realm-kerberos.c
+@@ -720,7 +720,7 @@ realm_kerberos_get_disco (RealmKerberos *self)
+ if (!disco->kerberos_realm)
+ disco->kerberos_realm = g_strdup (realm_kerberos_get_realm_name (self));
+ klass = REALM_KERBEROS_GET_CLASS (self);
+- if (klass->discover_myself)
++ if (klass && klass->discover_myself)
+ (klass->discover_myself) (self, disco);
+ self->pv->disco = disco;
+ }
+diff --git a/service/realm-provider.c b/service/realm-provider.c
+index 258e8e1..6d7cf96 100644
+--- a/service/realm-provider.c
++++ b/service/realm-provider.c
+@@ -450,7 +450,7 @@ realm_provider_get_realms (RealmProvider *self)
+
+ g_return_val_if_fail (REALM_IS_PROVIDER (self), NULL);
+ klass = REALM_PROVIDER_GET_CLASS (self);
+- g_return_val_if_fail (klass->get_realms != NULL, NULL);
++ g_return_val_if_fail (klass != NULL && klass->get_realms != NULL, NULL);
+
+ return (klass->get_realms) (self);
+ }
+--
+2.25.1
+
diff --git a/0006-doc-extend-description-of-config-handling.patch b/0006-doc-extend-description-of-config-handling.patch
new file mode 100644
index 000000000000..d0b4ed835d25
--- /dev/null
+++ b/0006-doc-extend-description-of-config-handling.patch
@@ -0,0 +1,104 @@
+From 98a69ca00e3441128b181b59c06bb06e8c362360 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 29 Nov 2019 21:57:02 +0100
+Subject: [PATCH 6/7] doc: extend description of config handling
+
+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1625005
+---
+ doc/manual/Makefile.am | 8 ++++++++
+ doc/manual/realmd.conf.xml | 15 +++++++++++----
+ doc/privatedir.xml.in | 1 +
+ 4 files changed, 21 insertions(+), 4 deletions(-)
+ create mode 100644 doc/privatedir.xml.in
+
+diff --git a/doc/manual/Makefile.am b/doc/manual/Makefile.am
+index 8b33fdd..9812c45 100644
+--- a/doc/manual/Makefile.am
++++ b/doc/manual/Makefile.am
+@@ -1,14 +1,20 @@
++XSLTPROC_FLAGS = --path $(abs_builddir):$(abs_srcdir):$(abs_builddir)/doc
+
+ man8_MANS += \
+ doc/manual/realm.8
+ man5_MANS += \
+ doc/manual/realmd.conf.5
+
++$(man5_MANS): doc/privatedir.xml
++
+ MAN_IN_FILES = \
+ $(man8_MANS:.8=.xml) \
+ $(man5_MANS:.5=.xml) \
+ $(NULL)
+
++doc/privatedir.xml: doc/privatedir.xml.in
++ $(V_SED) $(MKDIR_P) $(dir $@) && $(SED_SUBST) $< > $@
++
+ MANUAL_DOCBOOK = doc/manual/realmd-docs.xml
+
+ MANUAL_INCLUDES = \
+@@ -41,6 +47,7 @@ MANUAL_XSLT = \
+ $(NULL)
+
+ EXTRA_DIST += \
++ doc/privatedir.xml.in \
+ $(MANUAL_DOCBOOK) \
+ $(MANUAL_INCLUDES) \
+ $(MAN_IN_FILES) \
+@@ -50,6 +57,7 @@ EXTRA_DIST += \
+
+ CLEANFILES += \
+ realmd-org.freedesktop.realmd.generated \
++ doc/privatedir.xml \
+ $(DBUS_DOC_GENERATED) \
+ $(DBUS_ESCAPED) \
+ $(man8_MANS) \
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index 1592291..9062252 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -1,6 +1,9 @@
+ <?xml version='1.0'?>
+ <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
++[
++<!ENTITY privatedir SYSTEM "privatedir.xml">
++]>
+
+ <refentry id="realmd-conf">
+
+@@ -35,7 +38,9 @@
+ to act in specific ways. This is done by placing settings in a
+ <filename>/etc/realmd.conf</filename>. This file does not exist by
+ default. The syntax of this file is the same as an INI file or
+- Desktop Entry file.</para>
++ Desktop Entry file. If the file is changed and
++ <command>realmd</command> is running <command>realmd</command> must be
++ restarted to read the new values.</para>
+
+ <para>In general, settings in this file only apply at the point of
+ joining a domain or realm. Once the realm has been setup the settings
+@@ -46,8 +51,10 @@
+
+ <para>Only specify the settings you wish to override in the
+ <filename>/etc/realmd.conf</filename> file. Settings not specified will
+- be loaded from their packaged defaults. Only override the settings
+- below. You may find other settings if you look through the
++ be loaded from their packaged defaults which can be found in
++ <filename>&privatedir;/realmd-defaults.conf</filename> and
++ <filename>&privatedir;/realmd-distro.conf</filename>. Only override the
++ settings below. You may find other settings if you look through the
+ <command>realmd</command> source code. However these are not guaranteed
+ to remain stable.</para>
+
+diff --git a/doc/privatedir.xml.in b/doc/privatedir.xml.in
+new file mode 100644
+index 0000000..7f71afe
+--- /dev/null
++++ b/doc/privatedir.xml.in
+@@ -0,0 +1 @@
++@privatedir@
+\ No newline at end of file
+--
+2.25.1
+
diff --git a/0006-service-avoid-dereferencing-a-NULL-pointer.patch b/0006-service-avoid-dereferencing-a-NULL-pointer.patch
new file mode 100644
index 000000000000..7936bf08a074
--- /dev/null
+++ b/0006-service-avoid-dereferencing-a-NULL-pointer.patch
@@ -0,0 +1,24 @@
+From 9675cc5b6318f848ddf7237d50d02606e16d8003 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Sep 2018 11:17:07 +0200
+Subject: [PATCH 6/7] service: avoid dereferencing a NULL pointer
+
+---
+ service/realm-kerberos.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/service/realm-kerberos.c b/service/realm-kerberos.c
+index a8b3553..3294932 100644
+--- a/service/realm-kerberos.c
++++ b/service/realm-kerberos.c
+@@ -251,6 +251,7 @@ is_credential_supported (RealmKerberosMembershipIface *iface,
+ gboolean found = FALSE;
+ gint i;
+
++ g_assert (iface != NULL);
+ g_assert (iface->join_creds != NULL);
+ g_assert (iface->leave_creds != NULL);
+
+--
+2.25.1
+
diff --git a/0007-service-use-kerberos-method-secrets-and-keytab.patch b/0007-service-use-kerberos-method-secrets-and-keytab.patch
new file mode 100644
index 000000000000..fa1bfcf3f4d8
--- /dev/null
+++ b/0007-service-use-kerberos-method-secrets-and-keytab.patch
@@ -0,0 +1,30 @@
+From 517fa766782421302da827278ca17e6b2ad57da3 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 21 Feb 2020 14:06:16 +0100
+Subject: [PATCH 7/7] service: use "kerberos method" "secrets and keytab"
+
+When using Samba with Winbind the host password stored in secrets.tdb is
+still important so the "secrets and keytab" should be the preferred
+"kerberos method".
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1801195
+---
+ service/realm-samba.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/service/realm-samba.c b/service/realm-samba.c
+index e2a3608..4940b38 100644
+--- a/service/realm-samba.c
++++ b/service/realm-samba.c
+@@ -200,7 +200,7 @@ on_join_do_winbind (GObject *source,
+ "template shell", realm_settings_string ("users", "default-shell"),
+ "netbios name", computer_name,
+ "password server", enroll->disco->explicit_server,
+- "kerberos method", "system keytab",
++ "kerberos method", "secrets and keytab",
+ NULL);
+ }
+
+--
+2.25.1
+
diff --git a/PKGBUILD b/PKGBUILD
index ed56abd93727..66494dea73bc 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -3,7 +3,7 @@
pkgname=realmd
pkgver=0.16.3
-pkgrel=1
+pkgrel=2
pkgdesc="DBus service for joining hosts to Active Directory and FreeIPA realms"
arch=(i686 x86_64)
url="https://freedesktop.org/software/realmd/"
@@ -13,19 +13,89 @@ optdepends=('sssd: Active Directory, FreeIPA, LDAP client'
'samba: traditional Active Directory client')
makedepends=(docbook-xsl git intltool python xmlto)
source=("https://www.freedesktop.org/software/realmd/releases/$pkgname-$pkgver.tar.gz"
- "https://www.freedesktop.org/software/realmd/releases/$pkgname-$pkgver.tar.gz.sig")
+ "https://www.freedesktop.org/software/realmd/releases/$pkgname-$pkgver.tar.gz.sig"
+ 0001-Add-missing-xsl-file-to-Makefile.am.patch
+ 0001-doc-make-sure-cross-reference-ids-are-predictable.patch
+ 0001-Find-NetBIOS-name-in-keytab-while-leaving.patch
+ 0001-Fix-issues-found-by-Coverity.patch
+ 0001-Fix-man-page-reference-in-systemd-service-file.patch
+ 0001-IPA-do-not-call-sssd-enable-logins.patch
+ 0001-Kerberos-fall-back-to-tcp-SRV-lookup.patch
+ 0001-LDAP-don-t-close-LDAP-socket-twice.patch
+ 0001-Remove-support-for-deprecated-gtester-format.patch
+ 0001-service-Add-nss-and-pam-sssd.conf-services-after-joi.patch
+ 0001-service-Add-pam-and-nss-services-in-realm_sssd_confi.patch
+ 0001-Set-NEWEST-flag-when-resolving-packages-with-Package.patch
+ 0001-switch-to-authselect.patch
+ 0001-tests-ignore-order-in-test_update_domain.patch
+ 0001-tests-run-tests-with-python3.patch
+ 0001-Use-current-idmap-options-for-smb.conf.patch
+ 0002-Change-qualified-names-default-for-IPA.patch
+ 0002-configure-do-not-inherit-DISTRO-from-the-environment.patch
+ 0002-tools-remove-duplicated-va_start.patch
+ 0003-discover-try-to-get-domain-name-from-hostname.patch
+ 0003-doc-extend-user-principal-section.patch
+ 0003-service-remove-dead-code.patch
+ 0004-doc-fix-discover-name-only.patch
+ 0004-service-check-return-value-of-fcntl.patch
+ 0005-doc-add-see-also-to-man-pages.patch
+ 0005-service-avoid-dereference-of-a-null-pointer.patch
+ 0006-doc-extend-description-of-config-handling.patch
+ 0006-service-avoid-dereferencing-a-NULL-pointer.patch
+ 0007-service-use-kerberos-method-secrets-and-keytab.patch
+ computer-ou.patch
+ duplicate-test-path.patch
+ install-diagnostic.patch)
sha256sums=('d8943f66a2a666fee8be026d82a66904c0a5125aab7ef74504456ce269687dda'
- 'SKIP')
+ 'SKIP'
+ '6db7704e9342efd801ec24949f1002a8e26ac67c4f04638ca51977940ef3ac1d'
+ 'ea5a2b311f76ebfea0c88c2cf333c007ea5db32316935bbd5dd6883450edd5a3'
+ 'faffd409b53b46c67d4f776e252e49025a63f9963796e12ef6f487d416310958'
+ '262764b9acbe2c84348d8f9a7b759bd08d10c04ef779c4f390c3f6650ef6d96a'
+ 'cb376d3b6e90be4aa84a1d42d4d395f5a8f0aedfbf719277e549f08928e3a985'
+ '2c79e27e504d24b22a06bce567a3aa96348e1bb0682db4e042c96165f799c500'
+ 'a56748ad07b75e346dccedead2ec50053bfe3c3084f9c804b8fae6d961977236'
+ '65f4b0d4d8f51e55e9adc5b8d2896a3abf159f311fc9d3a99ae2df906181e04d'
+ '440ae6ac9d7b4e08440dc1382cfc243e28d69dfcf010f8335e3699c40eda9d63'
+ 'f25dd08914fb493d8b8e6ff5bd44d8398d0498116a874effb314f2cd6e26446d'
+ '6b3a36fdb36655940194ec0b53dcec7e97a4a79a0427863c8a905ad67c9c1714'
+ '512def4faeaa0cd283161fbb05f2bba16bd2d2373d681a99248e78ede958b0fe'
+ '47d7a73329a7dbb4754ab7bd3ed436799cbd21b4f555a0a0ab50c27944817335'
+ 'f408dc7c2263b01e97b66ec068fc48ba5597a3d13e55a60d26008ae309a7787d'
+ 'f3a584270e3e0d6a76c9aeb1dbf078c864b78d948c3277d6899b0b40f8a58030'
+ '8346081c5a8c1efbd5c33890e530fdd84906d394737a1a2cd5a8e2f5fb4f64b6'
+ 'd93b5ba71204cbcb70bab02bf990068d04d4be1888f23c251e2c512c8bb0caeb'
+ '86640fbf9a7f5d7606529584902dcee96fd13cb50c673d785ec04ab525364119'
+ '1daa4159e6fe20131111112b6127ca823b2355a2ef7895840959168af00a5483'
+ 'e4922a6c16c7fd41a2903a5857876c679fd9c257569fe35a4b08ffaabfd016e7'
+ 'eeca4747df151ab624feeefdeda4274da3703681074f21789a69a2eb73da9ca4'
+ 'd594af102566775b4bb0cf59554c69c20721d7db935ac69a3fbc86f28f1226bc'
+ '6fc569eb9641503352fb5f19cb2c5dd16a0e8c888c7e4ea652b55a8e9e69ff6e'
+ 'a962c7b5f3cf2dba39d16195ad7bb1a9d2db9d2292d74d6e65879c220791b871'
+ '3ef0438e83ec4cefba482435d8c22d69bbb8e93b24032a83ad139481ecbda817'
+ '76e511fe1033f19c8499b4edcc3410eede375ceff968f4ac08cd6333c7e33c2a'
+ '77bad53ed4f36ae51f3c81b0195fb898fa6c9f79a377550f51551423c12dcff0'
+ '682a5f7af3e4bdc0bfa5ed2f7ad654e9d311666995520ae2997898edb9264bdc'
+ '950d252020635b4415551fcf9fcacc06ade8497a639b25661b138341b327ea24'
+ '5e43d034348bdf3cb3f06ebd56d811b3427e43f9220fee9a104f50d3972cb5cd'
+ 'a659dfcf8e4f91123832ae89b9ac92bbcc9ea8d90a698533ca25dff9ec610d90'
+ 'e49fc613594d4fb540f0a562778e2fd45711548cbe3dc9769f5aa0773de16319')
validpgpkeys=('C0F67099B808FB063E2C81117BFB1108D92765AF')
prepare() {
cd "$pkgname-$pkgver"
- AUTOMAKE=automake ACLOCAL=aclocal NOCONFIGURE=1 ./autogen.sh
+ local src
+ for src in "${source[@]}"; do
+ src="${src%%::*}"
+ src="${src##*/}"
+ [[ $src = 0*.patch ]] || continue
+ echo "Applying patch $src..."
+ patch -Np1 < "../$src"
+ done
}
-
build() {
cd "$pkgname-$pkgver"
- ./configure \
+ AUTOMAKE=automake ACLOCAL=aclocal ./configure \
--prefix=/usr \
--sbindir=/usr/bin \
--sysconfdir=/etc \
diff --git a/computer-ou.patch b/computer-ou.patch
new file mode 100644
index 000000000000..39c8fadfd916
--- /dev/null
+++ b/computer-ou.patch
@@ -0,0 +1,894 @@
+From 3db35ad73ec57c8af499a0dcef96ffd4da914236 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Mon, 7 Sep 2015 13:49:10 +0200
+Subject: [PATCH 2/2] service: Fully qualify --computer-ou DN before passing to
+ adcli
+
+This allows us to have a similar behavior for both the Samba and
+adcli membership software.
+---
+ service/Makefile.am | 4 +-
+ service/realm-adcli-enroll.c | 11 +-
+ service/realm-dn-util.c | 239 +++++++++++++++++++++++++++++++++++++++++++
+ service/realm-dn-util.h | 32 ++++++
+ service/realm-samba-enroll.c | 4 +-
+ service/realm-samba-util.c | 172 -------------------------------
+ service/realm-samba-util.h | 29 ------
+ tests/Makefile.am | 16 +--
+ tests/test-dn-util.c | 129 +++++++++++++++++++++++
+ tests/test-samba-ou-format.c | 89 ----------------
+ 11 files changed, 422 insertions(+), 305 deletions(-)
+ create mode 100644 service/realm-dn-util.c
+ create mode 100644 service/realm-dn-util.h
+ delete mode 100644 service/realm-samba-util.c
+ delete mode 100644 service/realm-samba-util.h
+ create mode 100644 tests/test-dn-util.c
+ delete mode 100644 tests/test-samba-ou-format.c
+
+diff --git a/service/Makefile.am b/service/Makefile.am
+index 06a95ef..88ee780 100644
+--- a/service/Makefile.am
++++ b/service/Makefile.am
+@@ -43,6 +43,8 @@ realmd_SOURCES = \
+ service/realm-disco-mscldap.h \
+ service/realm-disco-rootdse.c \
+ service/realm-disco-rootdse.h \
++ service/realm-dn-util.c \
++ service/realm-dn-util.h \
+ service/realm-errors.c \
+ service/realm-errors.h \
+ service/realm-example.c \
+@@ -79,8 +81,6 @@ realmd_SOURCES = \
+ service/realm-samba-enroll.h \
+ service/realm-samba-provider.c \
+ service/realm-samba-provider.h \
+- service/realm-samba-util.c \
+- service/realm-samba-util.h \
+ service/realm-samba-winbind.c \
+ service/realm-samba-winbind.h \
+ service/realm-service.c \
+diff --git a/service/realm-adcli-enroll.c b/service/realm-adcli-enroll.c
+index 7448647..ef1b563 100644
+--- a/service/realm-adcli-enroll.c
++++ b/service/realm-adcli-enroll.c
+@@ -18,6 +18,7 @@
+ #include "realm-command.h"
+ #include "realm-daemon.h"
+ #include "realm-diagnostics.h"
++#include "realm-dn-util.h"
+ #include "realm-errors.h"
+ #include "realm-ini-config.h"
+ #include "realm-options.h"
+@@ -82,6 +83,7 @@ realm_adcli_enroll_join_async (RealmDisco *disco,
+ gchar *ccache_arg = NULL;
+ gchar *upn_arg = NULL;
+ gchar *server_arg = NULL;
++ gchar *ou_arg = NULL;
+
+ g_return_if_fail (cred != NULL);
+ g_return_if_fail (disco != NULL);
+@@ -120,9 +122,13 @@ realm_adcli_enroll_join_async (RealmDisco *disco,
+ }
+
+ computer_ou = realm_options_computer_ou (options, disco->domain_name);
+- if (computer_ou) {
++ if (computer_ou != NULL) {
++ ou_arg = realm_dn_util_build_qualified (computer_ou, disco->domain_name);
+ g_ptr_array_add (args, "--computer-ou");
+- g_ptr_array_add (args, (gpointer)computer_ou);
++ if (ou_arg)
++ g_ptr_array_add (args, ou_arg);
++ else
++ g_ptr_array_add (args, (gpointer)computer_ou);
+ }
+
+ os = realm_settings_value ("active-directory", "os-name");
+@@ -190,6 +196,7 @@ realm_adcli_enroll_join_async (RealmDisco *disco,
+ free (ccache_arg);
+ free (upn_arg);
+ free (server_arg);
++ free (ou_arg);
+ }
+
+ gboolean
+diff --git a/service/realm-dn-util.c b/service/realm-dn-util.c
+new file mode 100644
+index 0000000..85bcdb9
+--- /dev/null
++++ b/service/realm-dn-util.c
+@@ -0,0 +1,239 @@
++/* realmd -- Realm configuration service
++ *
++ * Copyright 2012 Red Hat Inc
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as published
++ * by the Free Software Foundation; either version 2 of the licence or (at
++ * your option) any later version.
++ *
++ * See the included COPYING file for more information.
++ *
++ * Author: Stef Walter <stefw@gnome.org>
++ */
++
++#include "config.h"
++
++#include "realm-dn-util.h"
++
++#include <glib.h>
++
++#include <ldap.h>
++
++static gboolean
++berval_is_string (const struct berval *bv,
++ const gchar *string,
++ gsize length)
++{
++ return (bv->bv_len == length &&
++ g_ascii_strncasecmp (bv->bv_val, string, length) == 0);
++
++}
++
++static gboolean
++berval_case_equals (const struct berval *v1,
++ const struct berval *v2)
++{
++ return (v1->bv_len == v2->bv_len &&
++ g_ascii_strncasecmp (v1->bv_val, v2->bv_val, v1->bv_len) == 0);
++}
++
++static gboolean
++dn_equals_domain (LDAPDN dn,
++ const gchar *domain_dn_str,
++ const gchar *domain)
++{
++ LDAPDN domain_dn;
++ gboolean ret;
++ int rc;
++ gint i, j;
++
++ rc = ldap_str2dn (domain_dn_str, &domain_dn, LDAP_DN_FORMAT_LDAPV3);
++ g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);
++
++ for (i = 0; dn[i] != NULL && domain_dn[i] != NULL; i++) {
++ for (j = 0; dn[i][j] != NULL && domain_dn[i][j] != NULL; j++) {
++ if (!berval_case_equals (&(dn[i][j]->la_attr), &(domain_dn[i][j]->la_attr)) ||
++ !berval_case_equals (&(dn[i][j]->la_value), &(domain_dn[i][j]->la_value)))
++ break;
++ }
++
++ if (dn[i][j] != NULL && domain_dn[i][j] != NULL)
++ break;
++ }
++
++ /* Did we reach end of both DNs? */
++ ret = (dn[i] == NULL && domain_dn[i] == NULL);
++
++ ldap_dnfree (domain_dn);
++
++ return ret;
++}
++
++gchar *
++realm_dn_util_build_samba_ou (const gchar *ldap_dn,
++ const gchar *domain)
++{
++ gchar *domain_dn_str = NULL;
++ GArray *parts;
++ GString *part;
++ gchar **strv;
++ gchar *str;
++ LDAPAVA* ava;
++ gboolean ret;
++ LDAPDN dn;
++ int rc;
++ gint i, j;
++
++ /*
++ * Here we convert a standard LDAP DN to the strange samba net format,
++ * as "documented" here:
++ *
++ * createcomputer=OU Precreate the computer account in a specific OU.
++ * The OU string read from top to bottom without RDNs and delimited by a '/'.
++ * E.g. "createcomputer=Computers/Servers/Unix"
++ * NB: A backslash '\' is used as escape at multiple levels and may
++ * need to be doubled or even quadrupled. It is not used as a separator.
++ */
++
++ /* ldap_str2dn doesn't like empty strings */
++ while (g_ascii_isspace (ldap_dn[0]))
++ ldap_dn++;
++ if (g_str_equal (ldap_dn, ""))
++ return NULL;
++
++ rc = ldap_str2dn (ldap_dn, &dn, LDAP_DN_FORMAT_LDAPV3);
++ if (rc != LDAP_SUCCESS)
++ return NULL;
++
++ ret = TRUE;
++ parts = g_array_new (TRUE, TRUE, sizeof (gchar *));
++
++ for (i = 0; dn[i] != NULL; i++) {
++ ava = dn[i][0];
++
++ /*
++ * Make sure this is a valid DN, we only support one value per
++ * RDN, string values, and must be an OU. DC values are allowed
++ * but only at the end of the DN.
++ */
++
++ if (ava == NULL || dn[i][1] != NULL || !(ava->la_flags & LDAP_AVA_STRING)) {
++ ret = FALSE;
++ break;
++
++ /* A DC, remainder must match the domain */
++ } else if (berval_is_string (&ava->la_attr, "DC", 2)) {
++ rc = ldap_domain2dn (domain, &domain_dn_str);
++ if (rc != LDAP_SUCCESS)
++ ret = FALSE;
++ else
++ ret = dn_equals_domain (dn + i, domain_dn_str, domain);
++ break;
++
++ /* An OU, include */
++ } else if (berval_is_string (&ava->la_attr, "OU", 2)) {
++ part = g_string_sized_new (ava->la_value.bv_len);
++ for (j = 0; j < ava->la_value.bv_len; j++) {
++ switch (ava->la_value.bv_val[j]) {
++ case '\\':
++ g_string_append (part, "\\\\");
++ break;
++ case '/':
++ g_string_append (part, "\\/");
++ break;
++ default:
++ g_string_append_c (part, ava->la_value.bv_val[j]);
++ break;
++ }
++ }
++ str = g_string_free (part, FALSE);
++ g_array_insert_val (parts, 0, str);
++
++ /* Invalid, stop */
++ } else {
++ ret = FALSE;
++ break;
++ }
++ }
++
++ ldap_dnfree (dn);
++ if (domain_dn_str)
++ ldap_memfree (domain_dn_str);
++
++ strv = (gchar **)g_array_free (parts, FALSE);
++ str = NULL;
++
++ /* Loop completed successfully */
++ if (ret)
++ str = g_strjoinv ("/", strv);
++
++ g_strfreev (strv);
++
++ return str;
++}
++
++gchar *
++realm_dn_util_build_qualified (const gchar *ldap_dn,
++ const gchar *domain)
++{
++ gchar *domain_dn_str = NULL;
++ gboolean had_dc = FALSE;
++ gchar *str;
++ LDAPAVA* ava;
++ gboolean ret;
++ LDAPDN dn;
++ int rc;
++ gint i;
++
++ /* ldap_str2dn doesn't like empty strings */
++ while (g_ascii_isspace (ldap_dn[0]))
++ ldap_dn++;
++ if (g_str_equal (ldap_dn, ""))
++ return NULL;
++
++ rc = ldap_str2dn (ldap_dn, &dn, LDAP_DN_FORMAT_LDAPV3);
++ if (rc != LDAP_SUCCESS)
++ return NULL;
++
++ rc = ldap_domain2dn (domain, &domain_dn_str);
++ if (rc != LDAP_SUCCESS) {
++ ldap_dnfree (dn);
++ return NULL;
++ }
++
++ ret = TRUE;
++
++ for (i = 0; dn[i] != NULL; i++) {
++ ava = dn[i][0];
++
++ /*
++ * Make sure this is a valid DN, we only support one value per
++ * RDN, string values. DC values are allowed but only at the end of the DN.
++ */
++
++ if (ava == NULL || dn[i][1] != NULL || !(ava->la_flags & LDAP_AVA_STRING)) {
++ ret = FALSE;
++ break;
++
++ /* A DC, remainder must match the domain */
++ } else if (berval_is_string (&ava->la_attr, "DC", 2)) {
++ had_dc = TRUE;
++ ret = dn_equals_domain (dn + i, domain_dn_str, domain);
++ break;
++ }
++ }
++
++ ldap_dnfree (dn);
++
++ if (!ret)
++ return NULL;
++
++ if (had_dc)
++ str = g_strdup (ldap_dn);
++ else
++ str = g_strdup_printf ("%s,%s", ldap_dn, domain_dn_str);
++
++ ldap_memfree (domain_dn_str);
++ return str;
++}
+diff --git a/service/realm-dn-util.h b/service/realm-dn-util.h
+new file mode 100644
+index 0000000..f5e5e69
+--- /dev/null
++++ b/service/realm-dn-util.h
+@@ -0,0 +1,32 @@
++/* realmd -- Realm configuration service
++ *
++ * Copyright 2012 Red Hat Inc
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as published
++ * by the Free Software Foundation; either version 2 of the licence or (at
++ * your option) any later version.
++ *
++ * See the included COPYING file for more information.
++ *
++ * Author: Stef Walter <stefw@gnome.org>
++ */
++
++#include "config.h"
++
++#ifndef __REALM_DN_UTIL_H__
++#define __REALM_DN_UTIL_H__
++
++#include <gio/gio.h>
++
++G_BEGIN_DECLS
++
++gchar * realm_dn_util_build_samba_ou (const gchar *ldap_dn,
++ const gchar *domain);
++
++gchar * realm_dn_util_build_qualified (const gchar *ldap_dn,
++ const gchar *domain);
++
++G_END_DECLS
++
++#endif /* __REALM_DN_UTIL_H__ */
+diff --git a/service/realm-samba-enroll.c b/service/realm-samba-enroll.c
+index e8739d7..e749764 100644
+--- a/service/realm-samba-enroll.c
++++ b/service/realm-samba-enroll.c
+@@ -18,12 +18,12 @@
+ #include "realm-daemon.h"
+ #include "realm-dbus-constants.h"
+ #include "realm-diagnostics.h"
++#include "realm-dn-util.h"
+ #include "realm-errors.h"
+ #include "realm-options.h"
+ #include "realm-samba-config.h"
+ #include "realm-samba-enroll.h"
+ #include "realm-samba-provider.h"
+-#include "realm-samba-util.h"
+ #include "realm-settings.h"
+
+ #include <glib/gstdio.h>
+@@ -314,7 +314,7 @@ begin_join (GTask *task,
+
+ computer_ou = realm_options_computer_ou (options, join->disco->domain_name);
+ if (computer_ou != NULL) {
+- strange_ou = realm_samba_util_build_strange_ou (computer_ou, join->disco->domain_name);
++ strange_ou = realm_dn_util_build_samba_ou (computer_ou, join->disco->domain_name);
+ if (strange_ou) {
+ if (!g_str_equal (strange_ou, ""))
+ join->join_args[at++] = g_strdup_printf ("createcomputer=%s", strange_ou);
+diff --git a/service/realm-samba-util.c b/service/realm-samba-util.c
+deleted file mode 100644
+index 3f6a53e..0000000
+--- a/service/realm-samba-util.c
++++ /dev/null
+@@ -1,172 +0,0 @@
+-/* realmd -- Realm configuration service
+- *
+- * Copyright 2012 Red Hat Inc
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License as published
+- * by the Free Software Foundation; either version 2 of the licence or (at
+- * your option) any later version.
+- *
+- * See the included COPYING file for more information.
+- *
+- * Author: Stef Walter <stefw@gnome.org>
+- */
+-
+-#include "config.h"
+-
+-#include "realm-samba-util.h"
+-
+-#include <glib.h>
+-
+-#include <ldap.h>
+-
+-static gboolean
+-berval_is_string (const struct berval *bv,
+- const gchar *string,
+- gsize length)
+-{
+- return (bv->bv_len == length &&
+- g_ascii_strncasecmp (bv->bv_val, string, length) == 0);
+-
+-}
+-
+-static gboolean
+-berval_case_equals (const struct berval *v1,
+- const struct berval *v2)
+-{
+- return (v1->bv_len == v2->bv_len &&
+- g_ascii_strncasecmp (v1->bv_val, v2->bv_val, v1->bv_len) == 0);
+-}
+-
+-static gboolean
+-dn_equals_domain (LDAPDN dn,
+- const gchar *domain)
+-{
+- LDAPDN domain_dn;
+- gchar *domain_dn_str;
+- gboolean ret;
+- int rc;
+- gint i, j;
+-
+- rc = ldap_domain2dn (domain, &domain_dn_str);
+- g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);
+-
+- rc = ldap_str2dn (domain_dn_str, &domain_dn, LDAP_DN_FORMAT_LDAPV3);
+- g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);
+-
+- ldap_memfree (domain_dn_str);
+-
+- for (i = 0; dn[i] != NULL && domain_dn[i] != NULL; i++) {
+- for (j = 0; dn[i][j] != NULL && domain_dn[i][j] != NULL; j++) {
+- if (!berval_case_equals (&(dn[i][j]->la_attr), &(domain_dn[i][j]->la_attr)) ||
+- !berval_case_equals (&(dn[i][j]->la_value), &(domain_dn[i][j]->la_value)))
+- break;
+- }
+-
+- if (dn[i][j] != NULL && domain_dn[i][j] != NULL)
+- break;
+- }
+-
+- /* Did we reach end of both DNs? */
+- ret = (dn[i] == NULL && domain_dn[i] == NULL);
+-
+- ldap_dnfree (domain_dn);
+-
+- return ret;
+-}
+-
+-gchar *
+-realm_samba_util_build_strange_ou (const gchar *ldap_dn,
+- const gchar *domain)
+-{
+- GArray *parts;
+- GString *part;
+- gchar **strv;
+- gchar *str;
+- LDAPAVA* ava;
+- gboolean ret;
+- LDAPDN dn;
+- int rc;
+- gint i, j;
+-
+- /*
+- * Here we convert a standard LDAP DN to the strange samba net format,
+- * as "documented" here:
+- *
+- * createcomputer=OU Precreate the computer account in a specific OU.
+- * The OU string read from top to bottom without RDNs and delimited by a '/'.
+- * E.g. "createcomputer=Computers/Servers/Unix"
+- * NB: A backslash '\' is used as escape at multiple levels and may
+- * need to be doubled or even quadrupled. It is not used as a separator.
+- */
+-
+- /* ldap_str2dn doesn't like empty strings */
+- while (g_ascii_isspace (ldap_dn[0]))
+- ldap_dn++;
+- if (g_str_equal (ldap_dn, ""))
+- return NULL;
+-
+- rc = ldap_str2dn (ldap_dn, &dn, LDAP_DN_FORMAT_LDAPV3);
+- if (rc != LDAP_SUCCESS)
+- return NULL;
+-
+- ret = TRUE;
+- parts = g_array_new (TRUE, TRUE, sizeof (gchar *));
+-
+- for (i = 0; dn[i] != NULL; i++) {
+- ava = dn[i][0];
+-
+- /*
+- * Make sure this is a valid DN, we only support one value per
+- * RDN, string values, and must be an OU. DC values are allowed
+- * but only at the end of the DN.
+- */
+-
+- if (ava == NULL || dn[i][1] != NULL || !(ava->la_flags & LDAP_AVA_STRING)) {
+- ret = FALSE;
+- break;
+-
+- /* A DC, remainder must match the domain */
+- } else if (berval_is_string (&ava->la_attr, "DC", 2)) {
+- ret = dn_equals_domain (dn + i, domain);
+- break;
+-
+- /* An OU, include */
+- } else if (berval_is_string (&ava->la_attr, "OU", 2)) {
+- part = g_string_sized_new (ava->la_value.bv_len);
+- for (j = 0; j < ava->la_value.bv_len; j++) {
+- switch (ava->la_value.bv_val[j]) {
+- case '\\':
+- g_string_append (part, "\\\\");
+- break;
+- case '/':
+- g_string_append (part, "\\/");
+- break;
+- default:
+- g_string_append_c (part, ava->la_value.bv_val[j]);
+- break;
+- }
+- }
+- str = g_string_free (part, FALSE);
+- g_array_insert_val (parts, 0, str);
+-
+- /* Invalid, stop */
+- } else {
+- ret = FALSE;
+- break;
+- }
+- }
+-
+- ldap_dnfree (dn);
+-
+- strv = (gchar **)g_array_free (parts, FALSE);
+- str = NULL;
+-
+- /* Loop completed successfully */
+- if (ret)
+- str = g_strjoinv ("/", strv);
+-
+- g_strfreev (strv);
+-
+- return str;
+-}
+diff --git a/service/realm-samba-util.h b/service/realm-samba-util.h
+deleted file mode 100644
+index 2a680e7..0000000
+--- a/service/realm-samba-util.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/* realmd -- Realm configuration service
+- *
+- * Copyright 2012 Red Hat Inc
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License as published
+- * by the Free Software Foundation; either version 2 of the licence or (at
+- * your option) any later version.
+- *
+- * See the included COPYING file for more information.
+- *
+- * Author: Stef Walter <stefw@gnome.org>
+- */
+-
+-#include "config.h"
+-
+-#ifndef __REALM_SAMBA_UTIL_H__
+-#define __REALM_SAMBA_UTIL_H__
+-
+-#include <gio/gio.h>
+-
+-G_BEGIN_DECLS
+-
+-gchar * realm_samba_util_build_strange_ou (const gchar *ldap_dn,
+- const gchar *suffix_dn);
+-
+-G_END_DECLS
+-
+-#endif /* __REALM_SAMBA_UTIL_H__ */
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index ddeba4d..3b05066 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -12,11 +12,11 @@ TEST_LIBS = \
+ $(GLIB_LIBS)
+
+ TEST_PROGS = \
++ test-dn-util \
+ test-ini-config \
+ test-sssd-config \
+ test-safe-format \
+ test-login-name \
+- test-samba-ou-format \
+ test-settings \
+ $(NULL)
+
+@@ -27,6 +27,13 @@ noinst_PROGRAMS += \
+ frob-install-packages \
+ $(NULL)
+
++test_dn_util_SOURCES = \
++ tests/test-dn-util.c \
++ service/realm-dn-util.c \
++ $(NULL)
++test_dn_util_LDADD = $(TEST_LIBS)
++test_dn_util_CFLAGS = $(TEST_CFLAGS)
++
+ test_ini_config_SOURCES = \
+ tests/test-ini-config.c \
+ service/realm-ini-config.c \
+@@ -59,13 +66,6 @@ test_login_name_SOURCES = \
+ test_login_name_LDADD = $(TEST_LIBS)
+ test_login_name_CFLAGS = $(TEST_CFLAGS)
+
+-test_samba_ou_format_SOURCES = \
+- tests/test-samba-ou-format.c \
+- service/realm-samba-util.c \
+- $(NULL)
+-test_samba_ou_format_LDADD = $(TEST_LIBS)
+-test_samba_ou_format_CFLAGS = $(TEST_CFLAGS)
+-
+ test_settings_SOURCES = \
+ tests/test-settings.c \
+ service/realm-settings.c \
+diff --git a/tests/test-dn-util.c b/tests/test-dn-util.c
+new file mode 100644
+index 0000000..c62a40f
+--- /dev/null
++++ b/tests/test-dn-util.c
+@@ -0,0 +1,129 @@
++/* realmd -- Realm configuration service
++ *
++ * Copyright 2012 Red Hat Inc
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as published
++ * by the Free Software Foundation; either version 2 of the licence or (at
++ * your option) any later version.
++ *
++ * See the included COPYING file for more information.
++ *
++ * Author: Stef Walter <stefw@gnome.org>
++ */
++
++#include "config.h"
++
++#include "service/realm-dn-util.h"
++
++#include <glib/gstdio.h>
++
++#include <string.h>
++
++typedef struct {
++ const gchar *ldap_dn;
++ const gchar *domain;
++ const gchar *result;
++} Fixture;
++
++static void
++test_samba_ou_format (gconstpointer user_data)
++{
++ const Fixture *fixture = user_data;
++ gchar *result;
++
++ result = realm_dn_util_build_samba_ou (fixture->ldap_dn, fixture->domain);
++ g_assert_cmpstr (result, ==, fixture->result);
++ g_free (result);
++}
++
++static const Fixture samba_ou_fixtures[] = {
++ { "OU=One", "domain.example.com", "One" },
++ { "OU=One,ou=two", "domain.example.com", "two/One" },
++ { "Ou=One Long,OU=two", "domain.example.com", "two/One Long" },
++ { "Ou=One,OU=two, ou=Three", "domain.example.com", "Three/two/One" },
++ { "Ou=Test/Escape,Ou=Two", "domain.example.com", "Two/Test\\/Escape" },
++ { "Ou=Test\\\\Escape,Ou=Two", "domain.example.com", "Two/Test\\\\Escape" },
++ { "OU=One,DC=domain,dc=example,Dc=COM", "domain.example.com", "One" },
++ { "OU=One,OU=Two Here,DC=domain,dc=example,Dc=COM", "domain.example.com", "Two Here/One" },
++ { "OU=One,OU=Two Here,DC=invalid,Dc=COM", "domain.example.com", NULL },
++ { " ", "domain.example.com", NULL },
++ { "", "domain.example.com", NULL },
++ { "OU", "domain.example.com", NULL },
++ { "OU=One,", "domain.example.com", NULL },
++ { "CN=Unsupported", "domain.example.com", NULL },
++ { "OU=One+CN=Unsupported", "domain.example.com", NULL },
++ { "DC=radi07, DC=segad, DC=lab, DC=sjc, DC=redhat, DC=com", "radi08.segad.lab.sjc.redhat.com", NULL },
++
++};
++
++static void
++test_qualify_dn (gconstpointer user_data)
++{
++ const Fixture *fixture = user_data;
++ gchar *result;
++
++ result = realm_dn_util_build_qualified (fixture->ldap_dn, fixture->domain);
++ g_assert_cmpstr (result, ==, fixture->result);
++ g_free (result);
++}
++
++static const Fixture qualify_fixtures[] = {
++ { "OU=One", "domain.example.com", "OU=One,dc=domain,dc=example,dc=com" },
++ { "OU=One,ou=two", "domain.example.com", "OU=One,ou=two,dc=domain,dc=example,dc=com" },
++ { "Ou=One Long,OU=two", "domain.example.com", "Ou=One Long,OU=two,dc=domain,dc=example,dc=com" },
++ { "OU=One,DC=domain,dc=example,Dc=COM", "domain.example.com", "OU=One,DC=domain,dc=example,Dc=COM" },
++ { "OU=One,OU=Two Here,DC=domain,dc=example,Dc=COM", "domain.example.com", "OU=One,OU=Two Here,DC=domain,dc=example,Dc=COM" },
++ { "OU=One,OU=Two Here,DC=invalid,Dc=COM", "domain.example.com", NULL },
++ { " ", "domain.example.com", NULL },
++ { "", "domain.example.com", NULL },
++ { "OU", "domain.example.com", NULL },
++ { "OU=One,", "domain.example.com", NULL },
++ { "CN=Test", "domain.example.com", "CN=Test,dc=domain,dc=example,dc=com" },
++ { "OU=One+CN=Unsupported", "domain.example.com", NULL },
++ { "DC=radi07, DC=segad, DC=lab, DC=sjc, DC=redhat, DC=com", "radi08.segad.lab.sjc.redhat.com", NULL },
++};
++
++int
++main (int argc,
++ char **argv)
++{
++ gchar *escaped;
++ gchar *name;
++ gint i;
++
++#if !GLIB_CHECK_VERSION(2, 36, 0)
++ g_type_init ();
++#endif
++
++ g_test_init (&argc, &argv, NULL);
++ g_set_prgname ("test-dn-util");
++
++ for (i = 0; i < G_N_ELEMENTS (samba_ou_fixtures); i++) {
++ if (g_str_equal (samba_ou_fixtures[i].ldap_dn, ""))
++ escaped = g_strdup ("_empty_");
++ else
++ escaped = g_strdup (samba_ou_fixtures[i].ldap_dn);
++ g_strdelimit (escaped, ", =\\/", '_');
++ name = g_strdup_printf ("/realmd/samba-ou-format/%s", escaped);
++ g_free (escaped);
++
++ g_test_add_data_func (name, samba_ou_fixtures + i, test_samba_ou_format);
++ g_free (name);
++ }
++
++ for (i = 0; i < G_N_ELEMENTS (qualify_fixtures); i++) {
++ if (g_str_equal (qualify_fixtures[i].ldap_dn, ""))
++ escaped = g_strdup ("_empty_");
++ else
++ escaped = g_strdup (qualify_fixtures[i].ldap_dn);
++ g_strdelimit (escaped, ", =\\/", '_');
++ name = g_strdup_printf ("/realmd/qualify-dn/%s", escaped);
++ g_free (escaped);
++
++ g_test_add_data_func (name, qualify_fixtures + i, test_qualify_dn);
++ g_free (name);
++ }
++
++ return g_test_run ();
++}
+diff --git a/tests/test-samba-ou-format.c b/tests/test-samba-ou-format.c
+deleted file mode 100644
+index 0a482ee..0000000
+--- a/tests/test-samba-ou-format.c
++++ /dev/null
+@@ -1,89 +0,0 @@
+-/* realmd -- Realm configuration service
+- *
+- * Copyright 2012 Red Hat Inc
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License as published
+- * by the Free Software Foundation; either version 2 of the licence or (at
+- * your option) any later version.
+- *
+- * See the included COPYING file for more information.
+- *
+- * Author: Stef Walter <stefw@gnome.org>
+- */
+-
+-#include "config.h"
+-
+-#include "service/realm-samba-util.h"
+-
+-#include <glib/gstdio.h>
+-
+-#include <string.h>
+-
+-typedef struct {
+- const gchar *ldap_dn;
+- const gchar *domain;
+- const gchar *ou_format;
+-} Fixture;
+-
+-static void
+-test_samba_ou_format (gconstpointer user_data)
+-{
+- const Fixture *fixture = user_data;
+- gchar *result;
+-
+- result = realm_samba_util_build_strange_ou (fixture->ldap_dn, fixture->domain);
+- g_assert_cmpstr (result, ==, fixture->ou_format);
+- g_free (result);
+-}
+-
+-static const Fixture samba_ou_fixtures[] = {
+- { "OU=One", "domain.example.com", "One" },
+- { "OU=One,ou=two", "domain.example.com", "two/One" },
+- { "Ou=One Long,OU=two", "domain.example.com", "two/One Long" },
+- { "Ou=One,OU=two, ou=Three", "domain.example.com", "Three/two/One" },
+- { "Ou=Test/Escape,Ou=Two", "domain.example.com", "Two/Test\\/Escape" },
+- { "Ou=Test\\\\Escape,Ou=Two", "domain.example.com", "Two/Test\\\\Escape" },
+- { "OU=One,DC=domain,dc=example,Dc=COM", "domain.example.com", "One" },
+- { "OU=One,OU=Two Here,DC=domain,dc=example,Dc=COM", "domain.example.com", "Two Here/One" },
+- { "OU=One,OU=Two Here,DC=invalid,Dc=COM", "domain.example.com", NULL },
+- { " ", "domain.example.com", NULL },
+- { "", "domain.example.com", NULL },
+- { "OU", "domain.example.com", NULL },
+- { "OU=One,", "domain.example.com", NULL },
+- { "CN=Unsupported", "domain.example.com", NULL },
+- { "OU=One+CN=Unsupported", "domain.example.com", NULL },
+- { "DC=radi07, DC=segad, DC=lab, DC=sjc, DC=redhat, DC=com", "radi08.segad.lab.sjc.redhat.com", NULL },
+-
+-};
+-
+-int
+-main (int argc,
+- char **argv)
+-{
+- gchar *escaped;
+- gchar *name;
+- gint i;
+-
+-#if !GLIB_CHECK_VERSION(2, 36, 0)
+- g_type_init ();
+-#endif
+-
+- g_test_init (&argc, &argv, NULL);
+- g_set_prgname ("test-samba-ou-format");
+-
+- for (i = 0; i < G_N_ELEMENTS (samba_ou_fixtures); i++) {
+- if (g_str_equal (samba_ou_fixtures[i].ldap_dn, ""))
+- escaped = g_strdup ("_empty_");
+- else
+- escaped = g_strdup (samba_ou_fixtures[i].ldap_dn);
+- g_strdelimit (escaped, ", =\\/", '_');
+- name = g_strdup_printf ("/realmd/samba-ou-format/%s", escaped);
+- g_free (escaped);
+-
+- g_test_add_data_func (name, samba_ou_fixtures + i, test_samba_ou_format);
+- g_free (name);
+- }
+-
+- return g_test_run ();
+-}
+--
+2.4.3
+
diff --git a/duplicate-test-path.patch b/duplicate-test-path.patch
new file mode 100644
index 000000000000..5d628379bea3
--- /dev/null
+++ b/duplicate-test-path.patch
@@ -0,0 +1,26 @@
+From ab41e2830d2f7540d58370b5f35f85c2808c1871 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Fri, 11 Sep 2015 12:32:36 +0200
+Subject: [PATCH] tests: Fix duplicate test case path
+
+GLib is now stricter about this
+---
+ tests/test-safe-format.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/test-safe-format.c b/tests/test-safe-format.c
+index 02aa5f1..204e10d 100644
+--- a/tests/test-safe-format.c
++++ b/tests/test-safe-format.c
+@@ -194,7 +194,7 @@ main (int argc,
+ else
+ escaped = g_strdup (fixtures[i].format);
+ g_strdelimit (escaped, " =\\/", '_');
+- name = g_strdup_printf ("/realmd/safe-format/%s", escaped);
++ name = g_strdup_printf ("/realmd/safe-format/%d-%s", i, escaped);
+ g_free (escaped);
+
+ g_test_add_data_func (name, fixtures + i, test_safe_format_string_cb);
+--
+2.4.3
+
diff --git a/install-diagnostic.patch b/install-diagnostic.patch
new file mode 100644
index 000000000000..2dc551ef6c2e
--- /dev/null
+++ b/install-diagnostic.patch
@@ -0,0 +1,29 @@
+From ef0797e5ed116a98cc074a6d4e1d1d6b6e6384db Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Mon, 7 Sep 2015 12:53:02 +0200
+Subject: [PATCH 1/2] service: Fix issue where diagnostics about package
+ install hidden
+
+Due to the recent refactoring the diagnostics about package
+installation were hidden (even when --verbose).
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1258745
+---
+ service/realm-packages.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/service/realm-packages.c b/service/realm-packages.c
+index 9da852c..321921a 100644
+--- a/service/realm-packages.c
++++ b/service/realm-packages.c
+@@ -615,6 +615,7 @@ realm_packages_install_async (const gchar **package_sets,
+ task = g_task_new (NULL, NULL, callback, user_data);
+ install = g_new0 (InstallClosure, 1);
+ install->automatic = realm_options_automatic_install ();
++ install->invocation = invocation ? g_object_ref (invocation) : NULL;
+ install->connection = g_object_ref (connection);
+ g_task_set_task_data (task, install, install_closure_free);
+
+--
+2.4.3
+