stefw pushed to realmd (f20). "Fixes for security issues (..more)"
notifications at fedoraproject.org
notifications at fedoraproject.org
Tue Apr 14 11:21:30 UTC 2015
>From 7cfe31999b8b5472441e387619276e694047d348 Mon Sep 17 00:00:00 2001
From: Stef Walter <stefw at redhat.com>
Date: Tue, 14 Apr 2015 13:04:34 +0200
Subject: Fixes for security issues
rhbz#1205752
rhbz#1205753
diff --git a/disable-automatic-ad-joins.patch b/disable-automatic-ad-joins.patch
new file mode 100644
index 0000000..219ab64
--- /dev/null
+++ b/disable-automatic-ad-joins.patch
@@ -0,0 +1,560 @@
+From d3b84368adefddc9bac7abda3b536d38f8b636d7 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw at redhat.com>
+Date: Fri, 20 Feb 2015 22:05:32 +0100
+Subject: [PATCH 2/2] service: Fix for automatic AD join problems
+
+We only offer them as an option to clients if they have been configured
+in the realmd.conf file.
+
+This is because automatic AD joins do not have the mutual authentication
+we usually expect with kerberos. The computer account secret is
+predictable and not secure enough to be on by default.
+
+Also refactor to support per domain supported cred types
+
+This is so specific domains can be configured to support things
+like automatic authentication.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=89205
+---
+ doc/manual/realm.xml | 5 +-
+ doc/manual/realmd-guide-active-directory.xml | 1 -
+ doc/manual/realmd.conf.xml | 20 ++++++++
+ service/realm-example.c | 38 +++++++++-----
+ service/realm-kerberos-membership.h | 4 +-
+ service/realm-kerberos.c | 23 +++++----
+ service/realm-options.c | 13 +++++
+ service/realm-options.h | 2 +
+ service/realm-samba.c | 50 +++++++++++--------
+ service/realm-sssd-ad.c | 75 ++++++++++++++++++----------
+ service/realm-sssd-ipa.c | 48 +++++++++++-------
+ 11 files changed, 185 insertions(+), 94 deletions(-)
+
+diff --git a/doc/manual/realm.xml b/doc/manual/realm.xml
+index 4b19766..aa79ec6 100644
+--- a/doc/manual/realm.xml
++++ b/doc/manual/realm.xml
+@@ -160,9 +160,8 @@ $ realm join --user=admin --computer-ou=OU=Special domain.example.com
+ must have a supported mechanism for joining from a client machine, such
+ as Active Directory or IPA.</para>
+
+- <para>Unless a <literal>--user</literal> is explicitly specified, an
+- automatic join is attempted first. Automatic joins require pre-configuration
+- on the domain side, and may not be supported by all domains.</para>
++ <para>If the domain has been preconfigured, and unless <literal>--user</literal>
++ is explicitly specified, an automatic join is attempted first.</para>
+
+ <para>Note that the <literal>--user </literal>, <literal>--no-password</literal>,
+ and <literal>--one-time-password </literal> options are mutually exclusive.
+diff --git a/doc/manual/realmd-guide-active-directory.xml b/doc/manual/realmd-guide-active-directory.xml
+index 401d299..9b4535d 100644
+--- a/doc/manual/realmd-guide-active-directory.xml
++++ b/doc/manual/realmd-guide-active-directory.xml
+@@ -139,7 +139,6 @@ $ <command>realm join --verbose domain.example.com</command>
+ <itemizedlist>
+ <listitem><para>Discovers information about the domain.</para></listitem>
+ <listitem><para>Installs the necessary software to join the domain, such as SSSD or Winbind.</para></listitem>
+- <listitem><para>Tries to join the domain automatically, without administrative credentials.</para></listitem>
+ <listitem><para>If administrative credentials are required, a password will be prompted for.</para></listitem>
+ <listitem><para>A computer account in the domain will be created, and or updated.</para></listitem>
+ <listitem><para>A host keytab file at <filename>/etc/krb5.keytab</filename> is created.</para></listitem>
+diff --git a/doc/manual/realmd.conf.xml b/doc/manual/realmd.conf.xml
+index b85c057..7f969fa 100644
+--- a/doc/manual/realmd.conf.xml
++++ b/doc/manual/realmd.conf.xml
+@@ -339,6 +339,26 @@ user-principal = yes
+ </varlistentry>
+
+ <varlistentry>
++ <term><option>automatic-join</option></term>
++ <listitem>
++ <para>This option only applies to Active Directory realms. This option
++ is off by default. In Active Directory domains, a computer account can
++ be preset with a known computer account password. This can be used for
++ automatic joins without authentication.</para>
++
++ <para>When automatic joins are used there is no mutual authentication
++ between the machine and the domain during the join process.</para>
++
++ <informalexample>
++<programlisting>
++[domain.example.com]
++automatic-join = yes
++</programlisting>
++ </informalexample>
++ </listitem>
++ </varlistentry>
++
++ <varlistentry>
+ <term><option>automatic-id-mapping</option></term>
+ <listitem>
+ <para>This option is on by default for Active Directory realms.
+diff --git a/service/realm-example.c b/service/realm-example.c
+index 37a7dd5..2a8d4aa 100644
+--- a/service/realm-example.c
++++ b/service/realm-example.c
+@@ -186,6 +186,17 @@ realm_example_join_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_example_join_creds (RealmKerberosMembership *membership)
++{
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
++ { 0, }
++ };
++
++ return creds;
++}
++
+ static void
+ on_leave_sleep_done (GObject *source,
+ GAsyncResult *res,
+@@ -319,6 +330,18 @@ realm_example_leave_async (RealmKerberosMembership *membership,
+ }
+ }
+
++static const RealmCredential *
++realm_example_leave_creds (RealmKerberosMembership *membership)
++{
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
++ { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE },
++ { 0, }
++ };
++
++ return creds;
++}
++
+ static void
+ realm_example_logins_async (RealmKerberos *realm,
+ GDBusMethodInvocation *invocation,
+@@ -496,24 +519,13 @@ realm_example_class_init (RealmExampleClass *klass)
+ static void
+ realm_example_kerberos_membership_iface (RealmKerberosMembershipIface *iface)
+ {
+- static const RealmCredential join_creds[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
+- { 0, }
+- };
+-
+- static const RealmCredential leave_creds[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
+- { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE },
+- { 0, }
+- };
+-
+ iface->join_async = realm_example_join_async;
+ iface->join_finish = realm_example_membership_generic_finish;
+- iface->join_creds_supported = join_creds;
++ iface->join_creds = realm_example_join_creds;
+
+ iface->leave_async = realm_example_leave_async;
+ iface->leave_finish = realm_example_membership_generic_finish;
+- iface->leave_creds_supported = leave_creds;
++ iface->leave_creds = realm_example_leave_creds;
+ }
+
+ RealmKerberos *
+diff --git a/service/realm-kerberos-membership.h b/service/realm-kerberos-membership.h
+index 9b1e395..50eea53 100644
+--- a/service/realm-kerberos-membership.h
++++ b/service/realm-kerberos-membership.h
+@@ -48,7 +48,7 @@ struct _RealmKerberosMembershipIface {
+ GAsyncResult *result,
+ GError **error);
+
+- const RealmCredential *join_creds_supported;
++ const RealmCredential * (* join_creds) (RealmKerberosMembership *realm);
+
+ void (* leave_async) (RealmKerberosMembership *realm,
+ RealmCredential *cred,
+@@ -61,7 +61,7 @@ struct _RealmKerberosMembershipIface {
+ GAsyncResult *result,
+ GError **error);
+
+- const RealmCredential *leave_creds_supported;
++ const RealmCredential * (* leave_creds) (RealmKerberosMembership *realm);
+ };
+
+ GType realm_kerberos_membership_get_type (void) G_GNUC_CONST;
+diff --git a/service/realm-kerberos.c b/service/realm-kerberos.c
+index e7f2f20..54d1ed7 100644
+--- a/service/realm-kerberos.c
++++ b/service/realm-kerberos.c
+@@ -241,6 +241,7 @@ on_unenroll_complete (GObject *source,
+
+ static gboolean
+ is_credential_supported (RealmKerberosMembershipIface *iface,
++ RealmKerberosMembership *membership,
+ RealmCredential *cred,
+ gboolean join,
+ GError **error)
+@@ -250,7 +251,10 @@ is_credential_supported (RealmKerberosMembershipIface *iface,
+ gboolean found = FALSE;
+ gint i;
+
+- supported = join ? iface->join_creds_supported : iface->leave_creds_supported;
++ g_assert (iface->join_creds != NULL);
++ g_assert (iface->leave_creds != NULL);
++
++ supported = (join ? iface->join_creds (membership) : iface->leave_creds (membership));
+ if (supported) {
+ for (i = 0; supported[i].type != 0; i++) {
+ if (cred->type == supported[i].type) {
+@@ -294,6 +298,7 @@ join_or_leave (RealmKerberos *self,
+ gboolean join)
+ {
+ RealmKerberosMembershipIface *iface = REALM_KERBEROS_MEMBERSHIP_GET_IFACE (self);
++ RealmKerberosMembership *membership = REALM_KERBEROS_MEMBERSHIP (self);
+ RealmCredential *cred;
+ MethodClosure *method;
+ GError *error = NULL;
+@@ -315,7 +320,7 @@ join_or_leave (RealmKerberos *self,
+ return;
+ }
+
+- if (!is_credential_supported (iface, cred, join, &error)) {
++ if (!is_credential_supported (iface, membership, cred, join, &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ realm_credential_unref (cred);
+ g_error_free (error);
+@@ -333,12 +338,10 @@ join_or_leave (RealmKerberos *self,
+
+ if (join) {
+ g_return_if_fail (iface->join_finish != NULL);
+- (iface->join_async) (REALM_KERBEROS_MEMBERSHIP (self), cred,
+- options, invocation, on_enroll_complete, method);
++ (iface->join_async) (membership, cred, options, invocation, on_enroll_complete, method);
+ } else {
+ g_return_if_fail (iface->leave_finish != NULL);
+- (iface->leave_async) (REALM_KERBEROS_MEMBERSHIP (self), cred,
+- options, invocation, on_unenroll_complete, method);
++ (iface->leave_async) (membership, cred, options, invocation, on_unenroll_complete, method);
+ }
+ }
+
+@@ -543,6 +546,7 @@ static void
+ realm_kerberos_constructed (GObject *obj)
+ {
+ RealmKerberosMembershipIface *iface;
++ RealmKerberosMembership *membership;
+ RealmKerberos *self = REALM_KERBEROS (obj);
+ const gchar *supported_interfaces[3];
+ GVariant *supported;
+@@ -561,11 +565,12 @@ realm_kerberos_constructed (GObject *obj)
+ G_DBUS_INTERFACE_SKELETON (self->pv->membership_iface));
+
+ iface = REALM_KERBEROS_MEMBERSHIP_GET_IFACE (self);
+- supported = realm_credential_build_supported (iface->join_creds_supported);
++ membership = REALM_KERBEROS_MEMBERSHIP (self);
++
++ supported = realm_credential_build_supported (iface->join_creds (membership));
+ realm_dbus_kerberos_membership_set_supported_join_credentials (self->pv->membership_iface, supported);
+
+- iface = REALM_KERBEROS_MEMBERSHIP_GET_IFACE (self);
+- supported = realm_credential_build_supported (iface->leave_creds_supported);
++ supported = realm_credential_build_supported (iface->leave_creds (membership));
+ realm_dbus_kerberos_membership_set_supported_leave_credentials (self->pv->membership_iface, supported);
+ }
+
+diff --git a/service/realm-options.c b/service/realm-options.c
+index f7a473c..6f7d915 100644
+--- a/service/realm-options.c
++++ b/service/realm-options.c
+@@ -96,6 +96,19 @@ realm_options_automatic_mapping (const gchar *realm_name)
+ }
+
+ gboolean
++realm_options_automatic_join (const gchar *realm_name)
++{
++ gchar *section;
++ gboolean mapping;
++
++ section = g_utf8_casefold (realm_name, -1);
++ mapping = realm_settings_boolean (realm_name, "automatic-join", FALSE);
++ g_free (section);
++
++ return mapping;
++}
++
++gboolean
+ realm_options_qualify_names (const gchar *realm_name)
+ {
+ gchar *section;
+diff --git a/service/realm-options.h b/service/realm-options.h
+index 4c95927..10af386 100644
+--- a/service/realm-options.h
++++ b/service/realm-options.h
+@@ -26,6 +26,8 @@ gboolean realm_options_manage_system (GVariant *options,
+
+ gboolean realm_options_automatic_install (GVariant *options);
+
++gboolean realm_options_automatic_join (const gchar *realm_name);
++
+ const gchar * realm_options_computer_ou (GVariant *options,
+ const gchar *realm_name);
+
+diff --git a/service/realm-samba.c b/service/realm-samba.c
+index 3a8ce87..9bf7872 100644
+--- a/service/realm-samba.c
++++ b/service/realm-samba.c
+@@ -293,6 +293,19 @@ realm_samba_join_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_samba_join_creds (RealmKerberosMembership *self)
++{
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER },
++ { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN },
++ { 0, },
++ };
++
++ return creds;
++}
++
+ typedef struct {
+ GDBusMethodInvocation *invocation;
+ RealmDisco *disco;
+@@ -425,6 +438,19 @@ realm_samba_leave_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_samba_leave_creds (RealmKerberosMembership *self)
++{
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER },
++ { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE },
++ { 0, },
++ };
++
++ return creds;
++}
++
+ static gboolean
+ realm_samba_change_logins (RealmKerberos *realm,
+ GDBusMethodInvocation *invocation,
+@@ -674,33 +700,13 @@ realm_samba_class_init (RealmSambaClass *klass)
+ static void
+ realm_samba_kerberos_membership_iface (RealmKerberosMembershipIface *iface)
+ {
+- /*
+- * Each line is a combination of owner and what kind of credentials are supported,
+- * same for enroll/leave. We can't accept a ccache, because samba3 needs
+- * to have credentials limited to RC4.
+- */
+-
+- static const RealmCredential join_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER },
+- { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN },
+- { 0, },
+- };
+-
+- static const RealmCredential leave_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER },
+- { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE },
+- { 0, },
+- };
+-
+ iface->join_async = realm_samba_join_async;
+ iface->join_finish = realm_samba_membership_generic_finish;
+- iface->join_creds_supported = join_supported;
++ iface->join_creds = realm_samba_join_creds;
+
+ iface->leave_async = realm_samba_leave_async;
+ iface->leave_finish = realm_samba_membership_generic_finish;
+- iface->leave_creds_supported = leave_supported;
++ iface->leave_creds = realm_samba_leave_creds;
+ }
+
+ RealmKerberos *
+diff --git a/service/realm-sssd-ad.c b/service/realm-sssd-ad.c
+index cc488fc..abd7fa7 100644
+--- a/service/realm-sssd-ad.c
++++ b/service/realm-sssd-ad.c
+@@ -426,6 +426,39 @@ realm_sssd_ad_join_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_sssd_ad_join_creds (RealmKerberosMembership *membership)
++{
++ /*
++ * Each line is a combination of owner and what kind of credentials are supported,
++ * same for enroll/leave. We can't accept a ccache with samba because of certain
++ * corner cases. However we do accept ccache for an admin user, and then we use
++ * adcli with that ccache.
++ */
++
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER, },
++ { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
++ { REALM_CREDENTIAL_SECRET, REALM_CREDENTIAL_OWNER_NONE, },
++ { 0, },
++ };
++
++ static const RealmCredential creds_no_auto[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER, },
++ { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_SECRET, REALM_CREDENTIAL_OWNER_NONE, },
++ { 0, }
++ };
++
++ const gchar *name;
++
++ name = realm_kerberos_get_name (REALM_KERBEROS (membership));
++ return realm_options_automatic_join (name) ? creds : creds_no_auto;
++}
++
+ typedef struct {
+ GDBusMethodInvocation *invocation;
+ gchar *realm_name;
+@@ -527,6 +560,20 @@ realm_sssd_ad_leave_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_sssd_ad_leave_creds (RealmKerberosMembership *membership)
++{
++ /* For leave, we don't support one-time-password (ie: secret/none) */
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
++ { 0, },
++ };
++
++ return creds;
++}
++
+ static gboolean
+ realm_sssd_ad_generic_finish (RealmKerberosMembership *realm,
+ GAsyncResult *result,
+@@ -594,35 +641,11 @@ realm_sssd_ad_class_init (RealmSssdAdClass *klass)
+ static void
+ realm_sssd_ad_kerberos_membership_iface (RealmKerberosMembershipIface *iface)
+ {
+- /*
+- * Each line is a combination of owner and what kind of credentials are supported,
+- * same for enroll/leave. We can't accept a ccache with samba because of certain
+- * corner cases. However we do accept ccache for an admin user, and then we use
+- * adcli with that ccache.
+- */
+-
+- static const RealmCredential join_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_USER, },
+- { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN, },
+- { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
+- { REALM_CREDENTIAL_SECRET, REALM_CREDENTIAL_OWNER_NONE, },
+- { 0, },
+- };
+-
+- /* For leave, we don't support one-time-password (ie: secret/none) */
+- static const RealmCredential leave_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
+- { REALM_CREDENTIAL_CCACHE, REALM_CREDENTIAL_OWNER_ADMIN, },
+- { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
+- { 0, },
+- };
+-
+ iface->join_async = realm_sssd_ad_join_async;
+ iface->join_finish = realm_sssd_ad_generic_finish;
+- iface->join_creds_supported = join_supported;
++ iface->join_creds = realm_sssd_ad_join_creds;
+
+ iface->leave_async = realm_sssd_ad_leave_async;
+ iface->leave_finish = realm_sssd_ad_generic_finish;
+- iface->leave_creds_supported = leave_supported;
++ iface->leave_creds = realm_sssd_ad_leave_creds;
+ }
+diff --git a/service/realm-sssd-ipa.c b/service/realm-sssd-ipa.c
+index ecf5026..a697223 100644
+--- a/service/realm-sssd-ipa.c
++++ b/service/realm-sssd-ipa.c
+@@ -390,6 +390,22 @@ realm_sssd_ipa_join_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_sssd_ipa_join_creds (RealmKerberosMembership *membership)
++{
++ /*
++ * NOTE: The ipa-client-install service requires that we pass a password directly
++ * to the process, and not a ccache. It also accepts a one time password.
++ */
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
++ { REALM_CREDENTIAL_SECRET, REALM_CREDENTIAL_OWNER_NONE, },
++ { 0, }
++ };
++
++ return creds;
++}
++
+ static void
+ on_ipa_client_do_disable (GObject *source,
+ GAsyncResult *result,
+@@ -489,6 +505,18 @@ realm_sssd_ipa_leave_async (RealmKerberosMembership *membership,
+ g_object_unref (task);
+ }
+
++static const RealmCredential *
++realm_sssd_ipa_leave_creds (RealmKerberosMembership *membership)
++{
++ static const RealmCredential creds[] = {
++ { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
++ { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
++ { 0, }
++ };
++
++ return creds;
++}
++
+ static gboolean
+ realm_sssd_ipa_generic_finish (RealmKerberosMembership *realm,
+ GAsyncResult *result,
+@@ -501,27 +529,11 @@ static void
+ realm_sssd_ipa_kerberos_membership_iface (RealmKerberosMembershipIface *iface)
+ {
+
+- /*
+- * NOTE: The ipa-client-install service requires that we pass a password directly
+- * to the process, and not a ccache. It also accepts a one time password.
+- */
+- static const RealmCredential join_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN },
+- { REALM_CREDENTIAL_SECRET, REALM_CREDENTIAL_OWNER_NONE, },
+- { 0, }
+- };
+-
+- static const RealmCredential leave_supported[] = {
+- { REALM_CREDENTIAL_PASSWORD, REALM_CREDENTIAL_OWNER_ADMIN, },
+- { REALM_CREDENTIAL_AUTOMATIC, REALM_CREDENTIAL_OWNER_NONE, },
+- { 0, }
+- };
+-
+ iface->join_async = realm_sssd_ipa_join_async;
+ iface->join_finish = realm_sssd_ipa_generic_finish;
+- iface->join_creds_supported = join_supported;
++ iface->join_creds = realm_sssd_ipa_join_creds;
+
+ iface->leave_async = realm_sssd_ipa_leave_async;
+ iface->leave_finish = realm_sssd_ipa_generic_finish;
+- iface->leave_creds_supported = leave_supported;
++ iface->leave_creds = realm_sssd_ipa_leave_creds;
+ }
+--
+2.3.5
+
diff --git a/ldap-validate-text.patch b/ldap-validate-text.patch
new file mode 100644
index 0000000..e73d815
--- /dev/null
+++ b/ldap-validate-text.patch
@@ -0,0 +1,124 @@
+From 77a255356efa20ab1a445b061d1adfe9f5042aa2 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw at redhat.com>
+Date: Tue, 14 Apr 2015 11:30:53 +0200
+Subject: [PATCH 1/2] service: Limit the characters we read from LDAP and
+ MSCLDAP
+
+We strictly limit this to characters expected in domain names.
+
+This provides an extra layer of protection against injecting
+odd characters into configuration files.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=89207
+---
+ service/realm-disco-mscldap.c | 11 ++++++++++-
+ service/realm-disco-rootdse.c | 21 ++++++++++++++++-----
+ 2 files changed, 26 insertions(+), 6 deletions(-)
+
+diff --git a/service/realm-disco-mscldap.c b/service/realm-disco-mscldap.c
+index 6ffa105..1ed4063 100644
+--- a/service/realm-disco-mscldap.c
++++ b/service/realm-disco-mscldap.c
+@@ -40,6 +40,8 @@ typedef struct {
+ #define HOST_NAME_MAX 255
+ #endif
+
++#define DOMAIN_NAME_VALID "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
++
+ static void
+ closure_free (gpointer data)
+ {
+@@ -98,14 +100,21 @@ get_string (guchar *beg,
+ guchar **at)
+ {
+ gchar buffer[HOST_NAME_MAX];
++ gsize len;
+ int n;
+
+ n = dn_expand (beg, end, *at, buffer, sizeof (buffer));
+ if (n < 0)
+ return NULL;
+
++ len = strlen (buffer);
++ if (strspn (buffer, DOMAIN_NAME_VALID) != len) {
++ g_message ("received invalid NetLogon string characters");
++ return NULL;
++ }
++
+ (*at) += n;
+- return g_strdup (buffer);
++ return g_strndup (buffer, len);
+ }
+
+ static gboolean
+diff --git a/service/realm-disco-rootdse.c b/service/realm-disco-rootdse.c
+index f1ae7bb..1a80d98 100644
+--- a/service/realm-disco-rootdse.c
++++ b/service/realm-disco-rootdse.c
+@@ -24,6 +24,8 @@
+
+ #include <resolv.h>
+
++#define DOMAIN_NAME_VALID "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
++
+ typedef struct _Closure Closure;
+
+ struct _Closure {
+@@ -89,7 +91,8 @@ entry_has_attribute (LDAP *ldap,
+ static gchar *
+ entry_get_attribute (LDAP *ldap,
+ LDAPMessage *entry,
+- const gchar *field)
++ const gchar *field,
++ const gchar *valid)
+ {
+ struct berval **bvs = NULL;
+ gchar *value = NULL;
+@@ -97,8 +100,16 @@ entry_get_attribute (LDAP *ldap,
+ if (entry != NULL)
+ bvs = ldap_get_values_len (ldap, entry, field);
+
+- if (bvs && bvs[0])
++ if (bvs && bvs[0]) {
+ value = g_strndup (bvs[0]->bv_val, bvs[0]->bv_len);
++ if (valid) {
++ if (strspn (value, valid) != bvs[0]->bv_len) {
++ g_free (value);
++ g_message ("Invalid value in LDAP %s field", field);
++ value = NULL;
++ }
++ }
++ }
+
+ ldap_value_free_len (bvs);
+
+@@ -144,7 +155,7 @@ result_krb_realm (GTask *task,
+ entry = ldap_first_entry (ldap, message);
+
+ g_free (clo->disco->kerberos_realm);
+- clo->disco->kerberos_realm = entry_get_attribute (ldap, entry, "cn");
++ clo->disco->kerberos_realm = entry_get_attribute (ldap, entry, "cn", DOMAIN_NAME_VALID);
+
+ g_debug ("Found realm: %s", clo->disco->kerberos_realm);
+
+@@ -200,7 +211,7 @@ result_domain_info (GTask *task,
+
+ /* What is the domain name? */
+ g_free (clo->disco->domain_name);
+- clo->disco->domain_name = entry_get_attribute (ldap, entry, "associatedDomain");
++ clo->disco->domain_name = entry_get_attribute (ldap, entry, "associatedDomain", DOMAIN_NAME_VALID);
+
+ g_debug ("Got associatedDomain: %s", clo->disco->domain_name);
+
+@@ -299,7 +310,7 @@ result_root_dse (GTask *task,
+ entry = ldap_first_entry (ldap, message);
+
+ /* Parse out the default naming context */
+- clo->default_naming_context = entry_get_attribute (ldap, entry, "defaultNamingContext");
++ clo->default_naming_context = entry_get_attribute (ldap, entry, "defaultNamingContext", NULL);
+
+ g_debug ("Got defaultNamingContext: %s", clo->default_naming_context);
+
+--
+2.3.5
+
diff --git a/realmd.spec b/realmd.spec
index 033dbb9..233050f 100644
--- a/realmd.spec
+++ b/realmd.spec
@@ -1,6 +1,6 @@
Name: realmd
Version: 0.14.6
-Release: 5%{?dist}
+Release: 6%{?dist}
Summary: Kerberos realm enrollment service
License: LGPLv2+
URL: http://cgit.freedesktop.org/realmd/realmd/
@@ -9,6 +9,9 @@ Patch1: oddjob-start.patch
Patch2: safe-printf.patch
Patch3: missing-fqname.patch
+Patch11: disable-automatic-ad-joins.patch
+Patch12: ldap-validate-text.patch
+
BuildRequires: intltool pkgconfig
BuildRequires: gettext-devel
BuildRequires: glib2-devel >= 2.32.0
@@ -43,6 +46,8 @@ applications that use %{name}.
%patch1 -p1
%patch2 -p1
%patch3 -p1
+%patch11 -p 1
+%patch12 -p 1
%build
%configure --disable-silent-rules
@@ -77,6 +82,9 @@ make install DESTDIR=%{buildroot}
%doc %{_datadir}/doc/realmd/
%changelog
+* Tue Apr 14 2015 Stef Walter <stefw at redhat.com> - 0.14.5-6
+- Fixes for security issues: rhbz#1205752 rhbz#1205753
+
* Wed Jul 16 2014 Stef Walter <stefw at redhat.com> - 0.14.6-5
- Fix desktop-centric polkit policy [#1094124]
--
cgit v0.10.2
http://pkgs.fedoraproject.org/cgit/realmd.git/commit/?h=f20&id=7cfe31999b8b5472441e387619276e694047d348
More information about the scm-commits
mailing list