Blame SOURCES/0001-Kerberos-add-default_domain-and-udp_preference_limit.patch

3eb28c
From 2fa90caf4ad38541615446b80dbeaccd0d0e6a6f Mon Sep 17 00:00:00 2001
3eb28c
From: Sumit Bose <sbose@redhat.com>
3eb28c
Date: Wed, 28 Oct 2020 13:40:03 +0100
3eb28c
Subject: [PATCH] Kerberos: add default_domain and udp_preference_limit
3eb28c
3eb28c
When joining an Active Directory domain realmd will set the
3eb28c
default_domain and udp_preference_limit in the Kerberos configuration to
3eb28c
avoid errors and make Kerberos handling in the AD domain more easy.
3eb28c
3eb28c
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791016
3eb28c
---
3eb28c
 doc/manual/realmd.conf.xml      |  69 +++++++++++++++++++
3eb28c
 service/Makefile.am             |   2 +
3eb28c
 service/realm-kerberos-config.c | 116 ++++++++++++++++++++++++++++++++
3eb28c
 service/realm-kerberos-config.h |  35 ++++++++++
3eb28c
 service/realm-samba.c           |  12 ++++
3eb28c
 service/realm-sssd-ad.c         |  12 ++++
3eb28c
 service/realmd-debian.conf      |   1 +
3eb28c
 service/realmd-defaults.conf    |   1 +
3eb28c
 service/realmd-redhat.conf      |   1 +
3eb28c
 service/realmd-suse.conf        |   1 +
3eb28c
 10 files changed, 250 insertions(+)
3eb28c
 create mode 100644 service/realm-kerberos-config.c
3eb28c
 create mode 100644 service/realm-kerberos-config.h
3eb28c
3eb28c
diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
3eb28c
index 9062252..97d2e8d 100644
3eb28c
--- a/doc/manual/realmd.conf.xml
3eb28c
+++ b/doc/manual/realmd.conf.xml
3eb28c
@@ -304,6 +304,75 @@ DOMAIN\user:*:13445:13446:Name:/home/DOMAIN/user:/bin/bash
3eb28c
 
3eb28c
 </refsect1>
3eb28c
 
3eb28c
+<refsect1 id="realmd-conf-paths">
3eb28c
+	<title>paths</title>
3eb28c
+
3eb28c
+	<para>These options should go in an <option>[paths]</option>
3eb28c
+	section of the <filename>/etc/realmd.conf</filename> file. Only
3eb28c
+	specify the settings you wish to override.</para>
3eb28c
+
3eb28c
+	<variablelist>
3eb28c
+	<varlistentry>
3eb28c
+	<term><option>krb5.conf</option></term>
3eb28c
+	<listitem>
3eb28c
+		<para>Path to the Kerberos configuration file, typically
3eb28c
+		<filename>/etc/krb5.conf</filename>. It can also be the path of
3eb28c
+		a file included by <filename>/etc/krb5.conf</filename>, e.g.
3eb28c
+		<filename>/etc/krb5.conf.d/realmd_settings</filename>, if the
3eb28c
+		file does not exist if will be created.</para>
3eb28c
+
3eb28c
+		<informalexample>
3eb28c
+<programlisting language="js">
3eb28c
+[paths]
3eb28c
+krb5.conf = /etc/krb5.conf.d/realmd_settings
3eb28c
+
3eb28c
+</programlisting>
3eb28c
+		</informalexample>
3eb28c
+
3eb28c
+		<para>When joining an Active Directory domain
3eb28c
+		<command>realmd</command> will set the
3eb28c
+		<option>default_realm</option> and
3eb28c
+		<option>udp_preference_limit</option> options in the Kerberos
3eb28c
+		configuration:</para>
3eb28c
+
3eb28c
+		<informalexample>
3eb28c
+<programlisting language="js">
3eb28c
+default_realm = DOMAIN.EXAMPLE.COM
3eb28c
+udp_preference_limit = 0
3eb28c
+
3eb28c
+</programlisting>
3eb28c
+		</informalexample>
3eb28c
+
3eb28c
+		<para>The <option>default_realm</option> option is e.g. needed
3eb28c
+		when trying to resolve enterprise principals and makes it more
3eb28c
+		convenient to request Kerberos tickets for users of the default
3eb28c
+		realm. Instead of specifying the whole principal just
3eb28c
+		<command>kinit username</command> can be used.</para>
3eb28c
+
3eb28c
+		<para>With <option>udp_preference_limit = 0</option> always TCP
3eb28c
+		will be used to send Kerberos request to domain controller. This
3eb28c
+		is useful in Active Directory environments because Kerberos will
3eb28c
+		typically switch to TCP after initially starting with UDP
3eb28c
+		because AD Kerberos tickets are often larger than UDP can handle.
3eb28c
+		Using TCP by default will avoid those extra UDP round trips.
3eb28c
+		Additionally it helps to avoid issues with password changes when
3eb28c
+		the DC does not reply soon enough and the client will send a
3eb28c
+		second UDP request. The DC might reply with a reply error to the
3eb28c
+		second request although the original password change request was
3eb28c
+		successful and the client will no know if the request was
3eb28c
+		successful or not. When using TCP this cannot happen because the
3eb28c
+		client will never send a second request but waits on the
3eb28c
+		connection until the server replies.</para>
3eb28c
+
3eb28c
+		<para>Please note that <command>realmd</command> will not remove
3eb28c
+		those options while leaving the domain since they are useful in
3eb28c
+		general. When joining a new domain <command>realmd</command>
3eb28c
+		will of course overwrite <option>default_realm</option>.</para>
3eb28c
+	</listitem>
3eb28c
+	</varlistentry>
3eb28c
+	</variablelist>
3eb28c
+</refsect1>
3eb28c
+
3eb28c
 <refsect1 id="realmd-conf-specific-settings">
3eb28c
 	<title>Realm specific settings</title>
3eb28c
 	<para>These options should go in an section with the same name
3eb28c
diff --git a/service/Makefile.am b/service/Makefile.am
3eb28c
index 88ee780..031cd1d 100644
3eb28c
--- a/service/Makefile.am
3eb28c
+++ b/service/Makefile.am
3eb28c
@@ -57,6 +57,8 @@ realmd_SOURCES = \
3eb28c
 	service/realm-invocation.h \
3eb28c
 	service/realm-kerberos.c \
3eb28c
 	service/realm-kerberos.h \
3eb28c
+	service/realm-kerberos-config.c \
3eb28c
+	service/realm-kerberos-config.h \
3eb28c
 	service/realm-kerberos-membership.c \
3eb28c
 	service/realm-kerberos-membership.h \
3eb28c
 	service/realm-kerberos-provider.c \
3eb28c
diff --git a/service/realm-kerberos-config.c b/service/realm-kerberos-config.c
3eb28c
new file mode 100644
3eb28c
index 0000000..447a452
3eb28c
--- /dev/null
3eb28c
+++ b/service/realm-kerberos-config.c
3eb28c
@@ -0,0 +1,116 @@
3eb28c
+/* realmd -- Realm configuration service
3eb28c
+ *
3eb28c
+ * Copyright 2020 Red Hat Inc
3eb28c
+ *
3eb28c
+ * This program is free software: you can redistribute it and/or modify
3eb28c
+ * it under the terms of the GNU Lesser General Public License as published
3eb28c
+ * by the Free Software Foundation; either version 2 of the licence or (at
3eb28c
+ * your option) any later version.
3eb28c
+ *
3eb28c
+ * See the included COPYING file for more information.
3eb28c
+ *
3eb28c
+ * Author: Sumit Bose <sbose@redhat.com>
3eb28c
+ */
3eb28c
+
3eb28c
+#include "config.h"
3eb28c
+
3eb28c
+#include "realm-ini-config.h"
3eb28c
+#include "realm-kerberos-config.h"
3eb28c
+#include "realm-settings.h"
3eb28c
+
3eb28c
+#include <string.h>
3eb28c
+
3eb28c
+RealmIniConfig *
3eb28c
+realm_kerberos_config_new_with_flags (RealmIniFlags flags,
3eb28c
+                                      GError **error)
3eb28c
+{
3eb28c
+	RealmIniConfig *config;
3eb28c
+	const gchar *filename;
3eb28c
+	GError *err = NULL;
3eb28c
+
3eb28c
+	config = realm_ini_config_new (REALM_INI_LINE_CONTINUATIONS | flags);
3eb28c
+
3eb28c
+	filename = realm_settings_path ("krb5.conf");
3eb28c
+
3eb28c
+	realm_ini_config_read_file (config, filename, &err;;
3eb28c
+
3eb28c
+	if (err != NULL) {
3eb28c
+		/* If the caller wants errors, then don't return an invalid samba config */
3eb28c
+		if (error) {
3eb28c
+			g_propagate_error (error, err);
3eb28c
+			g_object_unref (config);
3eb28c
+			config = NULL;
3eb28c
+
3eb28c
+		/* If the caller doesn't care, then warn but continue */
3eb28c
+		} else {
3eb28c
+			g_warning ("Couldn't load config file: %s: %s", filename,
3eb28c
+			           err->message);
3eb28c
+			g_error_free (err);
3eb28c
+		}
3eb28c
+	}
3eb28c
+
3eb28c
+	return config;
3eb28c
+}
3eb28c
+
3eb28c
+RealmIniConfig *
3eb28c
+realm_kerberos_config_new (GError **error)
3eb28c
+{
3eb28c
+	return realm_kerberos_config_new_with_flags (REALM_INI_NONE, error);
3eb28c
+}
3eb28c
+
3eb28c
+gboolean
3eb28c
+configure_krb5_conf_for_domain (const gchar *realm, GError **error )
3eb28c
+{
3eb28c
+	RealmIniConfig *config;
3eb28c
+	gboolean res;
3eb28c
+	GFile *gfile;
3eb28c
+	GFileInfo *file_info = NULL;
3eb28c
+
3eb28c
+	config = realm_kerberos_config_new (error);
3eb28c
+	if (config == NULL) {
3eb28c
+		return FALSE;
3eb28c
+	}
3eb28c
+
3eb28c
+	/* When writing to a file glib will replace the original file with a
3eb28c
+	 * new one. To make sure permissions and other attributes like e.g.
3eb28c
+	 * SELinux labels stay the same this information is saved before the
3eb28c
+	 * change and applied to the new file afterwards. */
3eb28c
+	gfile = g_file_new_for_path (realm_ini_config_get_filename (config));
3eb28c
+	file_info = g_file_query_info (gfile, "*", 0, NULL, error);
3eb28c
+	g_object_unref (gfile);
3eb28c
+	if (*error != NULL) {
3eb28c
+		g_warning ("Couldn't load file attributes, "
3eb28c
+		           "will continue without: %s: %s",
3eb28c
+		           realm_ini_config_get_filename (config),
3eb28c
+		           (*error)->message);
3eb28c
+		g_clear_error (error);
3eb28c
+	}
3eb28c
+
3eb28c
+	if (!realm_ini_config_begin_change (config, error)) {
3eb28c
+		g_object_unref (config);
3eb28c
+		return FALSE;
3eb28c
+	}
3eb28c
+
3eb28c
+	realm_ini_config_set (config, "libdefaults",
3eb28c
+	                              "default_realm", realm,
3eb28c
+	                              "udp_preference_limit", "0",
3eb28c
+	                               NULL);
3eb28c
+
3eb28c
+	res = realm_ini_config_finish_change (config, error);
3eb28c
+
3eb28c
+	if (file_info != NULL) {
3eb28c
+		gfile = g_file_new_for_path (realm_ini_config_get_filename (config));
3eb28c
+		if (!g_file_set_attributes_from_info (gfile, file_info,
3eb28c
+		                                      0, NULL, error)) {
3eb28c
+			g_warning ("Couldn't set file attributes: %s: %s",
3eb28c
+			           realm_ini_config_get_filename (config),
3eb28c
+			           (*error)->message);
3eb28c
+		}
3eb28c
+		g_object_unref (file_info);
3eb28c
+		g_object_unref (gfile);
3eb28c
+	}
3eb28c
+
3eb28c
+	g_object_unref (config);
3eb28c
+
3eb28c
+	return res;
3eb28c
+}
3eb28c
diff --git a/service/realm-kerberos-config.h b/service/realm-kerberos-config.h
3eb28c
new file mode 100644
3eb28c
index 0000000..791aa98
3eb28c
--- /dev/null
3eb28c
+++ b/service/realm-kerberos-config.h
3eb28c
@@ -0,0 +1,35 @@
3eb28c
+/* realmd -- Realm configuration service
3eb28c
+ *
3eb28c
+ * Copyright 2020 Red Hat Inc
3eb28c
+ *
3eb28c
+ * This program is free software: you can redistribute it and/or modify
3eb28c
+ * it under the terms of the GNU Lesser General Public License as published
3eb28c
+ * by the Free Software Foundation; either version 2 of the licence or (at
3eb28c
+ * your option) any later version.
3eb28c
+ *
3eb28c
+ * See the included COPYING file for more information.
3eb28c
+ *
3eb28c
+ * Author: Sumit Bose <sbose@redhat.com>
3eb28c
+ */
3eb28c
+
3eb28c
+#include "config.h"
3eb28c
+
3eb28c
+#ifndef __REALM_KERBEROS_CONFIG_H__
3eb28c
+#define __REALM_KERBEROS_CONFIG_H__
3eb28c
+
3eb28c
+#include <gio/gio.h>
3eb28c
+
3eb28c
+#include "realm-ini-config.h"
3eb28c
+
3eb28c
+
3eb28c
+RealmIniConfig *    realm_kerberos_config_new                      (GError **error);
3eb28c
+
3eb28c
+RealmIniConfig *    realm_kerberos_config_new_with_flags           (RealmIniFlags flags,
3eb28c
+                                                                    GError **error);
3eb28c
+
3eb28c
+gboolean            configure_krb5_conf_for_domain                 (const gchar *realm,
3eb28c
+                                                                    GError **error );
3eb28c
+
3eb28c
+G_END_DECLS
3eb28c
+
3eb28c
+#endif /* __REALM_KERBEROS_CONFIG_H__ */
3eb28c
diff --git a/service/realm-samba.c b/service/realm-samba.c
3eb28c
index fe33600..e7b80a0 100644
3eb28c
--- a/service/realm-samba.c
3eb28c
+++ b/service/realm-samba.c
3eb28c
@@ -21,6 +21,7 @@
3eb28c
 #include "realm-disco.h"
3eb28c
 #include "realm-errors.h"
3eb28c
 #include "realm-kerberos.h"
3eb28c
+#include "realm-kerberos-config.h"
3eb28c
 #include "realm-kerberos-membership.h"
3eb28c
 #include "realm-options.h"
3eb28c
 #include "realm-packages.h"
3eb28c
@@ -210,6 +211,17 @@ on_join_do_winbind (GObject *source,
3eb28c
 		                         NULL);
3eb28c
 	}
3eb28c
 
3eb28c
+	if (error == NULL) {
3eb28c
+		configure_krb5_conf_for_domain (enroll->disco->kerberos_realm, &error);
3eb28c
+		if (error != NULL) {
3eb28c
+			realm_diagnostics_error (enroll->invocation, error,
3eb28c
+			                         "Failed to update Kerberos "
3eb28c
+			                         "configuration, not fatal, "
3eb28c
+			                         "please check manually");
3eb28c
+			g_clear_error (&error);
3eb28c
+		}
3eb28c
+	}
3eb28c
+
3eb28c
 	if (error == NULL) {
3eb28c
 		name = realm_kerberos_get_name (REALM_KERBEROS (self));
3eb28c
 		realm_samba_winbind_configure_async (self->config, name, enroll->options,
3eb28c
diff --git a/service/realm-sssd-ad.c b/service/realm-sssd-ad.c
3eb28c
index de7ce30..6b2f9f8 100644
3eb28c
--- a/service/realm-sssd-ad.c
3eb28c
+++ b/service/realm-sssd-ad.c
3eb28c
@@ -19,6 +19,7 @@
3eb28c
 #include "realm-dbus-constants.h"
3eb28c
 #include "realm-diagnostics.h"
3eb28c
 #include "realm-errors.h"
3eb28c
+#include "realm-kerberos-config.h"
3eb28c
 #include "realm-kerberos-membership.h"
3eb28c
 #include "realm-options.h"
3eb28c
 #include "realm-packages.h"
3eb28c
@@ -256,6 +257,17 @@ on_join_do_sssd (GObject *source,
3eb28c
 		                           join->options, join->use_adcli, &error);
3eb28c
 	}
3eb28c
 
3eb28c
+	if (error == NULL) {
3eb28c
+		configure_krb5_conf_for_domain (join->disco->kerberos_realm, &error);
3eb28c
+		if (error != NULL) {
3eb28c
+			realm_diagnostics_error (join->invocation, error,
3eb28c
+			                         "Failed to update Kerberos "
3eb28c
+			                         "configuration, not fatal, "
3eb28c
+			                         "please check manually");
3eb28c
+			g_clear_error (&error);
3eb28c
+		}
3eb28c
+	}
3eb28c
+
3eb28c
 	if (error == NULL) {
3eb28c
 		realm_service_enable_and_restart ("sssd", join->invocation,
3eb28c
 		                                  on_sssd_enable_nss, g_object_ref (task));
3eb28c
diff --git a/service/realmd-debian.conf b/service/realmd-debian.conf
3eb28c
index 3e93d60..6cfdcef 100644
3eb28c
--- a/service/realmd-debian.conf
3eb28c
+++ b/service/realmd-debian.conf
3eb28c
@@ -1,6 +1,7 @@
3eb28c
 # Distro specific overrides for debian
3eb28c
 [paths]
3eb28c
 smb.conf = /etc/samba/smb.conf
3eb28c
+krb5.conf = /etc/krb5.conf
3eb28c
 
3eb28c
 #
3eb28c
 # Normally in these packages sections we can specify a file
3eb28c
diff --git a/service/realmd-defaults.conf b/service/realmd-defaults.conf
3eb28c
index 6d7ccf8..ac4b436 100644
3eb28c
--- a/service/realmd-defaults.conf
3eb28c
+++ b/service/realmd-defaults.conf
3eb28c
@@ -11,6 +11,7 @@ sssd.conf = /etc/sssd/sssd.conf
3eb28c
 adcli = /usr/sbin/adcli
3eb28c
 ipa-client-install = /usr/sbin/ipa-client-install
3eb28c
 pam_winbind.conf = /etc/security/pam_winbind.conf
3eb28c
+krb5.conf = /etc/krb5.conf
3eb28c
 
3eb28c
 [active-directory]
3eb28c
 default-client = sssd
3eb28c
diff --git a/service/realmd-redhat.conf b/service/realmd-redhat.conf
3eb28c
index e39fad5..46e61b1 100644
3eb28c
--- a/service/realmd-redhat.conf
3eb28c
+++ b/service/realmd-redhat.conf
3eb28c
@@ -1,6 +1,7 @@
3eb28c
 # Distro specific overrides for redhat
3eb28c
 [paths]
3eb28c
 smb.conf = /etc/samba/smb.conf
3eb28c
+krb5.conf = /etc/krb5.conf
3eb28c
 
3eb28c
 [samba-packages]
3eb28c
 samba-common-tools = /usr/bin/net
3eb28c
diff --git a/service/realmd-suse.conf b/service/realmd-suse.conf
3eb28c
index 052b4dc..3165efa 100644
3eb28c
--- a/service/realmd-suse.conf
3eb28c
+++ b/service/realmd-suse.conf
3eb28c
@@ -1,6 +1,7 @@
3eb28c
 # Distro specific overrides for SuSE
3eb28c
 [paths]
3eb28c
 smb.conf = /etc/samba/smb.conf
3eb28c
+krb5.conf = /etc/krb5.conf
3eb28c
 
3eb28c
 [samba-packages]
3eb28c
 samba-client = /usr/bin/net
3eb28c
-- 
3eb28c
2.26.2
3eb28c