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