Blob Blame History Raw
From a49994ab4ac36ff39a1e24a228e57a5269bf8fdf Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 12 Aug 2020 12:58:27 +0200
Subject: [PATCH] service: use 'additional dns hostnames' with net ads join

With newer versions of Samba the net ads join does not add services
principals with the configured host name anymore but added the new
option 'additional dns hostnames' for this.

realmd will try to figure out a fully-qualified host name and use it
with the new option if it is from a different domain.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1867912
---
 service/realm-disco.c        |  1 +
 service/realm-disco.h        |  1 +
 service/realm-samba-enroll.c | 57 +++++++++++++++++++++++++++++++++++-
 service/realm-samba.c        |  6 ++++
 4 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/service/realm-disco.c b/service/realm-disco.c
index ab06939..a12be50 100644
--- a/service/realm-disco.c
+++ b/service/realm-disco.c
@@ -62,6 +62,7 @@ realm_disco_unref (gpointer data)
 		g_free (disco->explicit_netbios);
 		g_free (disco->kerberos_realm);
 		g_free (disco->workgroup);
+		g_free (disco->dns_fqdn);
 		if (disco->server_address)
 			g_object_unref (disco->server_address);
 		g_free (disco);
diff --git a/service/realm-disco.h b/service/realm-disco.h
index 5f3e5e9..35532d2 100644
--- a/service/realm-disco.h
+++ b/service/realm-disco.h
@@ -30,6 +30,7 @@ typedef struct {
 	gchar *explicit_server;
 	gchar *explicit_netbios;
 	GSocketAddress *server_address;
+	gchar *dns_fqdn;
 } RealmDisco;
 
 #define        REALM_TYPE_DISCO             (realm_disco_get_type ())
diff --git a/service/realm-samba-enroll.c b/service/realm-samba-enroll.c
index 3f86c51..5624a08 100644
--- a/service/realm-samba-enroll.c
+++ b/service/realm-samba-enroll.c
@@ -33,6 +33,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 typedef struct {
 	GDBusMethodInvocation *invocation;
@@ -81,6 +84,44 @@ fallback_workgroup (const gchar *realm)
 		return g_utf8_strup (realm, pos - realm);
 }
 
+static char *
+try_to_get_fqdn (void)
+{
+	char hostname[HOST_NAME_MAX + 1];
+	gchar *fqdn = NULL;
+	int ret;
+	struct addrinfo *res;
+	struct addrinfo hints;
+
+	ret = gethostname (hostname, sizeof (hostname));
+	if (ret < 0) {
+		return NULL;
+	}
+
+	if (strchr (hostname, '.') == NULL) {
+		memset (&hints, 0, sizeof (struct addrinfo));
+		hints.ai_socktype = SOCK_DGRAM;
+		hints.ai_flags = AI_CANONNAME;
+
+		ret = getaddrinfo (hostname, NULL, &hints, &res);
+		if (ret != 0) {
+			return NULL;
+		}
+
+		/* Only use a fully-qualified name */
+		if (strchr (res->ai_canonname, '.') != NULL) {
+			fqdn = g_strdup (res->ai_canonname);
+		}
+
+		freeaddrinfo (res);
+
+	} else {
+		fqdn = g_strdup (hostname);
+	}
+
+	return fqdn;
+}
+
 static JoinClosure *
 join_closure_init (GTask *task,
                    RealmDisco *disco,
@@ -95,6 +136,8 @@ join_closure_init (GTask *task,
 	const gchar *explicit_computer_name = NULL;
 	const gchar *authid = NULL;
 	gchar *name_from_keytab = NULL;
+	gchar *fqdn = NULL;
+	gchar *fqdn_dom = NULL;
 
 	join = g_new0 (JoinClosure, 1);
 	join->disco = realm_disco_ref (disco);
@@ -124,7 +167,7 @@ join_closure_init (GTask *task,
 	                      "netbios name", authid,
 	                      NULL);
 
-    /*
+	/*
 	 * Samba complains if we don't set a 'workgroup' setting for the realm we're
 	 * going to join. If we didn't yet manage to lookup the workgroup, then go ahead
 	 * and assume that the first domain component is the workgroup name.
@@ -144,6 +187,18 @@ join_closure_init (GTask *task,
 			g_free (workgroup);
 	}
 
+	/* Add the fully-qualified DNS hostname as additional name if it is from
+	* a different domain. */
+	fqdn = try_to_get_fqdn ();
+	if (fqdn != NULL && join->disco->domain_name != NULL
+	                 && (fqdn_dom = strchr (fqdn, '.')) != NULL
+	                 && g_ascii_strcasecmp (fqdn_dom + 1, join->disco->domain_name) != 0 ) {
+		disco->dns_fqdn = g_strdup (fqdn);
+		realm_ini_config_set (join->config, REALM_SAMBA_CONFIG_GLOBAL,
+		                      "additional dns hostnames", disco->dns_fqdn, NULL);
+	}
+	g_free (fqdn);
+
 	/* Write out the config file for use by various net commands */
 	join->custom_smb_conf = g_build_filename (g_get_tmp_dir (), "realmd-smb-conf.XXXXXX", NULL);
 	temp_fd = g_mkstemp_full (join->custom_smb_conf, O_WRONLY, S_IRUSR | S_IWUSR);
diff --git a/service/realm-samba.c b/service/realm-samba.c
index 4940b38..fe33600 100644
--- a/service/realm-samba.c
+++ b/service/realm-samba.c
@@ -204,6 +204,11 @@ on_join_do_winbind (GObject *source,
 		                         NULL);
 	}
 
+	if (error == NULL && enroll->disco->dns_fqdn != NULL) {
+		realm_ini_config_change (self->config, REALM_SAMBA_CONFIG_GLOBAL, &error,
+		                         "additional dns hostnames", enroll->disco->dns_fqdn,
+		                         NULL);
+	}
 
 	if (error == NULL) {
 		name = realm_kerberos_get_name (REALM_KERBEROS (self));
@@ -364,6 +369,7 @@ leave_deconfigure_begin (RealmSamba *self,
 	if (!realm_ini_config_change (self->config, REALM_SAMBA_CONFIG_GLOBAL, &error,
 	                              "workgroup", NULL,
 	                              "realm", NULL,
+	                              "additional dns hostnames", NULL,
 	                              "security", "user",
 	                              NULL)) {
 		g_task_return_error (task, error);
-- 
2.28.0