c1b752
From e368c5a42656a687e6b726978752eb4abf6503d0 Mon Sep 17 00:00:00 2001
c1b752
From: Stef Walter <stefw@redhat.com>
c1b752
Date: Fri, 31 Jul 2015 12:53:04 +0200
c1b752
Subject: [PATCH 1/3] Be more liberal on what we accept as a domain name
c1b752
c1b752
Make the checks on what we accept as a domain name more liberal
c1b752
for values coming in from the network.
c1b752
c1b752
DNS Domain names are pretty liberal (internet domain names
c1b752
are more restrictive) See RFC 2181 section 11
c1b752
c1b752
http://www.ietf.org/rfc/rfc2181.txt
c1b752
c1b752
However we cannot consume names with whitespace and problematic
c1b752
punctuation, due to the various programs that parse the
c1b752
configuration files we set up.
c1b752
---
c1b752
 service/realm-disco-mscldap.c |  9 +++------
c1b752
 service/realm-disco-rootdse.c | 15 +++++++--------
c1b752
 service/realm-options.c       | 31 +++++++++++++++++++++++++++++++
c1b752
 service/realm-options.h       |  2 ++
c1b752
 4 files changed, 43 insertions(+), 14 deletions(-)
c1b752
c1b752
diff --git a/service/realm-disco-mscldap.c b/service/realm-disco-mscldap.c
c1b752
index 1ed4063..d3d3c10 100644
c1b752
--- a/service/realm-disco-mscldap.c
c1b752
+++ b/service/realm-disco-mscldap.c
c1b752
@@ -17,6 +17,7 @@
c1b752
 #include "realm-dbus-constants.h"
c1b752
 #include "realm-disco-mscldap.h"
c1b752
 #include "realm-ldap.h"
c1b752
+#include "realm-options.h"
c1b752
 
c1b752
 #include <glib/gi18n.h>
c1b752
 
