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