various fixes and improvements

Resolves: rhbz#1593240, rhbz#1608212, rhbz#1547014, rhbz#1547014,
          rhbz#1649868, rhbz#1588596, rhbz#1642546, rhbz#1595911,
          rhbz#1644311, rhbz#1337489, rhbz#1630187, rhbz#1622583
This commit is contained in:
Sumit Bose 2019-03-22 18:30:43 +01:00
parent 8490450af9
commit 8fc58f61c3
19 changed files with 1435 additions and 26 deletions

View File

@ -0,0 +1,181 @@
From 6fd99ff6c5dd6ef0be8d942989b1c6dcee3102d9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Mar 2019 12:37:39 +0100
Subject: [PATCH] Implement 'adcli testjoin'
By calling adcli testjoin it will be checked if the host credentials
stored in the keytab are still valid.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1622583
---
doc/adcli.xml | 34 +++++++++++++++++++++++
tools/computer.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
tools/tools.c | 1 +
tools/tools.h | 4 +++
4 files changed, 111 insertions(+)
diff --git a/doc/adcli.xml b/doc/adcli.xml
index af73433..9605b4a 100644
--- a/doc/adcli.xml
+++ b/doc/adcli.xml
@@ -43,6 +43,9 @@
<cmdsynopsis>
<command>adcli update</command>
</cmdsynopsis>
+ <cmdsynopsis>
+ <command>adcli testjoin</command>
+ </cmdsynopsis>
<cmdsynopsis>
<command>adcli create-user</command>
<arg choice="opt">--domain=domain.example.com</arg>
@@ -474,6 +477,37 @@ $ adcli update --login-ccache=/tmp/krbcc_123
</refsect1>
+<refsect1 id='testjoin'>
+ <title>Testing if the machine account password is valid</title>
+
+ <para><command>adcli testjoin</command> uses the current credentials in
+ the keytab and tries to authenticate with the machine account to the AD
+ domain. If this works the machine account password and the join are
+ still valid. If it fails the machine account password or the whole
+ machine account have to be refreshed with
+ <command>adcli join</command> or <command>adcli update</command>.
+ </para>
+
+<programlisting>
+$ adcli testjoin
+</programlisting>
+
+ <para>Only the global options not related to authentication are
+ available, additionally you can specify the following options to
+ control how this operation is done.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-K, --host-keytab=<parameter>/path/to/keytab</parameter></option></term>
+ <listitem><para>Specify the path to the host keytab where
+ current host credentials are stored and the new ones
+ will be written to. If not specified, the default
+ location will be used, usually
+ <filename>/etc/krb5.keytab</filename>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+</refsect1>
+
<refsect1 id='create_user'>
<title>Creating a User</title>
diff --git a/tools/computer.c b/tools/computer.c
index 112340e..610ed2b 100644
--- a/tools/computer.c
+++ b/tools/computer.c
@@ -566,6 +566,78 @@ adcli_tool_computer_update (adcli_conn *conn,
return 0;
}
+int
+adcli_tool_computer_testjoin (adcli_conn *conn,
+ int argc,
+ char *argv[])
+{
+ adcli_enroll *enroll;
+ adcli_result res;
+ const char *ktname;
+ int opt;
+
+ struct option options[] = {
+ { "domain", required_argument, NULL, opt_domain },
+ { "domain-controller", required_argument, NULL, opt_domain_controller },
+ { "host-keytab", required_argument, 0, opt_host_keytab },
+ { "verbose", no_argument, NULL, opt_verbose },
+ { "help", no_argument, NULL, 'h' },
+ { 0 },
+ };
+
+ static adcli_tool_desc usages[] = {
+ { 0, "usage: adcli testjoin" },
+ { 0 },
+ };
+
+ enroll = adcli_enroll_new (conn);
+ if (enroll == NULL)
+ errx (-1, "unexpected memory problems");
+
+ while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) {
+ switch (opt) {
+ case 'h':
+ case '?':
+ case ':':
+ adcli_tool_usage (options, usages);
+ adcli_tool_usage (options, common_usages);
+ adcli_enroll_unref (enroll);
+ return opt == 'h' ? 0 : 2;
+ default:
+ parse_option ((Option)opt, optarg, conn, enroll);
+ break;
+ }
+ }
+
+ /* Force use of a keytab to test the join/machine account password */
+ adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_COMPUTER_ACCOUNT);
+ ktname = adcli_enroll_get_keytab_name (enroll);
+ adcli_conn_set_login_keytab_name (conn, ktname ? ktname : "");
+
+ res = adcli_enroll_load (enroll);
+ if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
+ errx (-res, "couldn't lookup domain info from keytab: %s",
+ adcli_get_last_error ());
+ }
+
+ res = adcli_conn_connect (conn);
+ if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
+ errx (-res, "couldn't connect to %s domain: %s",
+ adcli_conn_get_domain_name (conn),
+ adcli_get_last_error ());
+ }
+
+ printf ("Sucessfully validated join to domain %s\n",
+ adcli_conn_get_domain_name (conn));
+
+ adcli_enroll_unref (enroll);
+
+ return 0;
+}
int
adcli_tool_computer_preset (adcli_conn *conn,
diff --git a/tools/tools.c b/tools/tools.c
index 915130e..c4e2851 100644
--- a/tools/tools.c
+++ b/tools/tools.c
@@ -55,6 +55,7 @@ struct {
{ "info", adcli_tool_info, "Print information about a domain", CONNECTION_LESS },
{ "join", adcli_tool_computer_join, "Join this machine to a domain", },
{ "update", adcli_tool_computer_update, "Update machine membership in a domain", },
+ { "testjoin", adcli_tool_computer_testjoin, "Test if machine account password is valid", },
{ "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 account", },
diff --git a/tools/tools.h b/tools/tools.h
index 6c97ccf..8cebbf9 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -70,6 +70,10 @@ int adcli_tool_computer_update (adcli_conn *conn,
int argc,
char *argv[]);
+int adcli_tool_computer_testjoin (adcli_conn *conn,
+ int argc,
+ char *argv[]);
+
int adcli_tool_computer_delete (adcli_conn *conn,
int argc,
char *argv[]);
--
2.20.1

View File

@ -0,0 +1,32 @@
From 5cf1723c308e21cdbe9b98ed2aaa42cb997456fb Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 15 Mar 2019 14:31:12 +0100
Subject: [PATCH] Increment kvno after password change with user creds
Originally only the host credential part was fixed in the context of
https://bugs.freedesktop.org/show_bug.cgi?id=91185. This patch adds the
fix to the case when user credentials are used.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1642546
---
library/adenroll.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/library/adenroll.c b/library/adenroll.c
index e02f403..58362c2 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1057,6 +1057,10 @@ set_password_with_user_creds (adcli_enroll *enroll)
#endif
} else {
_adcli_info ("Set computer password");
+ if (enroll->kvno > 0) {
+ enroll->kvno++;
+ _adcli_info ("kvno incremented to %d", enroll->kvno);
+ }
res = ADCLI_SUCCESS;
}
--
2.20.1

View File

@ -0,0 +1,134 @@
From 85d127fd52a8469f9f3ce0d1130fe17e756fdd75 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 16 Nov 2018 13:32:33 +0100
Subject: [PATCH 1/2] adutil: add _adcli_strv_add_unique
_adcli_strv_add_unique checks is the new value already exists in the
strv before adding it. Check can be done case-sensitive or not.
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/16
---
library/adprivate.h | 5 ++++
library/adutil.c | 65 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/library/adprivate.h b/library/adprivate.h
index bc9df6d..0806430 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -111,6 +111,11 @@ char ** _adcli_strv_add (char **strv,
char *string,
int *length) GNUC_WARN_UNUSED;
+char ** _adcli_strv_add_unique (char **strv,
+ char *string,
+ int *length,
+ bool case_sensitive) GNUC_WARN_UNUSED;
+
void _adcli_strv_remove_unsorted (char **strv,
const char *string,
int *length);
diff --git a/library/adutil.c b/library/adutil.c
index 17d2caa..76ea158 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -221,6 +221,34 @@ _adcli_strv_add (char **strv,
return seq_push (strv, length, string);
}
+static int
+_adcli_strv_has_ex (char **strv,
+ const char *str,
+ int (* compare) (const char *match, const char*value))
+{
+ int i;
+
+ for (i = 0; strv && strv[i] != NULL; i++) {
+ if (compare (strv[i], str) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+char **
+_adcli_strv_add_unique (char **strv,
+ char *string,
+ int *length,
+ bool case_sensitive)
+{
+ if (_adcli_strv_has_ex (strv, string, case_sensitive ? strcmp : strcasecmp) == 1) {
+ return strv;
+ }
+
+ return _adcli_strv_add (strv, string, length);
+}
+
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
void
@@ -241,19 +269,11 @@ _adcli_strv_remove_unsorted (char **strv,
(seq_compar)strcasecmp, free);
}
-
int
_adcli_strv_has (char **strv,
const char *str)
{
- int i;
-
- for (i = 0; strv && strv[i] != NULL; i++) {
- if (strcmp (strv[i], str) == 0)
- return 1;
- }
-
- return 0;
+ return _adcli_strv_has_ex (strv, str, strcmp);
}
void
@@ -704,6 +724,32 @@ test_strv_add_free (void)
_adcli_strv_free (strv);
}
+static void
+test_strv_add_unique_free (void)
+{
+ char **strv = NULL;
+
+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("tWo"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("TWO"), NULL, true);
+
+ assert_num_eq (_adcli_strv_len (strv), 4);
+
+ assert_str_eq (strv[0], "one");
+ assert_str_eq (strv[1], "two");
+ assert_str_eq (strv[2], "three");
+ assert_str_eq (strv[3], "TWO");
+ assert (strv[4] == NULL);
+
+ _adcli_strv_free (strv);
+}
+
+
static void
test_strv_dup (void)
{
@@ -856,6 +902,7 @@ main (int argc,
char *argv[])
{
test_func (test_strv_add_free, "/util/strv_add_free");
+ test_func (test_strv_add_unique_free, "/util/strv_add_unique_free");
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");
--
2.20.1

View File

@ -0,0 +1,71 @@
From 1457b4a7623a8ae58fb8d6a652d1cc44904b8863 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 18 Mar 2019 11:02:57 +0100
Subject: [PATCH 1/2] create-user: add nis-domain option
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/2
---
doc/adcli.xml | 8 ++++++++
tools/entry.c | 6 ++++++
2 files changed, 14 insertions(+)
diff --git a/doc/adcli.xml b/doc/adcli.xml
index 4722c3a..18620c0 100644
--- a/doc/adcli.xml
+++ b/doc/adcli.xml
@@ -531,6 +531,14 @@ $ adcli create-user Fry --domain=domain.example.com \
the new created user account, which should be the user's
numeric primary user id.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--nis-domain=<parameter>nis_domain</parameter></option></term>
+ <listitem><para>Set the <code>msSFU30NisDomain</code> attribute of
+ the new created user account, which should be the user's
+ NIS domain is the NIS/YP service of Active Directory's Services for Unix (SFU)
+ are used. This is needed to let the 'UNIX attributes' tab of older Active
+ Directoy versions show the set UNIX specific attributes.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/tools/entry.c b/tools/entry.c
index 7b6a200..69ce62c 100644
--- a/tools/entry.c
+++ b/tools/entry.c
@@ -52,6 +52,7 @@ typedef enum {
opt_unix_uid,
opt_unix_gid,
opt_unix_shell,
+ opt_nis_domain,
} Option;
static adcli_tool_desc common_usages[] = {
@@ -62,6 +63,7 @@ static adcli_tool_desc common_usages[] = {
{ opt_unix_uid, "unix uid number" },
{ opt_unix_gid, "unix gid number" },
{ opt_unix_shell, "unix shell" },
+ { opt_nis_domain, "NIS domain" },
{ opt_domain, "active directory domain name" },
{ opt_domain_realm, "kerberos realm for the domain" },
{ opt_domain_controller, "domain directory server to connect to" },
@@ -159,6 +161,7 @@ adcli_tool_user_create (adcli_conn *conn,
{ "unix-uid", required_argument, NULL, opt_unix_uid },
{ "unix-gid", required_argument, NULL, opt_unix_gid },
{ "unix-shell", required_argument, NULL, opt_unix_shell },
+ { "nis-domain", required_argument, NULL, opt_nis_domain },
{ "domain-ou", required_argument, NULL, opt_domain_ou },
{ "domain", required_argument, NULL, opt_domain },
{ "domain-realm", required_argument, NULL, opt_domain_realm },
@@ -200,6 +203,9 @@ adcli_tool_user_create (adcli_conn *conn,
case opt_unix_shell:
adcli_attrs_add (attrs, "loginShell", optarg, NULL);
break;
+ case opt_nis_domain:
+ adcli_attrs_add (attrs, "msSFU30NisDomain", optarg, NULL);
+ break;
case opt_domain_ou:
ou = optarg;
break;
--
2.20.1

View File

@ -0,0 +1,72 @@
From 3a84c2469c31967bc22c0490456f07723ef5fc86 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 20 Mar 2019 11:01:50 +0100
Subject: [PATCH 1/4] ensure_keytab_principals: do not leak memory when called
twice
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187
---
library/adenroll.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index d1f746c..48cb4cf 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -413,6 +413,25 @@ ensure_service_principals (adcli_result res,
return res;
}
+static void enroll_clear_keytab_principals (adcli_enroll *enroll)
+{
+ krb5_context k5;
+ size_t c;
+
+ if (enroll->keytab_principals) {
+ k5 = adcli_conn_get_krb5_context (enroll->conn);
+ return_if_fail (k5 != NULL);
+
+ for (c = 0; enroll->keytab_principals[c] != NULL; c++)
+ krb5_free_principal (k5, enroll->keytab_principals[c]);
+
+ free (enroll->keytab_principals);
+ enroll->keytab_principals = NULL;
+ }
+
+ return;
+}
+
static adcli_result
ensure_keytab_principals (adcli_result res,
adcli_enroll *enroll)
@@ -430,6 +449,7 @@ ensure_keytab_principals (adcli_result res,
k5 = adcli_conn_get_krb5_context (enroll->conn);
return_unexpected_if_fail (k5 != NULL);
+ enroll_clear_keytab_principals (enroll);
enroll->keytab_principals = calloc (count + 3, sizeof (krb5_principal));
return_unexpected_if_fail (enroll->keytab_principals != NULL);
at = 0;
@@ -1860,18 +1880,8 @@ static void
enroll_clear_state (adcli_enroll *enroll)
{
krb5_context k5;
- int i;
-
- if (enroll->keytab_principals) {
- k5 = adcli_conn_get_krb5_context (enroll->conn);
- return_if_fail (k5 != NULL);
-
- for (i = 0; enroll->keytab_principals[i] != NULL; i++)
- krb5_free_principal (k5, enroll->keytab_principals[i]);
- free (enroll->keytab_principals);
- enroll->keytab_principals = NULL;
- }
+ enroll_clear_keytab_principals (enroll);
if (enroll->keytab) {
k5 = adcli_conn_get_krb5_context (enroll->conn);
--
2.20.1

View File

@ -0,0 +1,25 @@
From 870ecd8f982ebb97092a93d730ad4006bd78505c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 8 Aug 2018 12:03:01 +0200
Subject: [PATCH 1/4] fix typo in flag value
---
library/adenroll.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/adenroll.h b/library/adenroll.h
index f87dffa..abbbfd4 100644
--- a/library/adenroll.h
+++ b/library/adenroll.h
@@ -30,7 +30,7 @@ typedef enum {
ADCLI_ENROLL_NO_KEYTAB = 1 << 1,
ADCLI_ENROLL_ALLOW_OVERWRITE = 1 << 2,
ADCLI_ENROLL_PASSWORD_VALID = 1 << 3,
- ADCLI_ENROLL_ADD_SAMBA_DATA = 1 << 3,
+ ADCLI_ENROLL_ADD_SAMBA_DATA = 1 << 4,
} adcli_enroll_flags;
typedef struct _adcli_enroll adcli_enroll;
--
2.17.1

View File

@ -0,0 +1,86 @@
From cd296bf24e7cc56fb8d00bad7e9a56c539894309 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 19 Mar 2019 20:44:36 +0100
Subject: [PATCH 1/2] join: always add service principals
If currently --service-name is given during the join only the service
names given by this option are added as service principal names. As a
result the default 'host' service principal name might be missing which
might cause issues e.g. with SSSD and sshd.
The patch makes sure the default service principals 'host' and
'RestrictedKrbHost' are always added during join.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1644311
---
library/adenroll.c | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index 58362c2..d1f746c 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -288,16 +288,23 @@ ensure_computer_password (adcli_result res,
}
static adcli_result
-ensure_service_names (adcli_result res,
- adcli_enroll *enroll)
+ensure_default_service_names (adcli_enroll *enroll)
{
int length = 0;
- if (res != ADCLI_SUCCESS)
- return res;
+ if (enroll->service_names != NULL) {
+ length = seq_count (enroll->service_names);
- if (enroll->service_names || enroll->service_principals)
- return ADCLI_SUCCESS;
+ /* Make sure there is no entry with an unexpected case. AD
+ * would not care but since the client side is case-sensitive
+ * we should make sure we use the expected spelling. */
+ seq_remove_unsorted (enroll->service_names,
+ &length, "host",
+ (seq_compar)strcasecmp, free);
+ seq_remove_unsorted (enroll->service_names,
+ &length, "RestrictedKrbHost",
+ (seq_compar)strcasecmp, free);
+ }
/* The default ones specified by MS */
enroll->service_names = _adcli_strv_add (enroll->service_names,
@@ -307,6 +314,19 @@ ensure_service_names (adcli_result res,
return ADCLI_SUCCESS;
}
+static adcli_result
+ensure_service_names (adcli_result res,
+ adcli_enroll *enroll)
+{
+ if (res != ADCLI_SUCCESS)
+ return res;
+
+ if (enroll->service_names || enroll->service_principals)
+ return ADCLI_SUCCESS;
+
+ return ensure_default_service_names (enroll);
+}
+
static adcli_result
add_service_names_to_service_principals (adcli_enroll *enroll)
{
@@ -2039,6 +2059,10 @@ adcli_enroll_join (adcli_enroll *enroll,
if (res != ADCLI_SUCCESS)
return res;
+ res = ensure_default_service_names (enroll);
+ if (res != ADCLI_SUCCESS)
+ return res;
+
res = adcli_enroll_prepare (enroll, flags);
if (res != ADCLI_SUCCESS)
return res;
--
2.20.1

View File

@ -0,0 +1,92 @@
From 85b835f8258a57e3b23de47a255dddd822d5bfb3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 15 Mar 2019 17:33:44 +0100
Subject: [PATCH] library: use getaddrinfo with AI_CANONNAME to find a FQDN
Currently adcli creates service principals only with a short name if the
hostname of the client is a short name. This would fail is
Kerberos/GSSAPI clients will use the fully-qualified domain name (FQDN)
to access the host.
With this patch adcli tries to expand the short name by calling
getaddrinfo with the AI_CANONNAME hint.
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/1
---
doc/adcli.xml | 6 +++++-
library/adconn.c | 30 +++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/doc/adcli.xml b/doc/adcli.xml
index 97dec08..4722c3a 100644
--- a/doc/adcli.xml
+++ b/doc/adcli.xml
@@ -228,7 +228,11 @@ Password for Administrator:
<term><option>-H, --host-fqdn=<parameter>host</parameter></option></term>
<listitem><para>Override the local machine's fully qualified
domain name. If not specified, the local machine's hostname
- will be retrieved via <function>gethostname()</function>.</para></listitem>
+ will be retrieved via <function>gethostname()</function>.
+ If <function>gethostname()</function> only returns a short name
+ <function>getaddrinfo()</function> with the AI_CANONNAME hint
+ is called to expand the name to a fully qualified domain
+ name.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-K, --host-keytab=<parameter>/path/to/keytab</parameter></option></term>
diff --git a/library/adconn.c b/library/adconn.c
index e2250e3..f6c23d3 100644
--- a/library/adconn.c
+++ b/library/adconn.c
@@ -86,11 +86,36 @@ struct _adcli_conn_ctx {
krb5_keytab keytab;
};
+static char *try_to_get_fqdn (const char *host_name)
+{
+ int ret;
+ char *fqdn = NULL;
+ struct addrinfo *res;
+ struct addrinfo hints;
+
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_CANONNAME;
+
+ ret = getaddrinfo (host_name, NULL, &hints, &res);
+ if (ret != 0) {
+ _adcli_err ("Failed to find FQDN: %s", gai_strerror (ret));
+ return NULL;
+ }
+
+ fqdn = strdup (res->ai_canonname);
+
+ freeaddrinfo (res);
+
+ return fqdn;
+}
+
static adcli_result
ensure_host_fqdn (adcli_result res,
adcli_conn *conn)
{
char hostname[HOST_NAME_MAX + 1];
+ char *fqdn = NULL;
int ret;
if (res != ADCLI_SUCCESS)
@@ -107,7 +132,10 @@ ensure_host_fqdn (adcli_result res,
return ADCLI_ERR_UNEXPECTED;
}
- conn->host_fqdn = strdup (hostname);
+ if (strchr (hostname, '.') == NULL) {
+ fqdn = try_to_get_fqdn (hostname);
+ }
+ conn->host_fqdn = fqdn != NULL ? fqdn : strdup (hostname);
return_unexpected_if_fail (conn->host_fqdn != NULL);
return ADCLI_SUCCESS;
}
--
2.20.1

View File

@ -0,0 +1,152 @@
From 41fdcb1af885d99a91e27406e9343b322f67756a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 28 Jun 2018 20:13:26 +0200
Subject: [PATCH] tools: properly release internal data on error
Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1588596
---
tools/computer.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/tools/computer.c b/tools/computer.c
index 3813f0a..112340e 100644
--- a/tools/computer.c
+++ b/tools/computer.c
@@ -415,11 +415,16 @@ adcli_tool_computer_join (adcli_conn *conn,
if (argc == 1)
adcli_conn_set_domain_name (conn, argv[0]);
- else if (argc > 1)
+ else if (argc > 1) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (2, "extra arguments specified");
+ }
res = adcli_conn_connect (conn);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't connect to %s domain: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -427,6 +432,8 @@ adcli_tool_computer_join (adcli_conn *conn,
res = adcli_enroll_join (enroll, flags);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "joining domain %s failed: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -525,12 +532,16 @@ adcli_tool_computer_update (adcli_conn *conn,
res = adcli_enroll_load (enroll);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't lookup domain info from keytab: %s",
adcli_get_last_error ());
}
res = adcli_conn_connect (conn);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't connect to %s domain: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -538,6 +549,8 @@ adcli_tool_computer_update (adcli_conn *conn,
res = adcli_enroll_update (enroll, flags);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "updating membership with domain %s failed: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -630,6 +643,8 @@ adcli_tool_computer_preset (adcli_conn *conn,
res = adcli_conn_connect (conn);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't connect to %s domain: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -643,6 +658,8 @@ adcli_tool_computer_preset (adcli_conn *conn,
res = adcli_enroll_join (enroll, flags);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "presetting %s in %s domain failed: %s", argv[i],
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -707,11 +724,16 @@ adcli_tool_computer_reset (adcli_conn *conn,
argc -= optind;
argv += optind;
- if (argc != 1)
+ if (argc != 1) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (EUSAGE, "specify one host name of computer account to reset");
+ }
res = adcli_conn_connect (conn);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't connect to %s domain: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -722,6 +744,8 @@ adcli_tool_computer_reset (adcli_conn *conn,
res = adcli_enroll_password (enroll, 0);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "resetting %s in %s domain failed: %s", argv[0],
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -781,19 +805,26 @@ adcli_tool_computer_delete (adcli_conn *conn,
argc -= optind;
argv += optind;
- if (argc > 1)
+ if (argc > 1) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (EUSAGE, "specify one host name of computer account to delete");
+ }
adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT);
res = adcli_enroll_load (enroll);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't lookup domain info from keytab: %s",
adcli_get_last_error ());
}
res = adcli_conn_connect (conn);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "couldn't connect to %s domain: %s",
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
@@ -804,6 +835,8 @@ adcli_tool_computer_delete (adcli_conn *conn,
res = adcli_enroll_delete (enroll, 0);
if (res != ADCLI_SUCCESS) {
+ adcli_enroll_unref (enroll);
+ adcli_conn_unref (conn);
errx (-res, "deleting %s in %s domain failed: %s", argv[0],
adcli_conn_get_domain_name (conn),
adcli_get_last_error ());
--
2.20.1

View File

@ -0,0 +1,25 @@
From 8cc4ef1cae7d4d753f2cf9aeb8021dd96cb75d36 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 8 Aug 2018 12:17:18 +0200
Subject: [PATCH 2/4] _adcli_call_external_program: silence noisy debug message
---
library/adutil.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/adutil.c b/library/adutil.c
index 6334b52..17d2caa 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -672,7 +672,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.17.1

View File

@ -0,0 +1,83 @@
From 0c027538f398b3823bedbfbf5f388ad97784a0ec Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 16 Nov 2018 13:32:59 +0100
Subject: [PATCH 2/2] adenroll: use _adcli_strv_add_unique for service
principals
Check if service principals is already in the list before adding it.
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/16
---
library/adenroll.c | 31 ++++++++-----------------------
1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index de2242a..e02f403 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -313,7 +313,6 @@ add_service_names_to_service_principals (adcli_enroll *enroll)
char *name;
int length = 0;
int i;
- size_t c;
if (enroll->service_principals != NULL) {
length = seq_count (enroll->service_principals);
@@ -322,28 +321,14 @@ add_service_names_to_service_principals (adcli_enroll *enroll)
for (i = 0; enroll->service_names[i] != NULL; i++) {
if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0)
return_unexpected_if_reached ();
- for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) {
- if (strcmp (name, enroll->service_principals[c]) == 0) {
- break;
- }
- }
- if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) {
- enroll->service_principals = _adcli_strv_add (enroll->service_principals,
- name, &length);
- }
+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals,
+ name, &length, false);
if (enroll->host_fqdn) {
if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0)
return_unexpected_if_reached ();
- for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) {
- if (strcmp (name, enroll->service_principals[c]) == 0) {
- break;
- }
- }
- if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) {
- enroll->service_principals = _adcli_strv_add (enroll->service_principals,
- name, &length);
- }
+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals,
+ name, &length, false);
}
}
@@ -364,9 +349,9 @@ add_and_remove_service_principals (adcli_enroll *enroll)
list = adcli_enroll_get_service_principals_to_add (enroll);
if (list != NULL) {
for (c = 0; list[c] != NULL; c++) {
- enroll->service_principals = _adcli_strv_add (enroll->service_principals,
- strdup (list[c]),
- &length);
+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals,
+ strdup (list[c]),
+ &length, false);
if (enroll->service_principals == NULL) {
return ADCLI_ERR_UNEXPECTED;
}
@@ -1525,7 +1510,7 @@ load_keytab_entry (krb5_context k5,
value = strdup (name);
return_val_if_fail (value != NULL, FALSE);
_adcli_info ("Found service principal in keytab: %s", value);
- enroll->service_principals = _adcli_strv_add (enroll->service_principals, value, NULL);
+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, value, NULL, false);
}
}
--
2.20.1

View File

@ -0,0 +1,147 @@
From 408880a11879b1a57a450e25c77ef2e310bdffd5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 18 Mar 2019 16:45:54 +0100
Subject: [PATCH 2/2] create-user: try to find NIS domain if needed
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/2
---
doc/adcli.xml | 4 +++-
library/adentry.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
library/adentry.h | 2 ++
tools/entry.c | 16 ++++++++++++++++
4 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/doc/adcli.xml b/doc/adcli.xml
index 18620c0..af73433 100644
--- a/doc/adcli.xml
+++ b/doc/adcli.xml
@@ -537,7 +537,9 @@ $ adcli create-user Fry --domain=domain.example.com \
the new created user account, which should be the user's
NIS domain is the NIS/YP service of Active Directory's Services for Unix (SFU)
are used. This is needed to let the 'UNIX attributes' tab of older Active
- Directoy versions show the set UNIX specific attributes.</para></listitem>
+ Directoy versions show the set UNIX specific attributes. If not specified
+ adcli will try to determine the NIS domain automatically if needed.
+ </para></listitem>
</varlistentry>
</variablelist>
diff --git a/library/adentry.c b/library/adentry.c
index 9b9e1c6..1cc0518 100644
--- a/library/adentry.c
+++ b/library/adentry.c
@@ -484,3 +484,47 @@ adcli_entry_new_group (adcli_conn *conn,
return_val_if_fail (sam_name != NULL, NULL);
return entry_new (conn, "group", group_entry_builder, sam_name);
}
+
+adcli_result
+adcli_get_nis_domain (adcli_entry *entry,
+ adcli_attrs *attrs)
+{
+ LDAP *ldap;
+ const char *ldap_attrs[] = { "cn", NULL };
+ LDAPMessage *results;
+ LDAPMessage *ldap_entry;
+ char *base;
+ const char *filter = "objectClass=msSFU30DomainInfo";
+ char *cn;
+ int ret;
+
+ ldap = adcli_conn_get_ldap_connection (entry->conn);
+ return_unexpected_if_fail (ldap != NULL);
+
+ if (asprintf (&base, "CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System,%s",
+ adcli_conn_get_default_naming_context (entry->conn)) < 0) {
+ return_unexpected_if_reached ();
+ }
+
+ ret = ldap_search_ext_s (ldap, base, LDAP_SCOPE_SUB, filter, (char **)ldap_attrs,
+ 0, NULL, NULL, NULL, -1, &results);
+
+ free (base);
+
+ if (ret != LDAP_SUCCESS) {
+ /* No NIS domain available */
+ ldap_msgfree (results);
+ return ADCLI_SUCCESS;
+ }
+
+ ldap_entry = ldap_first_entry (ldap, results);
+ if (ldap_entry != NULL) {
+ cn = _adcli_ldap_parse_value (ldap, ldap_entry, "cn");
+ return_unexpected_if_fail (cn != NULL);
+
+ adcli_attrs_add (attrs, "msSFU30NisDomain", cn, NULL);
+ }
+ ldap_msgfree (results);
+
+ return ADCLI_SUCCESS;
+}
diff --git a/library/adentry.h b/library/adentry.h
index eb8bc00..ae90689 100644
--- a/library/adentry.h
+++ b/library/adentry.h
@@ -58,4 +58,6 @@ const char * adcli_entry_get_sam_name (adcli_entry *entry);
const char * adcli_entry_get_dn (adcli_entry *entry);
+adcli_result adcli_get_nis_domain (adcli_entry *entry,
+ adcli_attrs *attrs);
#endif /* ADENTRY_H_ */
diff --git a/tools/entry.c b/tools/entry.c
index 69ce62c..de56586 100644
--- a/tools/entry.c
+++ b/tools/entry.c
@@ -153,6 +153,8 @@ adcli_tool_user_create (adcli_conn *conn,
adcli_attrs *attrs;
const char *ou = NULL;
int opt;
+ bool has_unix_attr = false;
+ bool has_nis_domain = false;
struct option options[] = {
{ "display-name", required_argument, NULL, opt_display_name },
@@ -193,18 +195,23 @@ adcli_tool_user_create (adcli_conn *conn,
break;
case opt_unix_home:
adcli_attrs_add (attrs, "unixHomeDirectory", optarg, NULL);
+ has_unix_attr = true;
break;
case opt_unix_uid:
adcli_attrs_add (attrs, "uidNumber", optarg, NULL);
+ has_unix_attr = true;
break;
case opt_unix_gid:
adcli_attrs_add (attrs, "gidNumber", optarg, NULL);
+ has_unix_attr = true;
break;
case opt_unix_shell:
adcli_attrs_add (attrs, "loginShell", optarg, NULL);
+ has_unix_attr = true;
break;
case opt_nis_domain:
adcli_attrs_add (attrs, "msSFU30NisDomain", optarg, NULL);
+ has_nis_domain = true;
break;
case opt_domain_ou:
ou = optarg;
@@ -242,6 +249,15 @@ adcli_tool_user_create (adcli_conn *conn,
adcli_get_last_error ());
}
+ if (has_unix_attr && !has_nis_domain) {
+ res = adcli_get_nis_domain (entry, attrs);
+ if (res != ADCLI_SUCCESS) {
+ adcli_entry_unref (entry);
+ adcli_attrs_free (attrs);
+ errx (-res, "couldn't get NIS domain");
+ }
+ }
+
res = adcli_entry_create (entry, attrs);
if (res != ADCLI_SUCCESS) {
errx (-res, "creating user %s in domain %s failed: %s",
--
2.20.1

View File

@ -0,0 +1,42 @@
From e1b45e66bc185f5db4c252e1f3fb1b4400b4538e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Mar 2019 10:36:38 +0100
Subject: [PATCH 2/4] library: make _adcli_strv_has_ex public
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187
---
library/adprivate.h | 4 ++++
library/adutil.c | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/library/adprivate.h b/library/adprivate.h
index 0806430..55e6234 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -125,6 +125,10 @@ void _adcli_strv_free (char **strv);
int _adcli_strv_has (char **strv,
const char *str);
+int _adcli_strv_has_ex (char **strv,
+ const char *str,
+ int (* compare) (const char *match, const char*value));
+
char ** _adcli_strv_dup (char **strv) GNUC_WARN_UNUSED;
char * _adcli_strv_join (char **strv,
diff --git a/library/adutil.c b/library/adutil.c
index 76ea158..9b0c47f 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -221,7 +221,7 @@ _adcli_strv_add (char **strv,
return seq_push (strv, length, string);
}
-static int
+int
_adcli_strv_has_ex (char **strv,
const char *str,
int (* compare) (const char *match, const char*value))
--
2.20.1

View File

@ -0,0 +1,35 @@
From 4987a21f4839ab7ea50e932c72df05075efb89b3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 21 Mar 2019 15:05:33 +0100
Subject: [PATCH 2/2] library: return error if no matching key was found
To avoid a misleading debug message indicating success a proper erro
code should be returned the no matching key was found when trying to
copy an keytab entry for a new principal.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1644311
---
library/adkrb5.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/library/adkrb5.c b/library/adkrb5.c
index 033c181..7f77373 100644
--- a/library/adkrb5.c
+++ b/library/adkrb5.c
@@ -298,11 +298,10 @@ _adcli_krb5_keytab_copy_entries (krb5_context k5,
code = _adcli_krb5_get_keyblock (k5, keytab, &entry.key,
match_enctype_and_kvno, &closure);
- if (code != 0) {
- return code;
+ if (code != 0 || closure.matched == 0) {
+ return code != 0 ? code : ENOKEY;
}
-
entry.principal = principal;
entry.vno = kvno;
--
2.20.1

View File

@ -0,0 +1,57 @@
From f05adc23d5cc9f1dfa5638e31949dcd81d632df9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 13 Aug 2018 17:32:24 +0200
Subject: [PATCH 3/4] Do not add service principals twice
---
library/adenroll.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index c4ba537..bb50365 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -313,6 +313,7 @@ add_service_names_to_service_principals (adcli_enroll *enroll)
char *name;
int length = 0;
int i;
+ size_t c;
if (enroll->service_principals != NULL) {
length = seq_count (enroll->service_principals);
@@ -321,14 +322,28 @@ add_service_names_to_service_principals (adcli_enroll *enroll)
for (i = 0; enroll->service_names[i] != NULL; i++) {
if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0)
return_unexpected_if_reached ();
- enroll->service_principals = _adcli_strv_add (enroll->service_principals,
- name, &length);
+ for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) {
+ if (strcmp (name, enroll->service_principals[c]) == 0) {
+ break;
+ }
+ }
+ if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) {
+ enroll->service_principals = _adcli_strv_add (enroll->service_principals,
+ name, &length);
+ }
if (enroll->host_fqdn) {
if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0)
return_unexpected_if_reached ();
- enroll->service_principals = _adcli_strv_add (enroll->service_principals,
- name, &length);
+ for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) {
+ if (strcmp (name, enroll->service_principals[c]) == 0) {
+ break;
+ }
+ }
+ if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) {
+ enroll->service_principals = _adcli_strv_add (enroll->service_principals,
+ name, &length);
+ }
}
}
--
2.17.1

View File

@ -0,0 +1,42 @@
From 10a4dbb5978b6f05cf75f820d97da908e735ace8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Mar 2019 10:37:11 +0100
Subject: [PATCH 3/4] library: _adcli_krb5_build_principal allow principals as
names
Make _adcli_krb5_build_principal a bit more robust by checking if the
given name already contains a realm suffix.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187
---
library/adkrb5.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/library/adkrb5.c b/library/adkrb5.c
index 7f77373..da835d7 100644
--- a/library/adkrb5.c
+++ b/library/adkrb5.c
@@ -41,12 +41,16 @@ _adcli_krb5_build_principal (krb5_context k5,
krb5_principal *principal)
{
krb5_error_code code;
- char *name;
+ char *name = NULL;
- if (asprintf (&name, "%s@%s", user, realm) < 0)
- return_val_if_reached (ENOMEM);
+ /* Use user if user contains a @-character and add @realm otherwise */
+ if (strchr (user, '@') == NULL) {
+ if (asprintf (&name, "%s@%s", user, realm) < 0) {
+ return_val_if_reached (ENOMEM);
+ }
+ }
- code = krb5_parse_name (k5, name, principal);
+ code = krb5_parse_name (k5, name != NULL ? name : user, principal);
return_val_if_fail (code == 0, code);
free (name);
--
2.20.1

View File

@ -0,0 +1,27 @@
From 8f726817b9ff643a382fa12ea9ff489cd5ab9068 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 13 Aug 2018 18:24:58 +0200
Subject: [PATCH 4/4] Do not depend on default_realm in krb5.conf
---
library/adenroll.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/library/adenroll.c b/library/adenroll.c
index bb50365..02bd9e3 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1661,7 +1661,9 @@ remove_principal_from_keytab (adcli_enroll *enroll,
krb5_principal principal;
match_principal_kvno closure;
- code = krb5_parse_name (k5, principal_name, &principal);
+ code = _adcli_krb5_build_principal (k5, principal_name,
+ adcli_conn_get_domain_realm (enroll->conn),
+ &principal);
if (code != 0) {
_adcli_err ("Couldn't parse principal: %s: %s",
principal_name, krb5_get_error_message (k5, code));
--
2.17.1

View File

@ -0,0 +1,82 @@
From 972f1a2f35829ed89f5353bd204683aa9ad6a2d2 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Mar 2019 10:37:57 +0100
Subject: [PATCH 4/4] library: make sure server side SPNs are preserved
adcli should not delete service principal names (SPNs) unexpectedly. If
a SPN was added on the server while presetting a host or updating an
existing entry and upcoming adcli join or update should preserver this
change.
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187
---
library/adenroll.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/library/adenroll.c b/library/adenroll.c
index 48cb4cf..1cce86a 100644
--- a/library/adenroll.c
+++ b/library/adenroll.c
@@ -1961,6 +1961,47 @@ adcli_enroll_prepare (adcli_enroll *enroll,
return res;
}
+static adcli_result
+add_server_side_service_principals (adcli_enroll *enroll)
+{
+ char **spn_list;
+ LDAP *ldap;
+ size_t c;
+ int length = 0;
+ adcli_result res;
+
+ ldap = adcli_conn_get_ldap_connection (enroll->conn);
+ assert (ldap != NULL);
+
+ spn_list = _adcli_ldap_parse_values (ldap, enroll->computer_attributes,
+ "servicePrincipalName");
+ if (spn_list == NULL) {
+ return ADCLI_SUCCESS;
+ }
+
+ if (enroll->service_principals != NULL) {
+ length = seq_count (enroll->service_principals);
+ }
+
+ for (c = 0; spn_list[c] != NULL; c++) {
+ _adcli_info ("Checking %s", spn_list[c]);
+ if (!_adcli_strv_has_ex (enroll->service_principals_to_remove, spn_list[c], strcasecmp)) {
+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals,
+ spn_list[c], &length, false);
+ assert (enroll->service_principals != NULL);
+ _adcli_info (" Added %s", spn_list[c]);
+ }
+ }
+ _adcli_strv_free (spn_list);
+
+ res = ensure_keytab_principals (ADCLI_SUCCESS, enroll);
+ if (res != ADCLI_SUCCESS) {
+ return res;
+ }
+
+ return ADCLI_SUCCESS;
+}
+
static adcli_result
enroll_join_or_update_tasks (adcli_enroll *enroll,
adcli_enroll_flags flags)
@@ -2019,6 +2060,11 @@ enroll_join_or_update_tasks (adcli_enroll *enroll,
update_and_calculate_enctypes (enroll);
update_computer_account (enroll);
+ res = add_server_side_service_principals (enroll);
+ if (res != ADCLI_SUCCESS) {
+ return res;
+ }
+
/* service_names is only set from input on the command line, so no
* additional check for explicit is needed here */
if (enroll->service_names != NULL) {
--
2.20.1

View File

@ -1,6 +1,6 @@
Name: adcli
Version: 0.8.2
Release: 3%{?dist}
Release: 4%{?dist}
Summary: Active Directory enrollment
License: LGPLv2+
URL: http://cgit.freedesktop.org/realmd/adcli
@ -31,6 +31,48 @@ Patch22: 0022-Add-add-service-principal-and-remove-service-princip.patch
Patch23: 0023-adcli_conn_is_writeable-do-not-crash-id-domain_disco.patch
Patch24: 0024-doc-fix-typos-in-the-adcli-man-page.patch
# Additional fixes for rhbz#1593240
Patch25: 0001-fix-typo-in-flag-value.patch
Patch26: 0002-_adcli_call_external_program-silence-noisy-debug-mes.patch
# rhbz#1608212
Patch27: 0003-Do-not-add-service-principals-twice.patch
# Additional fixed for rhbz#1547014
Patch28: 0004-Do-not-depend-on-default_realm-in-krb5.conf.patch
# rhbz#1649868
Patch29: 0001-adutil-add-_adcli_strv_add_unique.patch
Patch30: 0002-adenroll-use-_adcli_strv_add_unique-for-service-prin.patch
# rhbz#1588596 - many adcli-krb5-????? directories are created /tmp
Patch31: 0001-tools-properly-release-internal-data-on-error.patch
# rhbz#1642546 - adcli exports kerberos ticket with old kvno
Patch32: 0001-Increment-kvno-after-password-change-with-user-creds.patch
# rhbz#1595911 - [RFE] Have `adcli join` work without FQDN in `hostname` output
# with some additional man page fixes from rhbz#1440533
Patch33: 0001-library-use-getaddrinfo-with-AI_CANONNAME-to-find-a-.patch
# rhbz#1644311 - Improve handling of service principals
Patch34: 0001-join-always-add-service-principals.patch
Patch35: 0002-library-return-error-if-no-matching-key-was-found.patch
# rhbz#1337489 - [RFE] adcli command with --unix-* options doesn't update
# values in UnixAttributes Tab for user
Patch36: 0001-create-user-add-nis-domain-option.patch
Patch37: 0002-create-user-try-to-find-NIS-domain-if-needed.patch
# rhbz#1630187 - [RFE] adcli join should preserve SPN added by adcli preset-computer
Patch38: 0001-ensure_keytab_principals-do-not-leak-memory-when-cal.patch
Patch39: 0002-library-make-_adcli_strv_has_ex-public.patch
Patch40: 0003-library-_adcli_krb5_build_principal-allow-principals.patch
Patch41: 0004-library-make-sure-server-side-SPNs-are-preserved.patch
# rhbz#1622583 - [RFE] Need an option for adcli command which will show domain join status.
Patch42: 0001-Implement-adcli-testjoin.patch
BuildRequires: gcc
BuildRequires: intltool pkgconfig
BuildRequires: libtool
@ -53,31 +95,7 @@ standard LDAP and Kerberos calls.
%define _hardened_build 1
%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%autosetup -p1
%build
autoreconf --force --install --verbose
@ -111,6 +129,12 @@ documentation.
%doc %{_datadir}/doc/adcli/*
%changelog
* Fri Mar 22 2019 Sumit Bose <sbose@redhat.com> - 0.8.2-4
- various fixes and improvements
Resolves: rhbz#1593240, rhbz#1608212, rhbz#1547014, rhbz#1547014,
rhbz#1649868, rhbz#1588596, rhbz#1642546, rhbz#1595911,
rhbz#1644311, rhbz#1337489, rhbz#1630187, rhbz#1622583
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.2-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild