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