c1b752
@@ -40,8 +41,6 @@ typedef struct {
c1b752
 #define HOST_NAME_MAX 255
c1b752
 #endif
c1b752
 
c1b752
-#define DOMAIN_NAME_VALID "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
c1b752
-
c1b752
 static void
c1b752
 closure_free (gpointer data)
c1b752
 {
c1b752
@@ -100,21 +99,19 @@ get_string (guchar *beg,
c1b752
             guchar **at)
c1b752
 {
c1b752
 	gchar buffer[HOST_NAME_MAX];
c1b752
-	gsize len;
c1b752
 	int n;
c1b752
 
c1b752
 	n = dn_expand (beg, end, *at, buffer, sizeof (buffer));
c1b752
 	if (n < 0)
c1b752
 		return NULL;
c1b752
 
c1b752
-	len = strlen (buffer);
c1b752
-	if (strspn (buffer, DOMAIN_NAME_VALID) != len) {
c1b752
+	if (!realm_options_check_domain_name (buffer)) {
c1b752
 		g_message ("received invalid NetLogon string characters");
c1b752
 		return NULL;
c1b752
 	}
c1b752
 
c1b752
 	(*at) += n;
c1b752
-	return g_strndup (buffer, len);
c1b752
+	return g_strdup (buffer);
c1b752
 }
c1b752
 
c1b752
 static gboolean
c1b752
diff --git a/service/realm-disco-rootdse.c b/service/realm-disco-rootdse.c
c1b752
index 1a80d98..3100650 100644
c1b752
--- a/service/realm-disco-rootdse.c
c1b752
+++ b/service/realm-disco-rootdse.c
c1b752
@@ -19,13 +19,12 @@
c1b752
 #include "realm-disco-mscldap.h"
c1b752
 #include "realm-disco-rootdse.h"
c1b752
 #include "realm-ldap.h"
c1b752
+#include "realm-options.h"
c1b752
 
c1b752
 #include <glib/gi18n.h>
c1b752
 
c1b752
 #include <resolv.h>
c1b752
 
c1b752
-#define DOMAIN_NAME_VALID "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
c1b752
-
c1b752
 typedef struct _Closure Closure;
c1b752
 
c1b752
 struct _Closure {
c1b752
@@ -92,7 +91,7 @@ static gchar *
c1b752
 entry_get_attribute (LDAP *ldap,
c1b752
                      LDAPMessage *entry,
c1b752
                      const gchar *field,
c1b752
-                     const gchar *valid)
c1b752
+                     gboolean domain_name)
c1b752
 {
c1b752
 	struct berval **bvs = NULL;
c1b752
 	gchar *value = NULL;
c1b752
@@ -102,8 +101,8 @@ entry_get_attribute (LDAP *ldap,
c1b752
 
c1b752
 	if (bvs && bvs[0]) {
c1b752
 		value = g_strndup (bvs[0]->bv_val, bvs[0]->bv_len);
c1b752
-		if (valid) {
c1b752
-		       if (strspn (value, valid) != bvs[0]->bv_len) {
c1b752
+		if (domain_name) {
c1b752
+		       if (!realm_options_check_domain_name (value)) {
c1b752
 			       g_free (value);
c1b752
 			       g_message ("Invalid value in LDAP %s field", field);
c1b752
 			       value = NULL;
c1b752
@@ -155,7 +154,7 @@ result_krb_realm (GTask *task,
c1b752
 	entry = ldap_first_entry (ldap, message);
c1b752
 
c1b752
 	g_free (clo->disco->kerberos_realm);
c1b752
-	clo->disco->kerberos_realm = entry_get_attribute (ldap, entry, "cn", DOMAIN_NAME_VALID);
c1b752
+	clo->disco->kerberos_realm = entry_get_attribute (ldap, entry, "cn", TRUE);
c1b752
 
c1b752
 	g_debug ("Found realm: %s", clo->disco->kerberos_realm);
c1b752
 
c1b752
@@ -211,7 +210,7 @@ result_domain_info (GTask *task,
c1b752
 
c1b752
 	/* What is the domain name? */
c1b752
 	g_free (clo->disco->domain_name);
c1b752
-	clo->disco->domain_name = entry_get_attribute (ldap, entry, "associatedDomain", DOMAIN_NAME_VALID);
c1b752
+	clo->disco->domain_name = entry_get_attribute (ldap, entry, "associatedDomain", TRUE);
c1b752
 
c1b752
 	g_debug ("Got associatedDomain: %s", clo->disco->domain_name);
c1b752
 
c1b752
@@ -310,7 +309,7 @@ result_root_dse (GTask *task,
c1b752
 	entry = ldap_first_entry (ldap, message);
c1b752
 
c1b752
 	/* Parse out the default naming context */
c1b752
-	clo->default_naming_context = entry_get_attribute (ldap, entry, "defaultNamingContext", NULL);
c1b752
+	clo->default_naming_context = entry_get_attribute (ldap, entry, "defaultNamingContext", FALSE);
c1b752
 
c1b752
 	g_debug ("Got defaultNamingContext: %s", clo->default_naming_context);
c1b752
 
c1b752
diff --git a/service/realm-options.c b/service/realm-options.c
c1b752
index 53266f6..bba3ee4 100644
c1b752
--- a/service/realm-options.c
c1b752
+++ b/service/realm-options.c
c1b752
@@ -18,6 +18,8 @@
c1b752
 #include "realm-options.h"
c1b752
 #include "realm-settings.h"
c1b752
 
c1b752
+#include <string.h>
c1b752
+
c1b752
 gboolean
c1b752
 realm_options_automatic_install (void)
c1b752
 {
c1b752
@@ -128,3 +130,32 @@ realm_options_qualify_names (const gchar *realm_name)
c1b752
 
c1b752
 	return qualify;
c1b752
 }
c1b752
+
c1b752
+gboolean
c1b752
+realm_options_check_domain_name (const gchar *name)
c1b752
+{
c1b752
+	/*
c1b752
+	 * DNS Domain names are pretty liberal (internet domain names
c1b752
+	 * are more restrictive) See RFC 2181 section 11
c1b752
+	 *
c1b752
+	 * http://www.ietf.org/rfc/rfc2181.txt
c1b752
+	 *
c1b752
+	 * However we cannot consume names with whitespace and problematic
c1b752
+	 * punctuation, due to the various programs that parse the
c1b752
+	 * configuration files we set up.
c1b752
+	 */
c1b752
+
c1b752
+	gsize i, len;
c1b752
+	static const gchar *invalid = "=[]:";
c1b752
+
c1b752
+	g_return_val_if_fail (name != NULL, FALSE);
c1b752
+
c1b752
+	for (i = 0, len = strlen (name); i < len; i++) {
c1b752
+		if (name[i] <= ' ')
c1b752
+			return FALSE;
c1b752
+		if (strchr (invalid, name[i]))
c1b752
+			return FALSE;
c1b752
+	}
c1b752
+
c1b752
+	return TRUE;
c1b752
+}
c1b752
diff --git a/service/realm-options.h b/service/realm-options.h
c1b752
index 52dc6ff..4890cba 100644
c1b752
--- a/service/realm-options.h
c1b752
+++ b/service/realm-options.h
c1b752
@@ -39,6 +39,8 @@ gboolean       realm_options_automatic_mapping        (GVariant *options,
c1b752
 
c1b752
 gboolean       realm_options_qualify_names            (const gchar *realm_name);
c1b752
 
c1b752
+gboolean       realm_options_check_domain_name        (const gchar *domain_name);
c1b752
+
c1b752
 G_END_DECLS
c1b752
 
c1b752
 #endif /* __REALM_OPTIONS_H__ */
c1b752
-- 
c1b752
2.4.3
c1b752