Commit f5404de6 authored by Robin Sonnabend's avatar Robin Sonnabend

Add initial script for package building

parents
Pipeline #473 failed with stage
in 22 seconds
__pycache__/
venv/
image: stretch_website
before_script:
- export LANG=en_US.UTF-8
stages:
- test
test:
stage: test
script: scripts/build.py
---
- name: adcli
patch_dir: patches/adcli
From 213116ea8a16a10f4def750d92095c250b51def7 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 7 Oct 2016 13:57:44 +0200
Subject: [PATCH 01/30] Handle empty string in client site name
parse_disco_string() returns an empty string if there is no client site
name in the NetLogon reply. Later in the code only a NULL check is used
to check for a missing client site name. To make sure the empty string
is not used as client site name it should be replaced with NULL.
https://bugs.freedesktop.org/show_bug.cgi?id=98143
---
library/addisco.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/library/addisco.c b/library/addisco.c
index bf38e71..08d2c8e 100644
--- a/library/addisco.c
+++ b/library/addisco.c
@@ -378,6 +378,14 @@ parse_disco_data (struct berval *bv)
_adcli_info ("Received NetLogon info from: %s", disco->host_name);
}
+ /* If the DC cannot determine the client site it will return an empty
+ * string. Make sure this is handled the same way as a missing client
+ * site. */
+ if (disco->client_site[0] == '\0') {
+ free (disco->client_site);
+ disco->client_site = NULL;
+ }
+
/* We don't care about these */
free (user);
return disco;
--
2.11.0
From 85146804c219b2d4a62f315a0988536af7a53911 Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund <joakim.tjernlund@infinera.com>
Date: Thu, 30 Mar 2017 12:50:33 +0200
Subject: [PATCH 02/30] Move the empty client site check
Currently this check will SEGV(NULL ptr access) if the parsing
of Netlogon discovery data fails. Move the empty check to where the
disco ptr is always valid. Add a log msg too.
Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com>
https://bugs.freedesktop.org/show_bug.cgi?id=100466
---
library/addisco.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/library/addisco.c b/library/addisco.c
index 08d2c8e..8cc5bf0 100644
--- a/library/addisco.c
+++ b/library/addisco.c
@@ -376,14 +376,14 @@ parse_disco_data (struct berval *bv)
disco = NULL;
} else {
_adcli_info ("Received NetLogon info from: %s", disco->host_name);
- }
-
- /* If the DC cannot determine the client site it will return an empty
- * string. Make sure this is handled the same way as a missing client
- * site. */
- if (disco->client_site[0] == '\0') {
- free (disco->client_site);
- disco->client_site = NULL;
+ /* If the DC cannot determine the client site it will return an empty
+ * string. Make sure this is handled the same way as a missing client
+ * site. */
+ if (disco->client_site[0] == '\0') {
+ free (disco->client_site);
+ disco->client_site = NULL;
+ _adcli_info ("Empty client site, skipping");
+ }
}
/* We don't care about these */
--
2.11.0
From 7c95c61a86c5801d551d1042900b0e2e671891ce Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 24 Aug 2016 15:37:41 +0200
Subject: [PATCH 03/30] Remove upper-case only check when looking for the
NetBIOS name
It is a convention to use only upper-case letters for NetBIOS names but
it is not enforced on the AD-side. With the new option to specify a
random NetBIOS name it is possible to create host entries in AD with
lower-case letters in the name. To properly determine the name from the
keytab the upper-case check should be dropped.
---
library/adenroll.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index a15e4be..d1020e9 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1309,7 +1309,7 @@ load_keytab_entry (krb5_context k5,
if (!enroll->host_fqdn_explicit && !enroll->computer_name_explicit) {
/* Automatically use the netbios name */
- if (!enroll->computer_name && len > 1 && _adcli_str_is_up (name) &&
+ if (!enroll->computer_name && len > 1 &&
_adcli_str_has_suffix (name, "$") && !strchr (name, '/')) {
enroll->computer_name = name;
name[len - 1] = '\0';
--
2.11.0
From 90c1e96cf3eea8718aa97a6fb97aa2029ef64670 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 24 Aug 2016 16:19:36 +0200
Subject: [PATCH 04/30] Use strdup() if offsets are used
Strings with an offset to the original starting point must be copied
because otherwise they cannot be properly freed later.
---
library/adenroll.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index d1020e9..05885d0 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1318,9 +1318,9 @@ load_keytab_entry (krb5_context k5,
} else if (!enroll->host_fqdn && _adcli_str_has_prefix (name, "host/") && strchr (name, '.')) {
/* Skip host/ prefix */
- enroll->host_fqdn = name + 5;
- _adcli_info ("Found host qualified name in keytab: %s", name);
- name = NULL;
+ enroll->host_fqdn = strdup (name + 5);
+ return_val_if_fail (enroll->host_fqdn != NULL, FALSE);
+ _adcli_info ("Found host qualified name in keytab: %s", enroll->host_fqdn);
}
}
--
2.11.0
From 99b2d00ea848db46898ae111a10739f9a9c7bf3e Mon Sep 17 00:00:00 2001
From: Striker Leggette <striker@redhat.com>
Date: Wed, 1 Nov 2017 11:16:39 +0100
Subject: [PATCH 05/30] correct spelling of 'adcli_tool_computer_delete'
description
---
tools/tools.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/tools.c b/tools/tools.c
index 4b243de..915130e 100644
--- a/tools/tools.c
+++ b/tools/tools.c
@@ -57,7 +57,7 @@ struct {
{ "update", adcli_tool_computer_update, "Update machine membership in a domain", },
{ "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", },
{ "reset-computer", adcli_tool_computer_reset, "Reset a computer account", },
- { "delete-computer", adcli_tool_computer_delete, "Delete a computer acocunt", },
+ { "delete-computer", adcli_tool_computer_delete, "Delete a computer account", },
{ "create-user", adcli_tool_user_create, "Create a user account", },
{ "delete-user", adcli_tool_user_delete, "Delete a user account", },
{ "create-group", adcli_tool_group_create, "Create a group", },
--
2.11.0
From 8bfeba525a104f39c9ede7601035d934cd062437 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 12:01:18 +0100
Subject: [PATCH 06/30] doc: explain that all credential cache types are
supported
---
doc/adcli.xml | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/doc/adcli.xml b/doc/adcli.xml
index e18ba5d..c54cc1b 100644
--- a/doc/adcli.xml
+++ b/doc/adcli.xml
@@ -118,11 +118,15 @@
is automatically discovered.</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>-C, --login-ccache=<parameter>/path/to/file</parameter></option></term>
+ <term><option>-C, --login-ccache=<parameter>ccache_name</parameter></option></term>
<listitem><para>Use the specified kerberos credential
- cache to authenticate with the domain. If no file is specified or
- <option>-C</option> is used, then the default kerberos credential cache will
- be used.</para></listitem>
+ cache to authenticate with the domain. If no credential
+ cache is specified, the default kerberos credential
+ cache will be used. Credential caches of type FILE can
+ be given with the path to the file. For other
+ credential cache types, e.g. DIR, KEYRING or KCM, the
+ type must be specified explicitly together with a
+ suitable identifier.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-U, --login-user=<parameter>User</parameter></option></term>
--
2.11.0
From d9721f64ca3bb3467898c06aa8470aec73a0d0d8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 16:29:19 +0100
Subject: [PATCH 07/30] library: add adcli_conn_is_writeable()
---
library/adconn.c | 11 +++++++++++
library/adconn.h | 2 ++
2 files changed, 13 insertions(+)
diff --git a/library/adconn.c b/library/adconn.c
index a294dfd..0786ed4 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -1528,3 +1528,14 @@ adcli_conn_server_has_capability (adcli_conn *conn,
return 0;
}
+
+bool adcli_conn_is_writeable (adcli_conn *conn)
+{
+ disco_dance_if_necessary (conn);
+
+ if (conn->domain_disco == NULL) {
+ return false;
+ }
+
+ return ( (conn->domain_disco->flags & ADCLI_DISCO_WRITABLE) != 0);
+}
diff --git a/library/adconn.h b/library/adconn.h
index a0cb1f8..ed1cc58 100644
--- a/library/adconn.h
+++ b/library/adconn.h
@@ -144,4 +144,6 @@ void adcli_conn_set_krb5_conf_dir (adcli_conn *conn,
int adcli_conn_server_has_capability (adcli_conn *conn,
const char *capability);
+bool adcli_conn_is_writeable (adcli_conn *conn);
+
#endif /* ADCONN_H_ */
--
2.11.0
From 4edc04768f6b28312404312e7012c700661a4ee3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 17:14:05 +0100
Subject: [PATCH 08/30] Handle kvno increment for RODCs
Since the actual password change does not happen on the read-only domain
controller (RODC) the kvno change has to be replicated back which might
take some time. So we check the kvno before and after the change if we
are connected to a RODC and increment the kvno if needed.
---
library/adenroll.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/library/adenroll.c b/library/adenroll.c
index 05885d0..bb970d1 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1633,8 +1633,30 @@ enroll_join_or_update_tasks (adcli_enroll *enroll,
adcli_enroll_flags flags)
{
adcli_result res;
+ krb5_kvno old_kvno = -1;
if (!(flags & ADCLI_ENROLL_PASSWORD_VALID)) {
+
+ /* Handle kvno changes for read-only domain controllers
+ * (RODC). Since the actual password change does not happen on
+ * the RODC the kvno change has to be replicated back which
+ * might take some time. So we check the kvno before and after
+ * the change if we are connected to a RODC and increment the
+ * kvno if needed. */
+ if (!adcli_conn_is_writeable (enroll->conn)) {
+ if (enroll->computer_attributes == NULL) {
+ res = retrieve_computer_account (enroll);
+ if (res != ADCLI_SUCCESS)
+ return res;
+ }
+ old_kvno = adcli_enroll_get_kvno (enroll);
+ _adcli_info ("Found old kvno '%d'", old_kvno);
+
+ ldap_msgfree (enroll->computer_attributes);
+ enroll->computer_attributes = NULL;
+ adcli_enroll_set_kvno (enroll, 0);
+ }
+
res = set_computer_password (enroll);
if (res != ADCLI_SUCCESS)
return res;
@@ -1651,6 +1673,15 @@ enroll_join_or_update_tasks (adcli_enroll *enroll,
return res;
}
+ /* Handle kvno changes for read-only domain controllers (RODC) */
+ if (!adcli_conn_is_writeable (enroll->conn) && old_kvno != -1 &&
+ adcli_enroll_get_kvno (enroll) != 0 &&
+ adcli_enroll_get_kvno (enroll) == old_kvno) {
+ enroll->kvno++;
+ _adcli_info ("No kvno change detected on read-only DC, kvno "
+ "will be incremented by 1 to '%d'", enroll->kvno);
+ }
+
/* We ignore failures of setting these fields */
update_and_calculate_enctypes (enroll);
update_computer_account (enroll);
--
2.11.0
From 2f08e7992d484563c29a1db979e2a95691dbb170 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:37:05 +0100
Subject: [PATCH 09/30] library: add _adcli_bin_sid_to_str()
Convert a binary SID to the string representation.
https://bugs.freedesktop.org/show_bug.cgi?id=100118
https://gitlab.freedesktop.org/realmd/adcli/issues/6
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
library/adprivate.h | 4 ++
library/adutil.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+)
diff --git a/library/adprivate.h b/library/adprivate.h
index fc146af..e99f9fc 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -31,6 +31,7 @@
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdint.h>
#include <ldap.h>
@@ -132,6 +133,9 @@ int _adcli_str_has_prefix (const char *str,
int _adcli_str_has_suffix (const char *str,
const char *suffix);
+char * _adcli_bin_sid_to_str (const uint8_t *data,
+ size_t len);
+
char * _adcli_str_dupn (void *data,
size_t len);
diff --git a/library/adutil.c b/library/adutil.c
index 21ccd27..a057763 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -294,6 +294,83 @@ _adcli_strv_set (char ***field,
}
char *
+_adcli_bin_sid_to_str (const uint8_t *data,
+ size_t len)
+{
+ uint8_t sid_rev_num;
+ int8_t num_auths;
+ uint8_t id_auth[6];
+ uint32_t id_auth_val;
+ uint32_t sub_auths[15];
+ uint32_t val;
+ size_t p = 0;
+ size_t c;
+ int nc;
+ char *sid_buf;
+ size_t sid_buf_len;
+
+ if (data == NULL || len < 8) {
+ return NULL;
+ }
+
+ sid_rev_num = (uint8_t) data [p];
+ p++;
+
+ num_auths = (int8_t) data[p];
+ p++;
+
+ if (num_auths > 15 || len < 8 + (num_auths * sizeof (uint32_t))) {
+ return NULL;
+ }
+
+ for (c = 0; c < 6; c++) {
+ id_auth[c] = (uint8_t) data[p];
+ p++;
+ }
+
+ /* Only 32bits are used for the string representation */
+ id_auth_val = (id_auth[2] << 24) +
+ (id_auth[3] << 16) +
+ (id_auth[4] << 8) +
+ (id_auth[5]);
+
+ for (c = 0; c < num_auths; c++) {
+ memcpy (&val, data + p, sizeof (uint32_t));
+ sub_auths[c] = le32toh (val);
+
+ p += sizeof (uint32_t);
+ }
+
+ sid_buf_len = 17 + (num_auths * 11);
+ sid_buf = calloc (1, sid_buf_len);
+ if (sid_buf == NULL) {
+ return NULL;
+ }
+
+ nc = snprintf (sid_buf, sid_buf_len, "S-%u-%lu", sid_rev_num,
+ (unsigned long) id_auth_val);
+ if (nc < 0 || nc >= sid_buf_len) {
+ free (sid_buf);
+ return NULL;
+ }
+
+ p = 0;
+ for (c = 0; c < num_auths; c++) {
+ p += nc;
+ sid_buf_len -= nc;
+
+ nc = snprintf (sid_buf + p, sid_buf_len, "-%lu",
+ (unsigned long) sub_auths[c]);
+ if (nc < 0 || nc >= sid_buf_len) {
+ free (sid_buf);
+ return NULL;
+ }
+ }
+
+ return sid_buf;
+}
+
+char *
_adcli_str_dupn (void *data,
size_t len)
{
@@ -507,6 +584,41 @@ test_check_nt_time_string_lifetime (void)
assert (_adcli_check_nt_time_string_lifetime ("130645404000000000", 100000));
}
+static void
+test_bin_sid_to_str (void)
+{
+ uint8_t sid1[] = { 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x15, 0x00, 0x00, 0x00, 0xF8, 0x12, 0x13, 0xDC,
+ 0x47, 0xF3, 0x1C, 0x76, 0x47, 0x2F, 0x2E, 0xD7,
+ 0x51, 0x04, 0x00, 0x00 };
+
+ uint8_t sid2[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x15, 0x00, 0x00, 0x00, 0xF8, 0x12, 0x13, 0xDC,
+ 0x47, 0xF3, 0x1C, 0x76, 0x47, 0x2F, 0x2E, 0xD7};
+
+ uint8_t sid3[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x15, 0x00, 0x00, 0x00, 0x29, 0xC9, 0x4F, 0xD9,
+ 0xC2, 0x3C, 0xC3, 0x78, 0x36, 0x55, 0x87, 0xF8};
+
+
+ char *str;
+
+ str = _adcli_bin_sid_to_str (sid1, sizeof (sid1));
+ assert (str != NULL);
+ assert (strcmp (str, "S-1-5-21-3692237560-1981608775-3610128199-1105") == 0);
+ free (str);
+
+ str = _adcli_bin_sid_to_str (sid2, sizeof (sid2));
+ assert (str != NULL);
+ assert (strcmp (str, "S-1-5-21-3692237560-1981608775-3610128199") == 0);
+ free (str);
+
+ str = _adcli_bin_sid_to_str (sid3, sizeof (sid2));
+ assert (str != NULL);
+ assert (strcmp (str, "S-1-5-21-3645884713-2026060994-4169618742") == 0);
+ free (str);
+}
+
int
main (int argc,
char *argv[])
@@ -515,6 +627,7 @@ main (int argc,
test_func (test_strv_dup, "/util/strv_dup");
test_func (test_strv_count, "/util/strv_count");
test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime");
+ test_func (test_bin_sid_to_str, "/util/bin_sid_to_str");
return test_run (argc, argv);
}
--
2.11.0
From e25c49fc8be4df614e74a98e0d5dfecbf0af6020 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:39:17 +0100
Subject: [PATCH 10/30] library: add _adcli_call_external_program()
Allow adcli to call an external program given by an absolute path name
and an array of options. stdin and stdout can be used if needed.
https://bugs.freedesktop.org/show_bug.cgi?id=100118
https://gitlab.freedesktop.org/realmd/adcli/issues/6
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
configure.ac | 28 +++++++
library/adprivate.h | 6 ++
library/adutil.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 245 insertions(+)
diff --git a/configure.ac b/configure.ac
index 221d8ae..fe86638 100644
--- a/configure.ac
+++ b/configure.ac
@@ -263,6 +263,34 @@ AC_SUBST(LCOV)
AC_SUBST(GCOV)
AC_SUBST(GENHTML)
+AC_PATH_PROG(BIN_CAT, cat, no)
+if test "$BIN_CAT" = "no" ; then
+ AC_MSG_ERROR([cat is not available])
+else
+ AC_DEFINE_UNQUOTED(BIN_CAT, "$BIN_CAT", [path to cat, used in unit test])
+fi
+
+AC_PATH_PROG(BIN_TAC, tac, no)
+if test "$BIN_TAC" = "no" ; then
+ AC_MSG_ERROR([tac is not available])
+else
+ AC_DEFINE_UNQUOTED(BIN_TAC, "$BIN_TAC", [path to tac, used in unit test])
+fi
+
+AC_PATH_PROG(BIN_REV, rev, no)
+if test "$BIN_REV" = "no" ; then
+ AC_MSG_ERROR([rev is not available])
+else
+ AC_DEFINE_UNQUOTED(BIN_REV, "$BIN_REV", [path to rev, used in unit test])
+fi
+
+AC_PATH_PROG(BIN_ECHO, echo, no)
+if test "$BIN_ECHO" = "no" ; then
+ AC_MSG_ERROR([echo is not available])
+else
+ AC_DEFINE_UNQUOTED(BIN_ECHO, "$BIN_ECHO", [path to echo, used in unit test])
+fi
+
# ---------------------------------------------------------------------
ADCLI_LT_RELEASE=$ADCLI_CURRENT:$ADCLI_REVISION:$ADCLI_AGE
diff --git a/library/adprivate.h b/library/adprivate.h
index e99f9fc..7257c93 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -285,4 +285,10 @@ struct _adcli_attrs {
bool _adcli_check_nt_time_string_lifetime (const char *nt_time_string, unsigned int lifetime);
+adcli_result _adcli_call_external_program (const char *binary,
+ char * const *argv,
+ const char *stdin_data,
+ uint8_t **stdout_data,
+ size_t *stdout_data_len);
+
#endif /* ADPRIVATE_H_ */
diff --git a/library/adutil.c b/library/adutil.c
index a057763..14df42e 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -36,6 +36,7 @@
#include <unistd.h>
#include <stdint.h>
#include <time.h>
+#include <sys/wait.h>
static adcli_message_func message_func = NULL;
static char last_error[2048] = { 0, };
@@ -506,6 +507,161 @@ _adcli_check_nt_time_string_lifetime (const char *nt_time_string,
return false;
}
+adcli_result
+_adcli_call_external_program (const char *binary, char * const *argv,
+ const char *stdin_data,
+ uint8_t **stdout_data, size_t *stdout_data_len)
+{
+ int ret;
+ int pipefd_to_child[2] = { -1, -1};
+ int pipefd_from_child[2] = { -1, -1};
+ pid_t child_pid = 0;
+ int err;
+ size_t len;
+ ssize_t rlen;
+ pid_t wret;
+ int status;
+ uint8_t read_buf[4096];
+ uint8_t *out;
+
+ errno = 0;
+ ret = access (binary, X_OK);
+ if (ret != 0) {
+ err = errno;
+ _adcli_err ("Cannot run [%s]: [%d][%s].", binary, err,
+ strerror (err));
+ ret = ADCLI_ERR_FAIL;
+ goto done;
+ }
+
+ ret = pipe (pipefd_from_child);
+ if (ret == -1) {
+ err = errno;
+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err));
+ ret = ADCLI_ERR_FAIL;
+ goto done;
+ }
+
+ ret = pipe (pipefd_to_child);
+ if (ret == -1) {
+ err = errno;
+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err));
+ ret = ADCLI_ERR_FAIL;
+ goto done;
+ }
+
+ child_pid = fork ();
+
+ if (child_pid == 0) { /* child */
+ close (pipefd_to_child[1]);
+ ret = dup2 (pipefd_to_child[0], STDIN_FILENO);
+ if (ret == -1) {
+ err = errno;
+ _adcli_err ("dup2 failed [%d][%s].", err,
+ strerror (err));
+ exit (EXIT_FAILURE);
+ }