File 0041-populate-samba-secrets-using-offline-domain-join.patch of Package adcli.35968

From 05670e9d162bb979b5aa35d3e9ba253b7bd549e0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 8 Aug 2018 12:17:18 +0200
Subject: [PATCH 01/16] _adcli_call_external_program: silence noisy debug
 message

(cherry picked from commit 185a8b7378665d1d0ef7dd4d5a78438459bad9e0)
---
 library/adutil.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/adutil.c b/library/adutil.c
index 08da731..76ea158 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -692,7 +692,7 @@ done:
 		if (wret == -1) {
 			_adcli_err ("No sure what happend to net command.");
 		} else {
-			if (WIFEXITED (status)) {
+			if (WIFEXITED (status) && WEXITSTATUS (status) != 0) {
 				_adcli_err ("net command failed with %d.",
 				            WEXITSTATUS (status));
 			}
-- 
2.43.0


From ac9cc634ca8ba6752f84d6e4fd625a34eba3a8e8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 28 Jul 2021 12:55:16 +0200
Subject: [PATCH 02/16] configure: check for ns_get16 and ns_get32 as well

With newer versions of glibc res_query() might ba already available in
glibc with ns_get16() and ns_get32() still requires libresolv.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1984891
(cherry picked from commit e841ba7513f3f8b6393183d2dea9adcbf7ba2e44)
---
 configure.ac | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 68877c7..676256a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,13 +98,15 @@ AC_SUBST(LDAP_CFLAGS)
 # -------------------------------------------------------------------
 # resolv
 
-AC_MSG_CHECKING(for which library has res_query)
+AC_MSG_CHECKING([for which library has res_query, ns_get16 and ns_get32])
 for lib in "" "-lresolv"; do
 	saved_LIBS="$LIBS"
 	LIBS="$LIBS $lib"
 	AC_LINK_IFELSE([
 		AC_LANG_PROGRAM([#include <resolv.h>],
-		                [res_query (0, 0, 0, 0, 0)])
+		                [res_query (0, 0, 0, 0, 0);
+		                 ns_get32 (NULL);
+		                 ns_get16 (NULL);])
 	],
 	[ AC_MSG_RESULT(${lib:-libc}); have_res_query="yes"; break; ],
 	[ LIBS="$saved_LIBS" ])
-- 
2.43.0


From 9fd580694cb49bfb5693b6b0fed993568a1eeb84 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 13:39:12 +0200
Subject: [PATCH 03/16] disco: Add functions to extract domain GUID from LDAP
 ping

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/addisco.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/library/addisco.c b/library/addisco.c
index bf38e71..a069927 100644
--- a/library/addisco.c
+++ b/library/addisco.c
@@ -333,6 +333,78 @@ get_32_le (unsigned char **at,
 	return 1;
 }
 
+static int
+get_16_le (unsigned char **at,
+           unsigned char *end,
+           uint16_t *val)
+{
+	unsigned char *p = *at;
+	if (end - p < 2)
+		return 0;
+	*val = p[0] | p[1] << 8;
+	(*at) += 2;
+	return 1;
+}
+
+struct GUID {
+	uint32_t time_low;
+	uint16_t time_mid;
+	uint16_t time_hi_and_version;
+	uint8_t clock_seq[2];
+	uint8_t node[6];
+};
+
+/* Format is "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" */
+/* 32 chars + 4 ' ' + \0 + 2 for adding {}  */
+struct GUID_txt_buf {
+	char buf[39];
+};
+
+static char *GUID_buf_string(const struct GUID *guid,
+			     struct GUID_txt_buf *dst)
+{
+	if (guid == NULL) {
+		return NULL;
+	}
+	snprintf(dst->buf, sizeof(dst->buf),
+		 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		 guid->time_low, guid->time_mid,
+		 guid->time_hi_and_version,
+		 guid->clock_seq[0],
+		 guid->clock_seq[1],
+		 guid->node[0], guid->node[1],
+		 guid->node[2], guid->node[3],
+		 guid->node[4], guid->node[5]);
+	return dst->buf;
+}
+
+static int
+parse_guid (unsigned char **at,
+	    unsigned char *end,
+	    char **result)
+{
+	struct GUID g = { 0 };
+	struct GUID_txt_buf buf;
+
+	if (end - (*at) < sizeof(struct GUID)) {
+		return 0;
+	}
+
+	get_32_le(at, end, &g.time_low);
+	get_16_le(at, end, &g.time_mid);
+	get_16_le(at, end, &g.time_hi_and_version);
+
+	memcpy(&g.clock_seq, *at, sizeof(g.clock_seq));
+	(*at) += sizeof(g.clock_seq);
+
+	memcpy(&g.node, *at, sizeof(g.node));
+	(*at) += sizeof(g.node);
+
+	*result = strdup(GUID_buf_string(&g, &buf));
+
+	return 1;
+}
+
 static int
 skip_n (unsigned char **at,
         unsigned char *end,
-- 
2.43.0


From 58066578f0c7e223249fea5340eb359076261231 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 13:40:08 +0200
Subject: [PATCH 04/16] disco: Extract domain GUID from LDAP ping

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/addisco.c | 14 ++------------
 library/addisco.h |  1 +
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/library/addisco.c b/library/addisco.c
index a069927..985e684 100644
--- a/library/addisco.c
+++ b/library/addisco.c
@@ -405,17 +405,6 @@ parse_guid (unsigned char **at,
 	return 1;
 }
 
-static int
-skip_n (unsigned char **at,
-        unsigned char *end,
-        int n)
-{
-	if (end - (*at) < n)
-		return 0;
-	(*at) += n;
-	return 1;
-}
-
 static adcli_disco *
 parse_disco_data (struct berval *bv)
 {
@@ -434,7 +423,7 @@ parse_disco_data (struct berval *bv)
 	/* domain forest */
 	if (!get_32_le (&at, end, &type) || type != 23 ||
 	    !get_32_le (&at, end, &disco->flags) ||
-	    !skip_n (&at, end, 16) || /* guid */
+	    !parse_guid (&at, end, &disco->domain_guid) ||
 	    !parse_disco_string (beg, end, &at, &disco->forest) ||
 	    !parse_disco_string (beg, end, &at, &disco->domain) ||
 	    !parse_disco_string (beg, end, &at, &disco->host_name) ||
@@ -851,6 +840,7 @@ adcli_disco_free (adcli_disco *disco)
 		free (disco->host_addr);
 		free (disco->host_name);
 		free (disco->host_short);
+		free (disco->domain_guid);
 		free (disco->forest);
 		free (disco->domain);
 		free (disco->domain_short);
diff --git a/library/addisco.h b/library/addisco.h
index 06b69a9..79ec34f 100644
--- a/library/addisco.h
+++ b/library/addisco.h
@@ -48,6 +48,7 @@ typedef struct _adcli_disco {
 	char *forest;
 	char *domain;
 	char *domain_short;
+	char *domain_guid;
 	char *host_name;
 	char *host_addr;
 	char *host_short;
-- 
2.43.0


From 703fa4a87432ff6a260b00924ecac1118101f92c Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 13:43:47 +0200
Subject: [PATCH 05/16] conn: Copy domain GUID from disco

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adconn.c | 14 ++++++++++++++
 library/adconn.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/library/adconn.c b/library/adconn.c
index 7bab852..58db795 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -74,6 +74,7 @@ struct _adcli_conn_ctx {
 	char *canonical_host;
 	char *domain_short;
 	char *domain_sid;
+	char *domain_guid;
 	adcli_disco *domain_disco;
 	char *default_naming_context;
 	char *configuration_naming_context;
@@ -159,6 +160,11 @@ disco_dance_if_necessary (adcli_conn *conn)
 			conn->domain_short = strdup (conn->domain_disco->domain_short);
 			return_if_fail (conn->domain_short != NULL);
 		}
+
+		if (!conn->domain_guid && conn->domain_disco->domain_guid) {
+			conn->domain_guid = strdup(conn->domain_disco->domain_guid);
+			return_if_fail (conn->domain_guid != NULL);
+		}
 	}
 }
 
@@ -1287,6 +1293,7 @@ conn_free (adcli_conn *conn)
 	free (conn->domain_realm);
 	free (conn->domain_controller);
 	free (conn->domain_short);
+	free (conn->domain_guid);
 	free (conn->default_naming_context);
 	free (conn->configuration_naming_context);
 	_adcli_strv_free (conn->supported_capabilities);
@@ -1395,6 +1402,13 @@ adcli_conn_get_domain_name (adcli_conn *conn)
 	return conn->domain_name;
 }
 
+const char *
+adcli_conn_get_domain_guid(adcli_conn *conn)
+{
+	return_val_if_fail (conn != NULL, NULL);
+	return conn->domain_guid;
+}
+
 void
 adcli_conn_set_domain_name (adcli_conn *conn,
                             const char *value)
diff --git a/library/adconn.h b/library/adconn.h
index 1d5faa8..fe0ea85 100644
--- a/library/adconn.h
+++ b/library/adconn.h
@@ -97,6 +97,8 @@ const char *        adcli_conn_get_domain_short      (adcli_conn *conn);
 
 const char *        adcli_conn_get_domain_sid        (adcli_conn *conn);
 
+const char *        adcli_conn_get_domain_guid       (adcli_conn *conn);
+
 LDAP *              adcli_conn_get_ldap_connection   (adcli_conn *conn);
 
 krb5_context        adcli_conn_get_krb5_context      (adcli_conn *conn);
-- 
2.43.0


From 932198a327d691248a967beaa59fd76deaaa2ab8 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 13:45:06 +0200
Subject: [PATCH 06/16] conn: Copy forest name from disco

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adconn.c | 14 ++++++++++++++
 library/adconn.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/library/adconn.c b/library/adconn.c
index 58db795..e1c5539 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -75,6 +75,7 @@ struct _adcli_conn_ctx {
 	char *domain_short;
 	char *domain_sid;
 	char *domain_guid;
+	char *forest;
 	adcli_disco *domain_disco;
 	char *default_naming_context;
 	char *configuration_naming_context;
@@ -161,6 +162,11 @@ disco_dance_if_necessary (adcli_conn *conn)
 			return_if_fail (conn->domain_short != NULL);
 		}
 
+		if (!conn->forest && conn->domain_disco->forest) {
+			conn->forest = strdup(conn->domain_disco->forest);
+			return_if_fail (conn->forest != NULL);
+		}
+
 		if (!conn->domain_guid && conn->domain_disco->domain_guid) {
 			conn->domain_guid = strdup(conn->domain_disco->domain_guid);
 			return_if_fail (conn->domain_guid != NULL);
@@ -1294,6 +1300,7 @@ conn_free (adcli_conn *conn)
 	free (conn->domain_controller);
 	free (conn->domain_short);
 	free (conn->domain_guid);
+	free (conn->forest);
 	free (conn->default_naming_context);
 	free (conn->configuration_naming_context);
 	_adcli_strv_free (conn->supported_capabilities);
@@ -1402,6 +1409,13 @@ adcli_conn_get_domain_name (adcli_conn *conn)
 	return conn->domain_name;
 }
 
+const char *
+adcli_conn_get_forest_name (adcli_conn *conn)
+{
+	return_val_if_fail (conn != NULL, NULL);
+	return conn->forest;
+}
+
 const char *
 adcli_conn_get_domain_guid(adcli_conn *conn)
 {
diff --git a/library/adconn.h b/library/adconn.h
index fe0ea85..faca953 100644
--- a/library/adconn.h
+++ b/library/adconn.h
@@ -76,6 +76,8 @@ void                adcli_conn_set_host_fqdn         (adcli_conn *conn,
 
 const char *        adcli_conn_get_domain_name       (adcli_conn *conn);
 
+const char *        adcli_conn_get_forest_name       (adcli_conn *conn);
+
 void                adcli_conn_set_domain_name       (adcli_conn *conn,
                                                       const char *value);
 
-- 
2.43.0


From 5df2918a3fab6fd1afd084d84018264ba5ffb0b9 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 17:56:24 +0200
Subject: [PATCH 07/16] conn: Stop as soon as we have a valid LDAP connection

No need to test all possible addresses.

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adconn.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/adconn.c b/library/adconn.c
index e1c5539..f57eb1f 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -863,6 +863,7 @@ connect_to_address (const char *host,
 					break;
 				}
 			}
+			break;
 		}
 	}
 
-- 
2.43.0


From b6e3b7ea9b0da9db83e32af93ff3846bba1fe003 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 14:56:54 +0200
Subject: [PATCH 08/16] conn: Store the address of the connected server

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adconn.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/library/adconn.c b/library/adconn.c
index f57eb1f..ab4467e 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -84,6 +84,7 @@ struct _adcli_conn_ctx {
 
 	/* Connect state */
 	LDAP *ldap;
+	struct sockaddr *addr;
 	int ldap_authenticated;
 	krb5_context k5;
 	krb5_ccache ccache;
@@ -787,7 +788,8 @@ int ldap_init_fd (ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap
 static LDAP *
 connect_to_address (const char *host,
                     const char *canonical_host,
-                    bool use_ldaps)
+                    bool use_ldaps,
+		    struct sockaddr **addr)
 {
 	struct addrinfo *res = NULL;
 	struct addrinfo *ai;
@@ -870,6 +872,11 @@ connect_to_address (const char *host,
 	if (!ldap && error)
 		_adcli_err ("Couldn't connect to host: %s: %s", host, strerror (error));
 
+	*addr = malloc(sizeof(struct sockaddr));
+	if (*addr != NULL) {
+		memcpy(*addr, ai->ai_addr, sizeof(struct sockaddr));
+	}
+
 	freeaddrinfo (res);
 	/* coverity[leaked_handle] - the socket is carried inside the ldap struct */
 	return ldap;
@@ -883,6 +890,7 @@ connect_and_lookup_naming (adcli_conn *conn,
 	LDAPMessage *results;
 	adcli_result res;
 	LDAP *ldap;
+	struct sockaddr *addr;
 	int ret;
 	int ver;
 
@@ -895,13 +903,15 @@ connect_and_lookup_naming (adcli_conn *conn,
 	};
 
 	assert (conn->ldap == NULL);
+	assert (conn->addr == NULL);
 
 	canonical_host = disco->host_name;
 	if (!canonical_host)
 		canonical_host = disco->host_addr;
 
 	ldap = connect_to_address (disco->host_addr, canonical_host,
-	                           adcli_conn_get_use_ldaps (conn));
+				   adcli_conn_get_use_ldaps (conn),
+				   &addr);
 	if (ldap == NULL)
 		return ADCLI_ERR_DIRECTORY;
 
@@ -964,6 +974,7 @@ connect_and_lookup_naming (adcli_conn *conn,
 	}
 
 	conn->ldap = ldap;
+	conn->addr = addr;
 
 	free (conn->canonical_host);
 	conn->canonical_host = strdup (canonical_host);
@@ -1203,6 +1214,10 @@ conn_clear_state (adcli_conn *conn)
 		ldap_unbind_ext_s (conn->ldap, NULL, NULL);
 	conn->ldap = NULL;
 
+	if (conn->addr)
+		free(conn->addr);
+	conn->addr = NULL;
+
 	free (conn->canonical_host);
 	conn->canonical_host = NULL;
 
-- 
2.43.0


From faba57d59553a657ddd905f1391b5314730c3039 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 31 Aug 2023 17:11:55 +0200
Subject: [PATCH 09/16] conn: Allow to retrieve the connected LDAP address

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adconn.c | 7 +++++++
 library/adconn.h | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/library/adconn.c b/library/adconn.c
index ab4467e..94cc82e 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -1516,6 +1516,13 @@ adcli_conn_get_ldap_connection (adcli_conn *conn)
 	return conn->ldap;
 }
 
+struct sockaddr *
+adcli_conn_get_ldap_address (adcli_conn *conn)
+{
+	return_val_if_fail (conn != NULL, NULL);
+	return conn->addr;
+}
+
 krb5_context
 adcli_conn_get_krb5_context (adcli_conn *conn)
 {
diff --git a/library/adconn.h b/library/adconn.h
index faca953..6984c13 100644
--- a/library/adconn.h
+++ b/library/adconn.h
@@ -103,6 +103,8 @@ const char *        adcli_conn_get_domain_guid       (adcli_conn *conn);
 
 LDAP *              adcli_conn_get_ldap_connection   (adcli_conn *conn);
 
+struct sockaddr *   adcli_conn_get_ldap_address      (adcli_conn *conn);
+
 krb5_context        adcli_conn_get_krb5_context      (adcli_conn *conn);
 
 void                adcli_conn_set_krb5_context      (adcli_conn *conn,
-- 
2.43.0


From afe0ad08ccff58b29fc144af30dd496103d936ac Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 6 Sep 2023 11:49:19 +0200
Subject: [PATCH 10/16] util: Allow to append variables to external program
 environment

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adenroll.c  |  4 +--
 library/adprivate.h |  1 +
 library/adutil.c    | 69 +++++++++++++++++++++++++++++++++++++++------
 3 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/library/adenroll.c b/library/adenroll.c
index ab26e30..bbfe479 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1869,14 +1869,14 @@ update_samba_data (adcli_enroll *enroll)
 		_adcli_info ("Trying to set domain SID %s for Samba.",
 		             argv_sid[2]);
 		ret = _adcli_call_external_program (argv_sid[0], argv_sid,
-		                                    NULL, NULL, NULL);
+		                                    NULL, NULL, NULL, NULL);
 		if (ret != ADCLI_SUCCESS) {
 			_adcli_err ("Failed to set Samba domain SID.");
 		}
 	}
 
 	_adcli_info ("Trying to set Samba secret.");
-	ret = _adcli_call_external_program (argv_pw[0], argv_pw,
+	ret = _adcli_call_external_program (argv_pw[0], argv_pw, NULL,
 	                                    enroll->computer_password, NULL, NULL);
 	if (ret != ADCLI_SUCCESS) {
 		_adcli_err ("Failed to set Samba computer account password.");
diff --git a/library/adprivate.h b/library/adprivate.h
index 0806430..8f8c4ee 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -306,6 +306,7 @@ bool             _adcli_check_nt_time_string_lifetime (const char *nt_time_strin
 
 adcli_result     _adcli_call_external_program     (const char *binary,
                                                    char * const *argv,
+						   char * const *envp,
                                                    const char *stdin_data,
                                                    uint8_t **stdout_data,
                                                    size_t *stdout_data_len);
diff --git a/library/adutil.c b/library/adutil.c
index 76ea158..1a663df 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -550,7 +550,7 @@ _adcli_check_nt_time_string_lifetime (const char *nt_time_string,
 
 adcli_result
 _adcli_call_external_program (const char *binary, char * const *argv,
-                              const char *stdin_data,
+			      char * const *envp, const char *stdin_data,
                               uint8_t **stdout_data, size_t *stdout_data_len)
 {
 	int ret;
@@ -564,6 +564,48 @@ _adcli_call_external_program (const char *binary, char * const *argv,
 	int status;
 	uint8_t read_buf[4096];
 	uint8_t *out;
+	char **child_env = NULL;
+	size_t child_env_size = 0;
+
+	/* prepare child environment, append envp to environ */
+	if (envp != NULL) {
+		size_t environ_size = 0;
+		size_t envp_size = 0;
+		int i, j;
+
+		for (i = 0; environ[i] != NULL; i++) {
+			environ_size++;
+		}
+
+		for (i = 0; envp[i] != NULL; i++) {
+			envp_size++;
+		}
+
+		child_env_size = environ_size + envp_size + 1;
+		child_env = calloc(child_env_size, sizeof(char *));
+		if (child_env == NULL) {
+			_adcli_err("Failed to allocate memory.");
+			return ADCLI_ERR_FAIL;
+		}
+
+		memset(child_env, 0, child_env_size);
+
+		for (i = 0, j = 0; environ[i] != NULL; i++, j++) {
+			child_env[j] = strdup(environ[i]);
+			if (child_env[j] == NULL) {
+				_adcli_err("Failed to allocate memory.");
+				return ADCLI_ERR_FAIL;
+			}
+		}
+
+		for (i = 0; envp[i] != NULL; i++, j++) {
+			child_env[j] = strdup(envp[i]);
+			if (child_env[j] == NULL) {
+				_adcli_err("Failed to allocate memory.");
+				return ADCLI_ERR_FAIL;
+			}
+		}
+	}
 
 	errno = 0;
 	ret = access (binary, X_OK);
@@ -612,7 +654,11 @@ _adcli_call_external_program (const char *binary, char * const *argv,
 			exit (EXIT_FAILURE);
 		}
 
-		execv (binary, argv);
+                if (child_env != NULL) {
+                        execve(binary, argv, child_env);
+                } else {
+                        execv(binary, argv);
+                }
 		_adcli_err ("Failed to run %s.", binary);
 		ret = ADCLI_ERR_FAIL;
 		goto done;
@@ -671,6 +717,13 @@ _adcli_call_external_program (const char *binary, char * const *argv,
 		goto done;
 	}
 
+	if (child_env != NULL) {
+                for (int i = 0; i < child_env_size; i++) {
+                        free(child_env[i]);
+                }
+                free(child_env);
+	}
+
 	ret = ADCLI_SUCCESS;
 
 done:
@@ -852,25 +905,25 @@ test_call_external_program (void)
 	size_t stdout_data_len;
 
 	argv[0] = "/does/not/exists";
-	res = _adcli_call_external_program (argv[0], argv, NULL, NULL, NULL);
+	res = _adcli_call_external_program (argv[0], argv, NULL, NULL, NULL, NULL);
 	assert (res == ADCLI_ERR_FAIL);
 
 #ifdef BIN_CAT
 	argv[0] = BIN_CAT;
-	res = _adcli_call_external_program (argv[0], argv, "Hello",
+	res = _adcli_call_external_program (argv[0], argv, NULL, "Hello",
 	                                    &stdout_data, &stdout_data_len);
 	assert (res == ADCLI_SUCCESS);
 	assert (strncmp ("Hello", (char *) stdout_data, stdout_data_len) == 0);
 	free (stdout_data);
 
-	res = _adcli_call_external_program (argv[0], argv, "Hello",
+	res = _adcli_call_external_program (argv[0], argv, NULL, "Hello",
 	                                    NULL, NULL);
 	assert (res == ADCLI_SUCCESS);
 #endif
 
 #ifdef BIN_REV
 	argv[0] = BIN_REV;
-	res = _adcli_call_external_program (argv[0], argv, "Hello\n",
+	res = _adcli_call_external_program (argv[0], argv, NULL, "Hello\n",
 	                                    &stdout_data, &stdout_data_len);
 	assert (res == ADCLI_SUCCESS);
 	assert (strncmp ("olleH\n", (char *) stdout_data, stdout_data_len) == 0);
@@ -879,7 +932,7 @@ test_call_external_program (void)
 
 #ifdef BIN_TAC
 	argv[0] = BIN_TAC;
-	res = _adcli_call_external_program (argv[0], argv, "Hello\nWorld\n",
+	res = _adcli_call_external_program (argv[0], argv, NULL, "Hello\nWorld\n",
 	                                    &stdout_data, &stdout_data_len);
 	assert (res == ADCLI_SUCCESS);
 	assert (strncmp ("World\nHello\n", (char *) stdout_data, stdout_data_len) == 0);
@@ -889,7 +942,7 @@ test_call_external_program (void)
 #ifdef BIN_ECHO
 	argv[0] = BIN_ECHO;
 	argv[1] = "Hello";
-	res = _adcli_call_external_program (argv[0], argv, NULL,
+	res = _adcli_call_external_program (argv[0], argv, NULL, NULL,
 	                                    &stdout_data, &stdout_data_len);
 	assert (res == ADCLI_SUCCESS);
 	assert (strncmp ("Hello\n", (char *) stdout_data, stdout_data_len) == 0);
-- 
2.43.0


From 239607bc8d9b05a187a68453a7f3cbae7ed0365e Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 6 Sep 2023 12:05:03 +0200
Subject: [PATCH 11/16] util: Flag write end of pipe as invalid after closing
 it

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adutil.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/adutil.c b/library/adutil.c
index 1a663df..31e83d2 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -678,7 +678,7 @@ _adcli_call_external_program (const char *binary, char * const *argv,
 		close (pipefd_to_child[0]);
 		pipefd_to_child[0] = -1;
 		close (pipefd_to_child[1]);
-		pipefd_to_child[0] = -1;
+		pipefd_to_child[1] = -1;
 
 		if (stdout_data != NULL || stdout_data_len != NULL) {
 			rlen = read (pipefd_from_child[0], read_buf, sizeof (read_buf));
-- 
2.43.0


From eb3e1e2e91b2cc9d65aef90705d592f042066c1f Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 6 Sep 2023 16:30:45 +0200
Subject: [PATCH 12/16] util: Return failure if child exit status reports so

Otherwise error string from stdout won't be printed.

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adutil.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/adutil.c b/library/adutil.c
index 31e83d2..02f9aa2 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -748,6 +748,7 @@ done:
 			if (WIFEXITED (status) && WEXITSTATUS (status) != 0) {
 				_adcli_err ("net command failed with %d.",
 				            WEXITSTATUS (status));
+				ret = ADCLI_ERR_FAIL;
 			}
 		}
 	}
-- 
2.43.0


From a3f1bce1ee64385734a269fce6fa1e60b66434f0 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 6 Sep 2023 16:29:32 +0200
Subject: [PATCH 13/16] enroll: Issue a warning if Samba provision was
 requested but failed

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adenroll.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/library/adenroll.c b/library/adenroll.c
index bbfe479..c68621a 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -2056,9 +2056,9 @@ enroll_join_or_update_tasks (adcli_enroll *enroll,
 	if ( (flags & ADCLI_ENROLL_ADD_SAMBA_DATA) && ! (flags & ADCLI_ENROLL_PASSWORD_VALID)) {
 		res = update_samba_data (enroll);
 		if (res != ADCLI_SUCCESS) {
-			_adcli_info ("Failed to add Samba specific data, smbd "
+			_adcli_warn ("Failed to add Samba specific data, smbd "
 			             "or winbindd might not work as "
-			             "expected.\n");
+			             "expected.");
 		}
 	}
 
-- 
2.43.0


From b9f0dbf82c1eeed906bac514b119635c93561cd9 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 6 Sep 2023 12:55:50 +0200
Subject: [PATCH 14/16] enroll: Add a function to convert an IP address to text

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adutil.c | 34 ++++++++++++++++++++++++++++++++++
 library/adutil.h |  5 +++++
 2 files changed, 39 insertions(+)

diff --git a/library/adutil.c b/library/adutil.c
index 02f9aa2..81186fa 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -37,6 +37,7 @@
 #include <stdint.h>
 #include <time.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
 
 static adcli_message_func message_func = NULL;
 static char last_error[2048] = { 0, };
@@ -756,6 +757,39 @@ done:
 	return ret;
 }
 
+adcli_result
+adcli_sockaddr_to_string(struct sockaddr *sa, char *addr, size_t addr_len)
+{
+	const char *p;
+
+	if (sa == NULL) {
+		return ADCLI_ERR_FAIL;
+	}
+
+	errno = 0;
+	switch (sa->sa_family) {
+		case AF_INET:
+			p = inet_ntop(AF_INET,
+		 &(((struct sockaddr_in *)sa)->sin_addr),
+		 addr, addr_len);
+		break;
+		case AF_INET6:
+			p = inet_ntop(AF_INET6,
+		 &(((struct sockaddr_in6 *)sa)->sin6_addr),
+		 addr, addr_len);
+		break;
+		default:
+			_adcli_err("Failed to get LDAP server address, unknown socket family");
+			return ADCLI_ERR_FAIL;
+	}
+
+	if (p == NULL) {
+		_adcli_err("Failed to convert LDAP server address: %s", strerror(errno));
+		return ADCLI_ERR_FAIL;
+	}
+
+	return ADCLI_SUCCESS;
+}
 
 #ifdef UTIL_TESTS
 
diff --git a/library/adutil.h b/library/adutil.h
index a07c5da..27c0587 100644
--- a/library/adutil.h
+++ b/library/adutil.h
@@ -26,6 +26,7 @@
 
 #include <stdlib.h>
 #include <stdbool.h>
+#include <sys/socket.h>
 
 typedef enum {
 	/* Successful completion */
@@ -91,4 +92,8 @@ void              adcli_clear_last_error        (void);
 
 const char *      adcli_get_last_error          (void);
 
+adcli_result      adcli_sockaddr_to_string      (struct sockaddr *sa,
+						 char *addr,
+						 size_t addr_len);
+
 #endif /* ADUTIL_H_ */
-- 
2.43.0


From 617c4c09ed0bdec0800909919e1b79e8ad1454ef Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 7 Sep 2023 10:13:38 +0200
Subject: [PATCH 15/16] build: Check for NetComposeOfflineDomainJoin in samba's
 netapi library

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 configure.ac | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/configure.ac b/configure.ac
index 676256a..fdb27d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,12 @@ AC_CHECK_LIB(ldap, ldap_init_fd, [true], [
 AC_SUBST(LDAP_LIBS)
 AC_SUBST(LDAP_CFLAGS)
 
+# -------------------------------------------------------------------
+# samba
+
+AC_CHECK_LIB([netapi], [NetComposeOfflineDomainJoin],
+	     [AC_DEFINE(SAMBA_NETAPI_HAS_COMPOSEODJ, 1, [Samba NetApi supports composeodj])])
+
 # -------------------------------------------------------------------
 # resolv
 
-- 
2.43.0


From 89c5351355cb5873c89022dbaffc5163fcbce6fc Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 7 Sep 2023 10:19:29 +0200
Subject: [PATCH 16/16] enroll: Populate Samba's secrets database using offline
 domain join

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 library/adenroll.c | 146 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)

diff --git a/library/adenroll.c b/library/adenroll.c
index c68621a..c12ab0b 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1848,6 +1848,150 @@ update_keytab_for_principals (adcli_enroll *enroll,
 	return ADCLI_SUCCESS;
 }
 
+#if defined(SAMBA_NETAPI_HAS_COMPOSEODJ)
+
+#define CHECK_SNPRINTF(x, v) \
+	do { if ((x) < 0 || (x) >= sizeof((v))) { \
+		_adcli_err ("%s: Insufficient buffer for %s", __func__, #v); \
+		return ADCLI_ERR_FAIL; \
+	} } while (0)
+
+static adcli_result
+update_samba_data (adcli_enroll *enroll)
+{
+	int ret;
+	char dns_domain_name[128];
+	char netbios_domain_name[128];
+	char domain_sid[128];
+	char domain_guid[128];
+	char forest_name[128];
+	char machine_account_name[128];
+	char dc_name[128];
+	char dc_address[128];
+	char ldap_address[INET6_ADDRSTRLEN];
+	char *envp_composeodj[] = {"PASSWD_FD=0", NULL};
+	char *argv_composeodj[] = {
+		NULL,
+		"offlinejoin",
+		"composeodj",
+		dns_domain_name,
+		netbios_domain_name,
+		domain_sid,
+		domain_guid,
+		forest_name,
+		machine_account_name,
+		dc_name,
+		dc_address,
+		"printblob",
+		NULL};
+	char *argv_requestodj[] = {
+		NULL,
+		"offlinejoin",
+		"requestodj",
+		"-i",
+		NULL};
+	uint8_t *compose_out_data = NULL;
+	size_t compose_out_data_len = 0;
+	uint8_t *request_out_data = NULL;
+	size_t request_out_data_len = 0;
+
+        argv_composeodj[0] = (char *)adcli_enroll_get_samba_data_tool(enroll);
+        if (argv_composeodj[0] == NULL) {
+                _adcli_err("Samba data tool not available.");
+                return ADCLI_ERR_FAIL;
+        }
+        argv_requestodj[0] = argv_composeodj[0];
+
+	ret = adcli_sockaddr_to_string(adcli_conn_get_ldap_address(enroll->conn),
+				ldap_address, sizeof(ldap_address));
+	if (ret != ADCLI_SUCCESS) {
+		return ret;
+	}
+
+	ret = snprintf(dns_domain_name, sizeof(dns_domain_name), "--realm=%s",
+		adcli_conn_get_domain_name(enroll->conn));
+	CHECK_SNPRINTF(ret, dns_domain_name);
+
+	ret = snprintf(netbios_domain_name, sizeof(netbios_domain_name),
+		"--workgroup=%s", adcli_conn_get_domain_short(enroll->conn));
+	CHECK_SNPRINTF(ret, netbios_domain_name);
+
+	ret = snprintf(domain_sid, sizeof(domain_sid), "domain_sid=%s",
+		adcli_conn_get_domain_sid(enroll->conn));
+	CHECK_SNPRINTF(ret, domain_sid);
+
+	ret = snprintf(domain_guid, sizeof(domain_guid), "domain_guid=%s",
+		adcli_conn_get_domain_guid(enroll->conn));
+	CHECK_SNPRINTF(ret, domain_guid);
+
+	ret = snprintf(forest_name, sizeof(forest_name), "forest_name=%s",
+		adcli_conn_get_forest_name(enroll->conn));
+	CHECK_SNPRINTF(ret, forest_name);
+
+	ret = snprintf(machine_account_name, sizeof(machine_account_name),
+		"--user=%s", enroll->computer_sam);
+	CHECK_SNPRINTF(ret, machine_account_name);
+
+	ret = snprintf(dc_name, sizeof(dc_name), "--server=%s",
+		adcli_conn_get_domain_controller(enroll->conn));
+	CHECK_SNPRINTF(ret, dc_name);
+
+	ret = snprintf(dc_address, sizeof(dc_address), "--ipaddress=%s",
+		ldap_address);
+	CHECK_SNPRINTF(ret, dc_address);
+
+	_adcli_info("Trying to compose Samba ODJ blob.");
+	ret = _adcli_call_external_program(argv_composeodj[0],
+				    argv_composeodj, envp_composeodj,
+				    enroll->computer_password,
+				    &compose_out_data, &compose_out_data_len);
+	if (ret != ADCLI_SUCCESS) {
+		while (compose_out_data && compose_out_data_len > 0 &&
+			compose_out_data[compose_out_data_len - 1] == '\n') {
+			compose_out_data_len--;
+		}
+		_adcli_err("Failed to compose Samba ODJ blob: %.*s",
+			(int)compose_out_data_len, (char *)compose_out_data);
+		goto out;
+        }
+
+	if (compose_out_data == NULL || compose_out_data_len == 0) {
+		_adcli_err("Failed to compose ODJ blob, no data returned.");
+		ret = ADCLI_ERR_FAIL;
+		goto out;
+	}
+
+	_adcli_info("Trying to request Samba ODJ.");
+	ret = _adcli_call_external_program(argv_requestodj[0],
+				    argv_requestodj, NULL,
+				    (const char *)compose_out_data,
+				    &request_out_data, &request_out_data_len);
+	if (ret != ADCLI_SUCCESS) {
+		while (request_out_data && request_out_data_len > 0 &&
+			request_out_data[request_out_data_len - 1] == '\n') {
+			request_out_data_len--;
+		}
+		_adcli_err("Failed to request Samba ODJ: %.*s",
+			(int)request_out_data_len, request_out_data);
+		goto out;
+	}
+
+	ret = ADCLI_SUCCESS;
+out:
+	if (compose_out_data != NULL) {
+		/* Burn memory, the blob contains the machine password */
+		memset(compose_out_data, 0, compose_out_data_len);
+		free(compose_out_data);
+	}
+	if (request_out_data != NULL) {
+		free(request_out_data);
+	}
+
+	return ret;
+}
+
+#else /* defined(SAMBA_NETAPI_HAS_COMPOSEODJ) */
+
 static adcli_result
 update_samba_data (adcli_enroll *enroll)
 {
@@ -1885,6 +2029,8 @@ update_samba_data (adcli_enroll *enroll)
 	return ret;
 }
 
+#endif
+
 static void
 enroll_clear_state (adcli_enroll *enroll)
 {
-- 
2.43.0

openSUSE Build Service is sponsored by