Merge ~ahasenack/ubuntu/+source/adcli:groovy-adcli-upstream-fixes into ubuntu/+source/adcli:ubuntu/devel

Proposed by Andreas Hasenack
Status: Merged
Approved by: Andreas Hasenack
Approved revision: 778a64390fe2bd9c6a78f898a268dc9dacaa3fd7
Merged at revision: 778a64390fe2bd9c6a78f898a268dc9dacaa3fd7
Proposed branch: ~ahasenack/ubuntu/+source/adcli:groovy-adcli-upstream-fixes
Merge into: ubuntu/+source/adcli:ubuntu/devel
Diff against target: 1448 lines (+1356/-1)
14 files modified
debian/changelog (+33/-0)
debian/control (+2/-1)
debian/patches/Use-GSS-SPNEGO-if-available.patch (+127/-0)
debian/patches/add-description-option-to-join-and-update.patch (+186/-0)
debian/patches/add-option-use-ldaps.patch (+383/-0)
debian/patches/delete-do-not-exit-if-keytab-cannot-be-read.patch (+34/-0)
debian/patches/discovery-fix.patch (+29/-0)
debian/patches/man-explain-optional-parameter-of-login-ccache-bette.patch (+46/-0)
debian/patches/man-make-handling-of-optional-credential-cache-more-.patch (+43/-0)
debian/patches/man-move-note-to-the-right-section.patch (+50/-0)
debian/patches/series (+11/-0)
debian/patches/tools-add-show-computer-command.patch (+341/-0)
debian/patches/tools-disable-SSSD-s-locator-plugin.patch (+43/-0)
debian/patches/tools-fix-typo-in-show-password-help-output.patch (+28/-0)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Review via email: mp+390164@code.launchpad.net

Description of the change

I cherry picked many fixes from upstream's git repo. They are not yet released, but fedora has them, and they are upstream essentially.

There are 4 groups of fixes:
- documentation fixes: no FFe needed
- fix for new AD settings introduced this year: bug #1868703 which already existed for sssd. I added an adcli task and an FFe request/justification. Initially I didn't think this needed an FFe, but changed my mind. Happy to discuss.
- new features that I thought were useful: new FFe bug #1893784
- other random fixes, no FFe

Not all of these can be tested/verified without an AD server lying around. Others you can check that the manpage was updated/fixed, or the new command and parameter exist when you check "adcli --help".

PPA: https://launchpad.net/~ahasenack/+archive/ubuntu/adcli-fixes

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

This missed a review slot, I created one and grabbed it - but I'll need some more time after Lunch to complete.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

FFe is required but already present - ok

Thanks for explaining yesterday that they have rare releases and a stack of packaging patches seems to be a common way - otherwise I'd have asked just that.

I think on the mechanical side (changelog, version, filenames, ...) everything is fine.
I'll next go through the patches one by one to see if I spot anything concerning.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

tools-add-show-computer-command.patch - FFe, but ok
add-description-option-to-join-and-update.patch - FFe, but ok
Use-GSS-SPNEGO-if-available.patch - FFe, but ok
add-option-use-ldaps.patch - FFe, but ok
man-move-note-to-the-right-section.patch - ok
man-explain-optional-parameter-of-login-ccache-bette.patch - ok
man-make-handling-of-optional-credential-cache-more-.patch - ok
tools-fix-typo-in-show-password-help-output.patch - ok
discovery-fix.patch - ok
delete-do-not-exit-if-keytab-cannot-be-read.patch - ok
tools-disable-SSSD-s-locator-plugin.patch - FFe, but ok

The latter IMHO could cause a FFe worthy behavior change, but since you have an FFe bug already that isn't important.

-> All patches are upstream accepted.
-> No Further patches in the upload.
-> No patch forgotten in Changelog.

P.S. I have no test setup for adcli either and as you said "Not all of these can be tested/verified without an AD server lying around" :-/ But I have no better suggestion right now.
OTOH if these changes would be part of an upstream release we'd also not test them one by one.

LGTM +1!

Just curious, do you intend to submit that to Debian as well?
Or are we waiting on the (known to be slow) upstream release to drop this?

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Marking as approved, pending FFe verification.

Yes, I intend to submit all of this to debian

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Both ffes were just approved.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Tagging and uploading 778a64390fe2bd9c6a78f898a268dc9dacaa3fd7

$ git push pkg upload/0.9.0-1ubuntu1
Enumerating objects: 74, done.
Counting objects: 100% (74/74), done.
Delta compression using up to 4 threads
Compressing objects: 100% (69/69), done.
Writing objects: 100% (70/70), 23.07 KiB | 3.84 MiB/s, done.
Total 70 (delta 42), reused 0 (delta 0)
To ssh://git.launchpad.net/ubuntu/+source/adcli
 * [new tag] upload/0.9.0-1ubuntu1 -> upload/0.9.0-1ubuntu1

$ dput ubuntu ../adcli_0.9.0-1ubuntu1_source.changes
Checking signature on .changes
gpg: ../adcli_0.9.0-1ubuntu1_source.changes: Valid signature from AC983EB5BF6BCBA9
Checking signature on .dsc
gpg: ../adcli_0.9.0-1ubuntu1.dsc: Valid signature from AC983EB5BF6BCBA9
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading adcli_0.9.0-1ubuntu1.dsc: done.
  Uploading adcli_0.9.0-1ubuntu1.debian.tar.xz: done.
  Uploading adcli_0.9.0-1ubuntu1_source.buildinfo: done.
  Uploading adcli_0.9.0-1ubuntu1_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 716a3a6..3445006 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,36 @@
6+adcli (0.9.0-1ubuntu1) groovy; urgency=medium
7+
8+ * New features (LP: #1893784):
9+ - d/p/tools-add-show-computer-command.patch: add a show-computer
10+ command to print the LDAP attrs of the computer object
11+ - d/p/add-description-option-to-join-and-update.patch: allow setting
12+ an optional description on the computer account
13+ * Handle new Active Directory requirements from
14+ https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/ADV190023
15+ (LP: #1868703):
16+ - d/p/Use-GSS-SPNEGO-if-available.patch: prefer GSS-SPNEGO over
17+ GSSAPI if available, as that can handle some of the more advanced
18+ features which can be required by an AD server
19+ - d/p/add-option-use-ldaps.patch: add option to use LDAPS, useful
20+ if for some reason the LDAP port is blocked.
21+ * Documentation fixes:
22+ - d/p/man-move-note-to-the-right-section.patch: move note about
23+ password lifetime to the update section
24+ - d/p/man-explain-optional-parameter-of-login-ccache-bette.patch,
25+ d/p/man-make-handling-of-optional-credential-cache-more-.patch:
26+ better explain the login-ccache and -C parameters
27+ - d/p/tools-fix-typo-in-show-password-help-output.patch: typo fix
28+ * Other fixes:
29+ - d/p/discovery-fix.patch: do not continue processing on a closed
30+ connection
31+ - d/p/delete-do-not-exit-if-keytab-cannot-be-read.patch: fix computer
32+ deletion when keytab cannot be read
33+ - d/p/tools-disable-SSSD-s-locator-plugin.patch: ignore MIT's locator
34+ plugin to avoid conflicts if it returns a different DC than the one
35+ used for the LDAP connection
36+
37+ -- Andreas Hasenack <andreas@canonical.com> Wed, 02 Sep 2020 09:50:18 -0300
38+
39 adcli (0.9.0-1) unstable; urgency=medium
40
41 * New upstream release. (Closes: #941583)
42diff --git a/debian/control b/debian/control
43index 642e623..f529834 100644
44--- a/debian/control
45+++ b/debian/control
46@@ -1,7 +1,8 @@
47 Source: adcli
48 Section: admin
49 Priority: optional
50-Maintainer: Laurent Bigonville <bigon@debian.org>
51+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
52+XSBC-Original-Maintainer: Laurent Bigonville <bigon@debian.org>
53 Build-Depends: debhelper (>= 12),
54 libkrb5-dev,
55 libldap2-dev,
56diff --git a/debian/patches/Use-GSS-SPNEGO-if-available.patch b/debian/patches/Use-GSS-SPNEGO-if-available.patch
57new file mode 100644
58index 0000000..f61ef39
59--- /dev/null
60+++ b/debian/patches/Use-GSS-SPNEGO-if-available.patch
61@@ -0,0 +1,127 @@
62+From a6f795ba3d6048b32d7863468688bf7f42b2cafd Mon Sep 17 00:00:00 2001
63+From: Sumit Bose <sbose@redhat.com>
64+Date: Fri, 11 Oct 2019 16:39:25 +0200
65+Subject: [PATCH] Use GSS-SPNEGO if available
66+
67+Currently adcli uses the GSSAPI SASL mechanism for LDAP authentication
68+and to establish encryption. While this works in general it does not
69+handle some of the more advanced features which can be required by AD
70+DCs.
71+
72+The GSS-SPNEGO mechanism can handle them and is used with this patch by
73+adcli if the AD DC indicates that it supports it.
74+
75+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420
76+---
77+ library/adconn.c | 35 ++++++++++++++++++++++++++++++++++-
78+ library/adconn.h | 3 +++
79+ 2 files changed, 37 insertions(+), 1 deletion(-)
80+
81+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/a6f795ba3d6048b32d7863468688bf7f42b2cafd
82+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1868703
83+Last-Update: 2020-09-01
84+diff --git a/library/adconn.c b/library/adconn.c
85+index bcaced8..ffb54f9 100644
86+--- a/library/adconn.c
87++++ b/library/adconn.c
88+@@ -77,6 +77,7 @@ struct _adcli_conn_ctx {
89+ char *default_naming_context;
90+ char *configuration_naming_context;
91+ char **supported_capabilities;
92++ char **supported_sasl_mechs;
93+
94+ /* Connect state */
95+ LDAP *ldap;
96+@@ -845,6 +846,7 @@ connect_and_lookup_naming (adcli_conn *conn,
97+ "defaultNamingContext",
98+ "configurationNamingContext",
99+ "supportedCapabilities",
100++ "supportedSASLMechanisms",
101+ NULL
102+ };
103+
104+@@ -897,6 +899,11 @@ connect_and_lookup_naming (adcli_conn *conn,
105+ "supportedCapabilities");
106+ }
107+
108++ if (conn->supported_sasl_mechs == NULL) {
109++ conn->supported_sasl_mechs = _adcli_ldap_parse_values (ldap, results,
110++ "supportedSASLMechanisms");
111++ }
112++
113+ ldap_msgfree (results);
114+
115+ if (conn->default_naming_context == NULL) {
116+@@ -1022,6 +1029,7 @@ authenticate_to_directory (adcli_conn *conn)
117+ OM_uint32 minor;
118+ ber_len_t ssf;
119+ int ret;
120++ const char *mech = "GSSAPI";
121+
122+ if (conn->ldap_authenticated)
123+ return ADCLI_SUCCESS;
124+@@ -1038,7 +1046,11 @@ authenticate_to_directory (adcli_conn *conn)
125+ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf);
126+ return_unexpected_if_fail (ret == 0);
127+
128+- ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, "GSSAPI", NULL, NULL,
129++ if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) {
130++ mech = "GSS-SPNEGO";
131++ }
132++
133++ ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL,
134+ LDAP_SASL_QUIET, sasl_interact, NULL);
135+
136+ /* Clear the credential cache GSSAPI to use (for this thread) */
137+@@ -1231,6 +1243,7 @@ conn_free (adcli_conn *conn)
138+ free (conn->default_naming_context);
139+ free (conn->configuration_naming_context);
140+ _adcli_strv_free (conn->supported_capabilities);
141++ _adcli_strv_free (conn->supported_sasl_mechs);
142+
143+ free (conn->computer_name);
144+ free (conn->host_fqdn);
145+@@ -1606,6 +1619,26 @@ adcli_conn_server_has_capability (adcli_conn *conn,
146+ return 0;
147+ }
148+
149++bool
150++adcli_conn_server_has_sasl_mech (adcli_conn *conn,
151++ const char *mech)
152++{
153++ int i;
154++
155++ return_val_if_fail (conn != NULL, false);
156++ return_val_if_fail (mech != NULL, false);
157++
158++ if (!conn->supported_sasl_mechs)
159++ return false;
160++
161++ for (i = 0; conn->supported_sasl_mechs[i] != NULL; i++) {
162++ if (strcasecmp (mech, conn->supported_sasl_mechs[i]) == 0)
163++ return true;
164++ }
165++
166++ return false;
167++}
168++
169+ bool adcli_conn_is_writeable (adcli_conn *conn)
170+ {
171+ disco_dance_if_necessary (conn);
172+diff --git a/library/adconn.h b/library/adconn.h
173+index 1ad5715..37ebdd9 100644
174+--- a/library/adconn.h
175++++ b/library/adconn.h
176+@@ -149,6 +149,9 @@ void adcli_conn_set_krb5_conf_dir (adcli_conn *conn,
177+ int adcli_conn_server_has_capability (adcli_conn *conn,
178+ const char *capability);
179+
180++bool adcli_conn_server_has_sasl_mech (adcli_conn *conn,
181++ const char *mech);
182++
183+ bool adcli_conn_is_writeable (adcli_conn *conn);
184+
185+ #endif /* ADCONN_H_ */
186+--
187+GitLab
188+
189diff --git a/debian/patches/add-description-option-to-join-and-update.patch b/debian/patches/add-description-option-to-join-and-update.patch
190new file mode 100644
191index 0000000..e8de6eb
192--- /dev/null
193+++ b/debian/patches/add-description-option-to-join-and-update.patch
194@@ -0,0 +1,186 @@
195+From 3937a2a7db90611aa7a93248233b0c5d31e85a3e Mon Sep 17 00:00:00 2001
196+From: Sumit Bose <sbose@redhat.com>
197+Date: Wed, 27 Nov 2019 14:48:32 +0100
198+Subject: [PATCH] add description option to join and update
199+
200+This new option allows to set the description LDAP attribute for the AD
201+computer object.
202+
203+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1737342
204+---
205+ doc/adcli.xml | 10 ++++++++++
206+ library/adenroll.c | 29 +++++++++++++++++++++++++++++
207+ library/adenroll.h | 4 ++++
208+ tools/computer.c | 7 +++++++
209+ 4 files changed, 50 insertions(+)
210+
211+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/3937a2a7db90611aa7a93248233b0c5d31e85a3e
212+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1893784
213+Last-Update: 2020-09-02
214+diff --git a/doc/adcli.xml b/doc/adcli.xml
215+index 1f93186..dd30435 100644
216+--- a/doc/adcli.xml
217++++ b/doc/adcli.xml
218+@@ -275,6 +275,11 @@ Password for Administrator:
219+ <listitem><para>Set the operating system version on the computer
220+ account. Not set by default.</para></listitem>
221+ </varlistentry>
222++ <varlistentry>
223++ <term><option>--description=<parameter>description</parameter></option></term>
224++ <listitem><para>Set the description attribute on the computer
225++ account. Not set by default.</para></listitem>
226++ </varlistentry>
227+ <varlistentry>
228+ <term><option>--service-name=<parameter>service</parameter></option></term>
229+ <listitem><para>Additional service name for a kerberos
230+@@ -416,6 +421,11 @@ $ adcli update --login-ccache=/tmp/krbcc_123
231+ <listitem><para>Set the operating system version on the computer
232+ account. Not set by default.</para></listitem>
233+ </varlistentry>
234++ <varlistentry>
235++ <term><option>--description=<parameter>description</parameter></option></term>
236++ <listitem><para>Set the description attribute on the computer
237++ account. Not set by default.</para></listitem>
238++ </varlistentry>
239+ <varlistentry>
240+ <term><option>--service-name=<parameter>service</parameter></option></term>
241+ <listitem><para>Additional service name for a Kerberos
242+diff --git a/library/adenroll.c b/library/adenroll.c
243+index 8d2adeb..246f658 100644
244+--- a/library/adenroll.c
245++++ b/library/adenroll.c
246+@@ -83,6 +83,7 @@ static char *default_ad_ldap_attrs[] = {
247+ "operatingSystemServicePack",
248+ "pwdLastSet",
249+ "userAccountControl",
250++ "description",
251+ NULL,
252+ };
253+
254+@@ -143,6 +144,7 @@ struct _adcli_enroll {
255+ char *samba_data_tool;
256+ bool trusted_for_delegation;
257+ int trusted_for_delegation_explicit;
258++ char *description;
259+ };
260+
261+ static adcli_result
262+@@ -756,6 +758,8 @@ create_computer_account (adcli_enroll *enroll,
263+ char *vals_userPrincipalName[] = { enroll->user_principal, NULL };
264+ LDAPMod userPrincipalName = { LDAP_MOD_ADD, "userPrincipalName", { vals_userPrincipalName, }, };
265+ LDAPMod servicePrincipalName = { LDAP_MOD_ADD, "servicePrincipalName", { enroll->service_principals, } };
266++ char *vals_description[] = { enroll->description, NULL };
267++ LDAPMod description = { LDAP_MOD_ADD, "description", { vals_description, }, };
268+
269+ char *val = NULL;
270+
271+@@ -774,6 +778,7 @@ create_computer_account (adcli_enroll *enroll,
272+ &operatingSystemServicePack,
273+ &userPrincipalName,
274+ &servicePrincipalName,
275++ &description,
276+ NULL
277+ };
278+
279+@@ -1460,6 +1465,14 @@ update_computer_account (adcli_enroll *enroll)
280+ res |= update_computer_attribute (enroll, ldap, mods);
281+ }
282+
283++ if (res == ADCLI_SUCCESS && enroll->description != NULL) {
284++ char *vals_description[] = { enroll->description, NULL };
285++ LDAPMod description = { LDAP_MOD_REPLACE, "description", { vals_description, }, };
286++ LDAPMod *mods[] = { &description, NULL, };
287++
288++ res |= update_computer_attribute (enroll, ldap, mods);
289++ }
290++
291+ if (res != 0)
292+ _adcli_info ("Updated existing computer account: %s", enroll->computer_dn);
293+ }
294+@@ -2899,6 +2912,22 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll,
295+ enroll->trusted_for_delegation_explicit = 1;
296+ }
297+
298++void
299++adcli_enroll_set_description (adcli_enroll *enroll, const char *value)
300++{
301++ return_if_fail (enroll != NULL);
302++ if (value != NULL && value[0] != '\0') {
303++ _adcli_str_set (&enroll->description, value);
304++ }
305++}
306++
307++const char *
308++adcli_enroll_get_desciption (adcli_enroll *enroll)
309++{
310++ return_val_if_fail (enroll != NULL, NULL);
311++ return enroll->description;
312++}
313++
314+ const char **
315+ adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll)
316+ {
317+diff --git a/library/adenroll.h b/library/adenroll.h
318+index 11eb517..0606169 100644
319+--- a/library/adenroll.h
320++++ b/library/adenroll.h
321+@@ -126,6 +126,10 @@ bool adcli_enroll_get_trusted_for_delegation (adcli_enroll *enroll
322+ void adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll,
323+ bool value);
324+
325++const char * adcli_enroll_get_desciption (adcli_enroll *enroll);
326++void adcli_enroll_set_description (adcli_enroll *enroll,
327++ const char *value);
328++
329+ krb5_kvno adcli_enroll_get_kvno (adcli_enroll *enroll);
330+
331+ void adcli_enroll_set_kvno (adcli_enroll *enroll,
332+diff --git a/tools/computer.c b/tools/computer.c
333+index c8b96a4..840e334 100644
334+--- a/tools/computer.c
335++++ b/tools/computer.c
336+@@ -112,6 +112,7 @@ typedef enum {
337+ opt_trusted_for_delegation,
338+ opt_add_service_principal,
339+ opt_remove_service_principal,
340++ opt_description,
341+ } Option;
342+
343+ static adcli_tool_desc common_usages[] = {
344+@@ -142,6 +143,7 @@ static adcli_tool_desc common_usages[] = {
345+ "in the userAccountControl attribute", },
346+ { opt_add_service_principal, "add the given service principal to the account\n" },
347+ { opt_remove_service_principal, "remove the given service principal from the account\n" },
348++ { opt_description, "add a description to the account\n" },
349+ { opt_no_password, "don't prompt for or read a password" },
350+ { opt_prompt_password, "prompt for a password if necessary" },
351+ { opt_stdin_password, "read a password from stdin (until EOF) if\n"
352+@@ -306,6 +308,9 @@ parse_option (Option opt,
353+ case opt_remove_service_principal:
354+ adcli_enroll_add_service_principal_to_remove (enroll, optarg);
355+ return ADCLI_SUCCESS;
356++ case opt_description:
357++ adcli_enroll_set_description (enroll, optarg);
358++ return ADCLI_SUCCESS;
359+ case opt_verbose:
360+ return ADCLI_SUCCESS;
361+
362+@@ -369,6 +374,7 @@ adcli_tool_computer_join (adcli_conn *conn,
363+ { "os-name", required_argument, NULL, opt_os_name },
364+ { "os-version", required_argument, NULL, opt_os_version },
365+ { "os-service-pack", optional_argument, NULL, opt_os_service_pack },
366++ { "description", optional_argument, NULL, opt_description },
367+ { "user-principal", optional_argument, NULL, opt_user_principal },
368+ { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
369+ { "add-service-principal", required_argument, NULL, opt_add_service_principal },
370+@@ -487,6 +493,7 @@ adcli_tool_computer_update (adcli_conn *conn,
371+ { "os-name", required_argument, NULL, opt_os_name },
372+ { "os-version", required_argument, NULL, opt_os_version },
373+ { "os-service-pack", optional_argument, NULL, opt_os_service_pack },
374++ { "description", optional_argument, NULL, opt_description },
375+ { "user-principal", optional_argument, NULL, opt_user_principal },
376+ { "computer-password-lifetime", optional_argument, NULL, opt_computer_password_lifetime },
377+ { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
378+--
379+GitLab
380+
381diff --git a/debian/patches/add-option-use-ldaps.patch b/debian/patches/add-option-use-ldaps.patch
382new file mode 100644
383index 0000000..47d9431
384--- /dev/null
385+++ b/debian/patches/add-option-use-ldaps.patch
386@@ -0,0 +1,383 @@
387+From 85097245b57f190337225dbdbf6e33b58616c092 Mon Sep 17 00:00:00 2001
388+From: Sumit Bose <sbose@redhat.com>
389+Date: Thu, 19 Dec 2019 07:22:33 +0100
390+Subject: [PATCH] add option use-ldaps
391+
392+In general using the LDAP port with GSS-SPNEGO should satifiy all
393+requirements an AD DC should have for authentication on an encrypted
394+LDAP connection.
395+
396+But if e.g. the LDAP port is blocked by a firewall using the LDAPS port
397+with TLS encryption might be an alternative. For this use case the
398+--use-ldaps option is added.
399+
400+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420
401+---
402+ doc/adcli.xml | 24 +++++++++++++++
403+ library/adconn.c | 79 ++++++++++++++++++++++++++++++++++++++++++------
404+ library/adconn.h | 4 +++
405+ tools/computer.c | 10 ++++++
406+ tools/entry.c | 11 +++++++
407+ 5 files changed, 119 insertions(+), 9 deletions(-)
408+
409+ Ubuntu backport note: adjusted the ldap.conf path in the documentation
410+
411+Origin: backport, https://gitlab.freedesktop.org/realmd/adcli/-/commit/85097245b57f190337225dbdbf6e33b58616c092
412+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1868703
413+Last-Update: 2020-09-01
414+diff --git a/doc/adcli.xml b/doc/adcli.xml
415+index dd30435..acced25 100644
416+--- a/doc/adcli.xml
417++++ b/doc/adcli.xml
418+@@ -128,6 +128,30 @@
419+ If not specified, then an appropriate domain controller
420+ is automatically discovered.</para></listitem>
421+ </varlistentry>
422++ <varlistentry>
423++ <term><option>--use-ldaps</option></term>
424++ <listitem><para>Connect to the domain controller
425++ with LDAPS. By default the LDAP port is used and SASL
426++ GSS-SPNEGO or GSSAPI is used for authentication and to
427++ establish encryption. This should satisfy all
428++ requirements set on the server side and LDAPS should
429++ only be used if the LDAP port is not accessible due to
430++ firewalls or other reasons.</para>
431++ <para> Please note that the place where CA certificates
432++ can be found to validate the AD DC certificates
433++ must be configured in the OpenLDAP configuration
434++ file, e.g. <filename>/etc/ldap/ldap.conf</filename>.
435++ As an alternative it can be specified with the help of
436++ an environment variable, e.g.
437++<programlisting>
438++$ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.example.com
439++...
440++</programlisting>
441++ Please see
442++ <citerefentry><refentrytitle>ldap.conf</refentrytitle>
443++ <manvolnum>5</manvolnum></citerefentry> for details.
444++ </para></listitem>
445++ </varlistentry>
446+ <varlistentry>
447+ <term><option>-C, --login-ccache=<parameter>ccache_name</parameter></option></term>
448+ <listitem><para>Use the specified kerberos credential
449+diff --git a/library/adconn.c b/library/adconn.c
450+index ffb54f9..7bab852 100644
451+--- a/library/adconn.c
452++++ b/library/adconn.c
453+@@ -70,6 +70,7 @@ struct _adcli_conn_ctx {
454+ char *domain_name;
455+ char *domain_realm;
456+ char *domain_controller;
457++ bool use_ldaps;
458+ char *canonical_host;
459+ char *domain_short;
460+ char *domain_sid;
461+@@ -773,7 +774,8 @@ int ldap_init_fd (ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap
462+
463+ static LDAP *
464+ connect_to_address (const char *host,
465+- const char *canonical_host)
466++ const char *canonical_host,
467++ bool use_ldaps)
468+ {
469+ struct addrinfo *res = NULL;
470+ struct addrinfo *ai;
471+@@ -783,6 +785,16 @@ connect_to_address (const char *host,
472+ char *url;
473+ int sock;
474+ int rc;
475++ int opt_rc;
476++ const char *port = "389";
477++ const char *proto = "ldap";
478++ const char *errmsg = NULL;
479++
480++ if (use_ldaps) {
481++ port = "636";
482++ proto = "ldaps";
483++ _adcli_info ("Using LDAPS to connect to %s", host);
484++ }
485+
486+ memset (&hints, '\0', sizeof(hints));
487+ #ifdef AI_ADDRCONFIG
488+@@ -794,7 +806,7 @@ connect_to_address (const char *host,
489+ if (!canonical_host)
490+ canonical_host = host;
491+
492+- rc = getaddrinfo (host, "389", &hints, &res);
493++ rc = getaddrinfo (host, port, &hints, &res);
494+ if (rc != 0) {
495+ _adcli_err ("Couldn't resolve host name: %s: %s", host, gai_strerror (rc));
496+ return NULL;
497+@@ -810,7 +822,7 @@ connect_to_address (const char *host,
498+ close (sock);
499+ } else {
500+ error = 0;
501+- if (asprintf (&url, "ldap://%s", canonical_host) < 0)
502++ if (asprintf (&url, "%s://%s", proto, canonical_host) < 0)
503+ return_val_if_reached (NULL);
504+ rc = ldap_init_fd (sock, 1, url, &ldap);
505+ free (url);
506+@@ -820,6 +832,25 @@ connect_to_address (const char *host,
507+ ldap_err2string (rc));
508+ break;
509+ }
510++
511++ if (use_ldaps) {
512++ rc = ldap_install_tls (ldap);
513++ if (rc != LDAP_SUCCESS) {
514++ opt_rc = ldap_get_option (ldap,
515++ LDAP_OPT_DIAGNOSTIC_MESSAGE,
516++ (void *) &errmsg);
517++ if (opt_rc != LDAP_SUCCESS) {
518++ errmsg = NULL;
519++ }
520++ _adcli_err ("Couldn't initialize TLS [%s]: %s",
521++ ldap_err2string (rc),
522++ errmsg == NULL ? "- no details -"
523++ : errmsg);
524++ ldap_unbind_ext_s (ldap, NULL, NULL);
525++ ldap = NULL;
526++ break;
527++ }
528++ }
529+ }
530+ }
531+
532+@@ -856,7 +887,8 @@ connect_and_lookup_naming (adcli_conn *conn,
533+ if (!canonical_host)
534+ canonical_host = disco->host_addr;
535+
536+- ldap = connect_to_address (disco->host_addr, canonical_host);
537++ ldap = connect_to_address (disco->host_addr, canonical_host,
538++ adcli_conn_get_use_ldaps (conn));
539+ if (ldap == NULL)
540+ return ADCLI_ERR_DIRECTORY;
541+
542+@@ -1041,14 +1073,28 @@ authenticate_to_directory (adcli_conn *conn)
543+ status = gss_krb5_ccache_name (&minor, conn->login_ccache_name, NULL);
544+ return_unexpected_if_fail (status == 0);
545+
546+- /* Clumsily tell ldap + cyrus-sasl that we want encryption */
547+- ssf = 1;
548+- ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf);
549+- return_unexpected_if_fail (ret == 0);
550++ if (adcli_conn_get_use_ldaps (conn)) {
551++ /* do not use SASL encryption on LDAPS connection */
552++ ssf = 0;
553++ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf);
554++ return_unexpected_if_fail (ret == 0);
555++ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MAX, &ssf);
556++ return_unexpected_if_fail (ret == 0);
557++ } else {
558++ /* Clumsily tell ldap + cyrus-sasl that we want encryption */
559++ ssf = 1;
560++ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf);
561++ return_unexpected_if_fail (ret == 0);
562++ }
563+
564+- if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) {
565++ /* There are issues with cryrus-sasl and GSS-SPNEGO with TLS even if
566++ * ssf_max is set to 0. To be on the safe side GSS-SPNEGO is only used
567++ * without LDAPS. */
568++ if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")
569++ && !adcli_conn_get_use_ldaps (conn)) {
570+ mech = "GSS-SPNEGO";
571+ }
572++ _adcli_info ("Using %s for SASL bind", mech);
573+
574+ ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL,
575+ LDAP_SASL_QUIET, sasl_interact, NULL);
576+@@ -1230,6 +1276,7 @@ adcli_conn_new (const char *domain_name)
577+ conn->refs = 1;
578+ conn->logins_allowed = ADCLI_LOGIN_COMPUTER_ACCOUNT | ADCLI_LOGIN_USER_ACCOUNT;
579+ adcli_conn_set_domain_name (conn, domain_name);
580++ adcli_conn_set_use_ldaps (conn, false);
581+ return conn;
582+ }
583+
584+@@ -1389,6 +1436,20 @@ adcli_conn_set_domain_controller (adcli_conn *conn,
585+ no_more_disco (conn);
586+ }
587+
588++bool
589++adcli_conn_get_use_ldaps (adcli_conn *conn)
590++{
591++ return_val_if_fail (conn != NULL, NULL);
592++ return conn->use_ldaps;
593++}
594++
595++void
596++adcli_conn_set_use_ldaps (adcli_conn *conn, bool value)
597++{
598++ return_if_fail (conn != NULL);
599++ conn->use_ldaps = value;
600++}
601++
602+ const char *
603+ adcli_conn_get_domain_short (adcli_conn *conn)
604+ {
605+diff --git a/library/adconn.h b/library/adconn.h
606+index 37ebdd9..1d5faa8 100644
607+--- a/library/adconn.h
608++++ b/library/adconn.h
609+@@ -89,6 +89,10 @@ const char * adcli_conn_get_domain_controller (adcli_conn *conn);
610+ void adcli_conn_set_domain_controller (adcli_conn *conn,
611+ const char *value);
612+
613++bool adcli_conn_get_use_ldaps (adcli_conn *conn);
614++void adcli_conn_set_use_ldaps (adcli_conn *conn,
615++ bool value);
616++
617+ const char * adcli_conn_get_domain_short (adcli_conn *conn);
618+
619+ const char * adcli_conn_get_domain_sid (adcli_conn *conn);
620+diff --git a/tools/computer.c b/tools/computer.c
621+index 840e334..292c4d8 100644
622+--- a/tools/computer.c
623++++ b/tools/computer.c
624+@@ -113,12 +113,14 @@ typedef enum {
625+ opt_add_service_principal,
626+ opt_remove_service_principal,
627+ opt_description,
628++ opt_use_ldaps,
629+ } Option;
630+
631+ static adcli_tool_desc common_usages[] = {
632+ { opt_domain, "active directory domain name" },
633+ { opt_domain_realm, "kerberos realm for the domain" },
634+ { opt_domain_controller, "domain controller to connect to" },
635++ { opt_use_ldaps, "use LDAPS port for communication" },
636+ { opt_host_fqdn, "override the fully qualified domain name of the\n"
637+ "local machine" },
638+ { opt_host_keytab, "filename for the host kerberos keytab" },
639+@@ -311,6 +313,9 @@ parse_option (Option opt,
640+ case opt_description:
641+ adcli_enroll_set_description (enroll, optarg);
642+ return ADCLI_SUCCESS;
643++ case opt_use_ldaps:
644++ adcli_conn_set_use_ldaps (conn, true);
645++ return ADCLI_SUCCESS;
646+ case opt_verbose:
647+ return ADCLI_SUCCESS;
648+
649+@@ -357,6 +362,7 @@ adcli_tool_computer_join (adcli_conn *conn,
650+ { "domain-realm", required_argument, NULL, opt_domain_realm },
651+ { "domain-controller", required_argument, NULL, opt_domain_controller },
652+ { "domain-server", required_argument, NULL, opt_domain_controller }, /* compat */
653++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
654+ { "login-user", required_argument, NULL, opt_login_user },
655+ { "user", required_argument, NULL, opt_login_user }, /* compat */
656+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
657+@@ -688,6 +694,7 @@ adcli_tool_computer_preset (adcli_conn *conn,
658+ { "domain", required_argument, NULL, opt_domain },
659+ { "domain-realm", required_argument, NULL, opt_domain_realm },
660+ { "domain-controller", required_argument, NULL, opt_domain_controller },
661++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
662+ { "domain-ou", required_argument, NULL, opt_domain_ou },
663+ { "login-user", required_argument, NULL, opt_login_user },
664+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
665+@@ -800,6 +807,7 @@ adcli_tool_computer_reset (adcli_conn *conn,
666+ { "domain", required_argument, NULL, opt_domain },
667+ { "domain-realm", required_argument, NULL, opt_domain_realm },
668+ { "domain-controller", required_argument, NULL, opt_domain_controller },
669++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
670+ { "login-user", required_argument, NULL, opt_login_user },
671+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
672+ { "login-type", required_argument, NULL, opt_login_type },
673+@@ -888,6 +896,7 @@ adcli_tool_computer_delete (adcli_conn *conn,
674+ { "domain", required_argument, NULL, opt_domain },
675+ { "domain-realm", required_argument, NULL, opt_domain_realm },
676+ { "domain-controller", required_argument, NULL, opt_domain_controller },
677++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
678+ { "login-user", required_argument, NULL, opt_login_user },
679+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
680+ { "no-password", no_argument, 0, opt_no_password },
681+@@ -985,6 +994,7 @@ adcli_tool_computer_show (adcli_conn *conn,
682+ { "domain", required_argument, NULL, opt_domain },
683+ { "domain-realm", required_argument, NULL, opt_domain_realm },
684+ { "domain-controller", required_argument, NULL, opt_domain_controller },
685++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
686+ { "login-user", required_argument, NULL, opt_login_user },
687+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
688+ { "login-type", required_argument, NULL, opt_login_type },
689+diff --git a/tools/entry.c b/tools/entry.c
690+index f361845..05e4313 100644
691+--- a/tools/entry.c
692++++ b/tools/entry.c
693+@@ -53,6 +53,7 @@ typedef enum {
694+ opt_unix_gid,
695+ opt_unix_shell,
696+ opt_nis_domain,
697++ opt_use_ldaps,
698+ } Option;
699+
700+ static adcli_tool_desc common_usages[] = {
701+@@ -67,6 +68,7 @@ static adcli_tool_desc common_usages[] = {
702+ { opt_domain, "active directory domain name" },
703+ { opt_domain_realm, "kerberos realm for the domain" },
704+ { opt_domain_controller, "domain directory server to connect to" },
705++ { opt_use_ldaps, "use LDAPS port for communication" },
706+ { opt_login_ccache, "kerberos credential cache file which contains\n"
707+ "ticket to used to connect to the domain" },
708+ { opt_login_user, "user (usually administrative) login name of\n"
709+@@ -136,6 +138,9 @@ parse_option (Option opt,
710+ stdin_password = 1;
711+ }
712+ return ADCLI_SUCCESS;
713++ case opt_use_ldaps:
714++ adcli_conn_set_use_ldaps (conn, true);
715++ return ADCLI_SUCCESS;
716+ case opt_verbose:
717+ return ADCLI_SUCCESS;
718+ default:
719+@@ -172,6 +177,7 @@ adcli_tool_user_create (adcli_conn *conn,
720+ { "domain", required_argument, NULL, opt_domain },
721+ { "domain-realm", required_argument, NULL, opt_domain_realm },
722+ { "domain-controller", required_argument, NULL, opt_domain_controller },
723++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
724+ { "login-user", required_argument, NULL, opt_login_user },
725+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
726+ { "no-password", no_argument, 0, opt_no_password },
727+@@ -306,6 +312,7 @@ adcli_tool_user_delete (adcli_conn *conn,
728+ { "domain", required_argument, NULL, opt_domain },
729+ { "domain-realm", required_argument, NULL, opt_domain_realm },
730+ { "domain-controller", required_argument, NULL, opt_domain_controller },
731++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
732+ { "login-user", required_argument, NULL, opt_login_user },
733+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
734+ { "no-password", no_argument, 0, opt_no_password },
735+@@ -394,6 +401,7 @@ adcli_tool_group_create (adcli_conn *conn,
736+ { "domain", required_argument, NULL, opt_domain },
737+ { "domain-realm", required_argument, NULL, opt_domain_realm },
738+ { "domain-controller", required_argument, NULL, opt_domain_controller },
739++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
740+ { "domain-ou", required_argument, NULL, opt_domain_ou },
741+ { "login-user", required_argument, NULL, opt_login_user },
742+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
743+@@ -496,6 +504,7 @@ adcli_tool_group_delete (adcli_conn *conn,
744+ { "domain", required_argument, NULL, opt_domain },
745+ { "domain-realm", required_argument, NULL, opt_domain_realm },
746+ { "domain-controller", required_argument, NULL, opt_domain_controller },
747++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
748+ { "login-user", required_argument, NULL, opt_login_user },
749+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
750+ { "no-password", no_argument, 0, opt_no_password },
751+@@ -622,6 +631,7 @@ adcli_tool_member_add (adcli_conn *conn,
752+ { "domain", required_argument, NULL, opt_domain },
753+ { "domain-realm", required_argument, NULL, opt_domain_realm },
754+ { "domain-controller", required_argument, NULL, opt_domain_controller },
755++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
756+ { "login-user", required_argument, NULL, opt_login_user },
757+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
758+ { "no-password", no_argument, 0, opt_no_password },
759+@@ -722,6 +732,7 @@ adcli_tool_member_remove (adcli_conn *conn,
760+ { "domain", required_argument, NULL, opt_domain },
761+ { "domain-realm", required_argument, NULL, opt_domain_realm },
762+ { "domain-controller", required_argument, NULL, opt_domain_controller },
763++ { "use-ldaps", no_argument, 0, opt_use_ldaps },
764+ { "login-user", required_argument, NULL, opt_login_user },
765+ { "login-ccache", optional_argument, NULL, opt_login_ccache },
766+ { "no-password", no_argument, 0, opt_no_password },
767+--
768+GitLab
769+
770diff --git a/debian/patches/delete-do-not-exit-if-keytab-cannot-be-read.patch b/debian/patches/delete-do-not-exit-if-keytab-cannot-be-read.patch
771new file mode 100644
772index 0000000..d5f8ac8
773--- /dev/null
774+++ b/debian/patches/delete-do-not-exit-if-keytab-cannot-be-read.patch
775@@ -0,0 +1,34 @@
776+From 40d3be22f6e518e4354aa7c3d0278291fcbed32f Mon Sep 17 00:00:00 2001
777+From: Sumit Bose <sbose@redhat.com>
778+Date: Fri, 5 Jun 2020 17:06:58 +0200
779+Subject: [PATCH] delete: do not exit if keytab cannot be read
780+
781+Reading the keytab is not required when deleting a host object in AD. It
782+is only needed in the case where the host was added with a manual set
783+NetBIOS name (--computer-name option) which does not match the short
784+hostname and no computer name was given at the delete-computer command
785+line.
786+
787+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1840752
788+---
789+ tools/computer.c | 2 --
790+ 1 file changed, 2 deletions(-)
791+
792+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/40d3be22f6e518e4354aa7c3d0278291fcbed32f
793+Last-Update: 2020-09-02
794+diff --git a/tools/computer.c b/tools/computer.c
795+index 292c4d8..a90c4b2 100644
796+--- a/tools/computer.c
797++++ b/tools/computer.c
798+@@ -952,8 +952,6 @@ adcli_tool_computer_delete (adcli_conn *conn,
799+ if (res != ADCLI_SUCCESS) {
800+ warnx ("couldn't lookup domain info from keytab: %s",
801+ adcli_get_last_error ());
802+- adcli_enroll_unref (enroll);
803+- return -res;
804+ }
805+
806+ res = adcli_conn_connect (conn);
807+--
808+GitLab
809+
810diff --git a/debian/patches/discovery-fix.patch b/debian/patches/discovery-fix.patch
811new file mode 100644
812index 0000000..ebd1adf
813--- /dev/null
814+++ b/debian/patches/discovery-fix.patch
815@@ -0,0 +1,29 @@
816+From 08bac0946de29f3e5de90743ce6dfc7118d4ad20 Mon Sep 17 00:00:00 2001
817+From: Sumit Bose <sbose@redhat.com>
818+Date: Tue, 11 Feb 2020 17:42:03 +0100
819+Subject: [PATCH] discovery fix
820+
821+Do not continue processing on closed connection.
822+
823+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1802258
824+---
825+ library/addisco.c | 1 +
826+ 1 file changed, 1 insertion(+)
827+
828+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/08bac0946de29f3e5de90743ce6dfc7118d4ad20
829+Last-Update: 2020-09-02
830+diff --git a/library/addisco.c b/library/addisco.c
831+index 6e73ead..f3b3546 100644
832+--- a/library/addisco.c
833++++ b/library/addisco.c
834+@@ -622,6 +622,7 @@ ldap_disco (const char *domain,
835+ "Couldn't perform discovery search");
836+ ldap_unbind_ext_s (ldap[i], NULL, NULL);
837+ ldap[i] = NULL;
838++ continue;
839+ }
840+
841+ /* From https://msdn.microsoft.com/en-us/library/ff718294.aspx first
842+--
843+GitLab
844+
845diff --git a/debian/patches/man-explain-optional-parameter-of-login-ccache-bette.patch b/debian/patches/man-explain-optional-parameter-of-login-ccache-bette.patch
846new file mode 100644
847index 0000000..0f3919b
848--- /dev/null
849+++ b/debian/patches/man-explain-optional-parameter-of-login-ccache-bette.patch
850@@ -0,0 +1,46 @@
851+From 93a39bd12db11dd407676f428cfbc30406a88c36 Mon Sep 17 00:00:00 2001
852+From: Sumit Bose <sbose@redhat.com>
853+Date: Mon, 15 Jun 2020 15:57:47 +0200
854+Subject: [PATCH] man: explain optional parameter of login-ccache better
855+
856+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791545
857+---
858+ doc/adcli.xml | 20 +++++++++++++-------
859+ 1 file changed, 13 insertions(+), 7 deletions(-)
860+
861+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/93a39bd12db11dd407676f428cfbc30406a88c36
862+Last-Update: 2020-09-02
863+diff --git a/doc/adcli.xml b/doc/adcli.xml
864+index acced25..ecf8726 100644
865+--- a/doc/adcli.xml
866++++ b/doc/adcli.xml
867+@@ -155,13 +155,19 @@ $ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.exa
868+ <varlistentry>
869+ <term><option>-C, --login-ccache=<parameter>ccache_name</parameter></option></term>
870+ <listitem><para>Use the specified kerberos credential
871+- cache to authenticate with the domain. If no credential
872+- cache is specified, the default kerberos credential
873+- cache will be used. Credential caches of type FILE can
874+- be given with the path to the file. For other
875+- credential cache types, e.g. DIR, KEYRING or KCM, the
876+- type must be specified explicitly together with a
877+- suitable identifier.</para></listitem>
878++ cache to authenticate with the domain. If no credential
879++ cache is specified, the default kerberos credential
880++ cache will be used. Credential caches of type FILE can
881++ be given with the path to the file. For other
882++ credential cache types, e.g. DIR, KEYRING or KCM, the
883++ type must be specified explicitly together with a
884++ suitable identifier.</para>
885++ <para>Please note that since the
886++ <parameter>ccache_name</parameter> is optional the
887++ =(equal) sign is mandatory. If = is missing the
888++ parameter is treated as optionless extra argument. How
889++ this is handled depends on the specific sub-command.
890++ </para></listitem>
891+ </varlistentry>
892+ <varlistentry>
893+ <term><option>-U, --login-user=<parameter>User</parameter></option></term>
894+--
895+GitLab
896+
897diff --git a/debian/patches/man-make-handling-of-optional-credential-cache-more-.patch b/debian/patches/man-make-handling-of-optional-credential-cache-more-.patch
898new file mode 100644
899index 0000000..da13c13
900--- /dev/null
901+++ b/debian/patches/man-make-handling-of-optional-credential-cache-more-.patch
902@@ -0,0 +1,43 @@
903+From 88fbb7e2395dec20b37697a213a097909870c21f Mon Sep 17 00:00:00 2001
904+From: Sumit Bose <sbose@redhat.com>
905+Date: Thu, 13 Aug 2020 17:10:01 +0200
906+Subject: [PATCH] man: make handling of optional credential cache more clear
907+
908+The optional Kerberos credential cache can only be used with the long
909+option name --login-ccache and not with the short version -C. To make
910+this more clear each option get its own entry.
911+
912+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791545
913+---
914+ doc/adcli.xml | 12 +++++++++---
915+ 1 file changed, 9 insertions(+), 3 deletions(-)
916+
917+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/88fbb7e2395dec20b37697a213a097909870c21f
918+Last-Update: 2020-09-02
919+diff --git a/doc/adcli.xml b/doc/adcli.xml
920+index ecf8726..1437679 100644
921+--- a/doc/adcli.xml
922++++ b/doc/adcli.xml
923+@@ -153,10 +153,16 @@ $ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.exa
924+ </para></listitem>
925+ </varlistentry>
926+ <varlistentry>
927+- <term><option>-C, --login-ccache=<parameter>ccache_name</parameter></option></term>
928+- <listitem><para>Use the specified kerberos credential
929++ <term><option>-C</option></term>
930++ <listitem><para>Use the default Kerberos credential
931++ cache to authenticate with the domain.
932++ </para></listitem>
933++ </varlistentry>
934++ <varlistentry>
935++ <term><option>--login-ccache<parameter>[=ccache_name]</parameter></option></term>
936++ <listitem><para>Use the specified Kerberos credential
937+ cache to authenticate with the domain. If no credential
938+- cache is specified, the default kerberos credential
939++ cache is specified, the default Kerberos credential
940+ cache will be used. Credential caches of type FILE can
941+ be given with the path to the file. For other
942+ credential cache types, e.g. DIR, KEYRING or KCM, the
943+--
944+GitLab
945+
946diff --git a/debian/patches/man-move-note-to-the-right-section.patch b/debian/patches/man-move-note-to-the-right-section.patch
947new file mode 100644
948index 0000000..0b25c4d
949--- /dev/null
950+++ b/debian/patches/man-move-note-to-the-right-section.patch
951@@ -0,0 +1,50 @@
952+From d2d3879bdfcea70757a8b0527882e79e8b5c6e70 Mon Sep 17 00:00:00 2001
953+From: Sumit Bose <sbose@redhat.com>
954+Date: Wed, 27 Nov 2019 18:26:44 +0100
955+Subject: [PATCH] man: move note to the right section
956+
957+Unfortunately the note about the password lifetime was added to the join
958+section. This patch move it to the update section where it belongs to.
959+
960+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1738573
961+ https://bugzilla.redhat.com/show_bug.cgi?id=1745931
962+ https://bugzilla.redhat.com/show_bug.cgi?id=1774622
963+---
964+ doc/adcli.xml | 12 ++++++------
965+ 1 file changed, 6 insertions(+), 6 deletions(-)
966+
967+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/d2d3879bdfcea70757a8b0527882e79e8b5c6e70
968+Last-Update: 2020-09-02
969+diff --git a/doc/adcli.xml b/doc/adcli.xml
970+index 4f201e0..9faf96a 100644
971+--- a/doc/adcli.xml
972++++ b/doc/adcli.xml
973+@@ -330,11 +330,7 @@ Password for Administrator:
974+ important here is currently the
975+ <option>workgroup</option> option, see
976+ <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
977+- for details.</para>
978+- <para>Note that if the machine account password is not
979+- older than 30 days, you have to pass
980+- <option>--computer-password-lifetime=0</option> to
981+- force the update.</para></listitem>
982++ for details.</para></listitem>
983+ </varlistentry>
984+ <varlistentry>
985+ <term><option>--samba-data-tool=<parameter>/path/to/net</parameter></option></term>
986+@@ -472,7 +468,11 @@ $ adcli update --login-ccache=/tmp/krbcc_123
987+ important here is currently the
988+ <option>workgroup</option> option, see
989+ <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
990+- for details.</para></listitem>
991++ for details.</para>
992++ <para>Note that if the machine account password is not
993++ older than 30 days, you have to pass
994++ <option>--computer-password-lifetime=0</option> to
995++ force the update.</para></listitem>
996+ </varlistentry>
997+ <varlistentry>
998+ <term><option>--samba-data-tool=<parameter>/path/to/net</parameter></option></term>
999+--
1000+GitLab
1001+
1002diff --git a/debian/patches/series b/debian/patches/series
1003new file mode 100644
1004index 0000000..0d3657d
1005--- /dev/null
1006+++ b/debian/patches/series
1007@@ -0,0 +1,11 @@
1008+tools-add-show-computer-command.patch
1009+add-description-option-to-join-and-update.patch
1010+Use-GSS-SPNEGO-if-available.patch
1011+add-option-use-ldaps.patch
1012+man-move-note-to-the-right-section.patch
1013+man-explain-optional-parameter-of-login-ccache-bette.patch
1014+man-make-handling-of-optional-credential-cache-more-.patch
1015+tools-fix-typo-in-show-password-help-output.patch
1016+discovery-fix.patch
1017+delete-do-not-exit-if-keytab-cannot-be-read.patch
1018+tools-disable-SSSD-s-locator-plugin.patch
1019diff --git a/debian/patches/tools-add-show-computer-command.patch b/debian/patches/tools-add-show-computer-command.patch
1020new file mode 100644
1021index 0000000..29bb77f
1022--- /dev/null
1023+++ b/debian/patches/tools-add-show-computer-command.patch
1024@@ -0,0 +1,341 @@
1025+From 0a169bd9b2687293f74bb57694eb82f9769610c9 Mon Sep 17 00:00:00 2001
1026+From: Sumit Bose <sbose@redhat.com>
1027+Date: Wed, 27 Nov 2019 12:34:45 +0100
1028+Subject: [PATCH] tools: add show-computer command
1029+
1030+The show-computer command prints the LDAP attributes of the related
1031+computer object from AD.
1032+
1033+Related to https://bugzilla.redhat.com/show_bug.cgi?id=1737342
1034+---
1035+ doc/adcli.xml | 28 ++++++++++++++
1036+ library/adenroll.c | 78 +++++++++++++++++++++++++++++---------
1037+ library/adenroll.h | 5 +++
1038+ tools/computer.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
1039+ tools/tools.c | 1 +
1040+ tools/tools.h | 4 ++
1041+ 6 files changed, 191 insertions(+), 18 deletions(-)
1042+
1043+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/0a169bd9b2687293f74bb57694eb82f9769610c9
1044+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1893784
1045+Last-Update: 2020-09-02
1046+diff --git a/doc/adcli.xml b/doc/adcli.xml
1047+index 9faf96a..1f93186 100644
1048+--- a/doc/adcli.xml
1049++++ b/doc/adcli.xml
1050+@@ -93,6 +93,11 @@
1051+ <arg choice="opt">--domain=domain.example.com</arg>
1052+ <arg choice="plain">computer</arg>
1053+ </cmdsynopsis>
1054++ <cmdsynopsis>
1055++ <command>adcli show-computer</command>
1056++ <arg choice="opt">--domain=domain.example.com</arg>
1057++ <arg choice="plain">computer</arg>
1058++ </cmdsynopsis>
1059+ </refsynopsisdiv>
1060+
1061+ <refsect1 id='general_overview'>
1062+@@ -811,6 +816,29 @@ Password for Administrator:
1063+
1064+ </refsect1>
1065+
1066++<refsect1 id='show_computer_account'>
1067++ <title>Show Computer Account Attributes</title>
1068++
1069++ <para><command>adcli show-computer</command> show the computer account
1070++ attributes stored in AD. The account must already exist.</para>
1071++
1072++<programlisting>
1073++$ adcli show-computer --domain=domain.example.com host2
1074++Password for Administrator:
1075++</programlisting>
1076++
1077++ <para>If the computer name contains a dot, then it is
1078++ treated as fully qualified host name, otherwise it is treated
1079++ as short computer name.</para>
1080++
1081++ <para>If no computer name is specified, then the host name of the
1082++ computer adcli is running on is used, as returned by
1083++ <literal>gethostname()</literal>.</para>
1084++
1085++ <para>The various global options can be used.</para>
1086++
1087++</refsect1>
1088++
1089+ <refsect1 id='bugs'>
1090+ <title>Bugs</title>
1091+ <para>
1092+diff --git a/library/adenroll.c b/library/adenroll.c
1093+index 524663a..8d2adeb 100644
1094+--- a/library/adenroll.c
1095++++ b/library/adenroll.c
1096+@@ -71,6 +71,21 @@ static krb5_enctype v51_earlier_enctypes[] = {
1097+ 0
1098+ };
1099+
1100++static char *default_ad_ldap_attrs[] = {
1101++ "sAMAccountName",
1102++ "userPrincipalName",
1103++ "msDS-KeyVersionNumber",
1104++ "msDS-supportedEncryptionTypes",
1105++ "dNSHostName",
1106++ "servicePrincipalName",
1107++ "operatingSystem",
1108++ "operatingSystemVersion",
1109++ "operatingSystemServicePack",
1110++ "pwdLastSet",
1111++ "userAccountControl",
1112++ NULL,
1113++};
1114++
1115+ /* Some constants for the userAccountControl AD LDAP attribute, see e.g.
1116+ * https://support.microsoft.com/en-us/help/305144/how-to-use-the-useraccountcontrol-flags-to-manipulate-user-account-pro
1117+ * for details. */
1118+@@ -1213,19 +1228,6 @@ retrieve_computer_account (adcli_enroll *enroll)
1119+ char *end;
1120+ int ret;
1121+
1122+- char *attrs[] = {
1123+- "msDS-KeyVersionNumber",
1124+- "msDS-supportedEncryptionTypes",
1125+- "dNSHostName",
1126+- "servicePrincipalName",
1127+- "operatingSystem",
1128+- "operatingSystemVersion",
1129+- "operatingSystemServicePack",
1130+- "pwdLastSet",
1131+- "userAccountControl",
1132+- NULL,
1133+- };
1134+-
1135+ assert (enroll->computer_dn != NULL);
1136+ assert (enroll->computer_attributes == NULL);
1137+
1138+@@ -1233,7 +1235,8 @@ retrieve_computer_account (adcli_enroll *enroll)
1139+ assert (ldap != NULL);
1140+
1141+ ret = ldap_search_ext_s (ldap, enroll->computer_dn, LDAP_SCOPE_BASE,
1142+- "(objectClass=*)", attrs, 0, NULL, NULL, NULL, -1,
1143++ "(objectClass=*)", default_ad_ldap_attrs,
1144++ 0, NULL, NULL, NULL, -1,
1145+ &enroll->computer_attributes);
1146+
1147+ if (ret != LDAP_SUCCESS) {
1148+@@ -2179,12 +2182,11 @@ adcli_enroll_load (adcli_enroll *enroll)
1149+ }
1150+
1151+ adcli_result
1152+-adcli_enroll_update (adcli_enroll *enroll,
1153+- adcli_enroll_flags flags)
1154++adcli_enroll_read_computer_account (adcli_enroll *enroll,
1155++ adcli_enroll_flags flags)
1156+ {
1157+ adcli_result res = ADCLI_SUCCESS;
1158+ LDAP *ldap;
1159+- char *value;
1160+
1161+ return_unexpected_if_fail (enroll != NULL);
1162+
1163+@@ -2214,7 +2216,18 @@ adcli_enroll_update (adcli_enroll *enroll,
1164+ }
1165+
1166+ /* Get information about the computer account */
1167+- res = retrieve_computer_account (enroll);
1168++ return retrieve_computer_account (enroll);
1169++}
1170++
1171++adcli_result
1172++adcli_enroll_update (adcli_enroll *enroll,
1173++ adcli_enroll_flags flags)
1174++{
1175++ adcli_result res = ADCLI_SUCCESS;
1176++ LDAP *ldap;
1177++ char *value;
1178++
1179++ res = adcli_enroll_read_computer_account (enroll, flags);
1180+ if (res != ADCLI_SUCCESS)
1181+ return res;
1182+
1183+@@ -2242,6 +2255,35 @@ adcli_enroll_update (adcli_enroll *enroll,
1184+ return enroll_join_or_update_tasks (enroll, flags);
1185+ }
1186+
1187++adcli_result
1188++adcli_enroll_show_computer_attribute (adcli_enroll *enroll)
1189++{
1190++ LDAP *ldap;
1191++ size_t c;
1192++ char **vals;
1193++ size_t v;
1194++
1195++ ldap = adcli_conn_get_ldap_connection (enroll->conn);
1196++ assert (ldap != NULL);
1197++
1198++ for (c = 0; default_ad_ldap_attrs[c] != NULL; c++) {
1199++ vals = _adcli_ldap_parse_values (ldap,
1200++ enroll->computer_attributes,
1201++ default_ad_ldap_attrs[c]);
1202++ printf ("%s:\n", default_ad_ldap_attrs[c]);
1203++ if (vals == NULL) {
1204++ printf (" - not set -\n");
1205++ } else {
1206++ for (v = 0; vals[v] != NULL; v++) {
1207++ printf (" %s\n", vals[v]);
1208++ }
1209++ }
1210++ _adcli_strv_free (vals);
1211++ }
1212++
1213++ return ADCLI_SUCCESS;
1214++}
1215++
1216+ adcli_result
1217+ adcli_enroll_delete (adcli_enroll *enroll,
1218+ adcli_enroll_flags delete_flags)
1219+diff --git a/library/adenroll.h b/library/adenroll.h
1220+index 1d5d00d..11eb517 100644
1221+--- a/library/adenroll.h
1222++++ b/library/adenroll.h
1223+@@ -46,6 +46,11 @@ adcli_result adcli_enroll_join (adcli_enroll *enroll,
1224+ adcli_result adcli_enroll_update (adcli_enroll *enroll,
1225+ adcli_enroll_flags flags);
1226+
1227++adcli_result adcli_enroll_read_computer_account (adcli_enroll *enroll,
1228++ adcli_enroll_flags flags);
1229++
1230++adcli_result adcli_enroll_show_computer_attribute (adcli_enroll *enroll);
1231++
1232+ adcli_result adcli_enroll_delete (adcli_enroll *enroll,
1233+ adcli_enroll_flags delete_flags);
1234+
1235+diff --git a/tools/computer.c b/tools/computer.c
1236+index ac8a203..c8b96a4 100644
1237+--- a/tools/computer.c
1238++++ b/tools/computer.c
1239+@@ -964,3 +964,96 @@ adcli_tool_computer_delete (adcli_conn *conn,
1240+ adcli_enroll_unref (enroll);
1241+ return 0;
1242+ }
1243++
1244++int
1245++adcli_tool_computer_show (adcli_conn *conn,
1246++ int argc,
1247++ char *argv[])
1248++{
1249++ adcli_enroll *enroll;
1250++ adcli_result res;
1251++ int opt;
1252++
1253++ struct option options[] = {
1254++ { "domain", required_argument, NULL, opt_domain },
1255++ { "domain-realm", required_argument, NULL, opt_domain_realm },
1256++ { "domain-controller", required_argument, NULL, opt_domain_controller },
1257++ { "login-user", required_argument, NULL, opt_login_user },
1258++ { "login-ccache", optional_argument, NULL, opt_login_ccache },
1259++ { "login-type", required_argument, NULL, opt_login_type },
1260++ { "no-password", no_argument, 0, opt_no_password },
1261++ { "stdin-password", no_argument, 0, opt_stdin_password },
1262++ { "prompt-password", no_argument, 0, opt_prompt_password },
1263++ { "verbose", no_argument, NULL, opt_verbose },
1264++ { "help", no_argument, NULL, 'h' },
1265++ { 0 },
1266++ };
1267++
1268++ static adcli_tool_desc usages[] = {
1269++ { 0, "usage: adcli show-computer --domain=xxxx host1.example.com" },
1270++ { 0 },
1271++ };
1272++
1273++ enroll = adcli_enroll_new (conn);
1274++ if (enroll == NULL) {
1275++ warnx ("unexpected memory problems");
1276++ return -1;
1277++ }
1278++
1279++ while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) {
1280++ switch (opt) {
1281++ case 'h':
1282++ case '?':
1283++ case ':':
1284++ adcli_tool_usage (options, usages);
1285++ adcli_tool_usage (options, common_usages);
1286++ adcli_enroll_unref (enroll);
1287++ return opt == 'h' ? 0 : 2;
1288++ default:
1289++ res = parse_option ((Option)opt, optarg, conn, enroll);
1290++ if (res != ADCLI_SUCCESS) {
1291++ adcli_enroll_unref (enroll);
1292++ return res;
1293++ }
1294++ break;
1295++ }
1296++ }
1297++
1298++ argc -= optind;
1299++ argv += optind;
1300++
1301++ res = adcli_conn_connect (conn);
1302++ if (res != ADCLI_SUCCESS) {
1303++ warnx ("couldn't connect to %s domain: %s",
1304++ adcli_conn_get_domain_name (conn),
1305++ adcli_get_last_error ());
1306++ adcli_enroll_unref (enroll);
1307++ return -res;
1308++ }
1309++
1310++ if (argc == 1) {
1311++ parse_fqdn_or_name (enroll, argv[0]);
1312++ }
1313++
1314++ res = adcli_enroll_read_computer_account (enroll, 0);
1315++ if (res != ADCLI_SUCCESS) {
1316++ warnx ("couldn't read data for %s: %s",
1317++ adcli_enroll_get_host_fqdn (enroll) != NULL
1318++ ? adcli_enroll_get_host_fqdn (enroll)
1319++ : adcli_enroll_get_computer_name (enroll),
1320++ adcli_get_last_error ());
1321++ adcli_enroll_unref (enroll);
1322++ return -res;
1323++ }
1324++
1325++ res = adcli_enroll_show_computer_attribute (enroll);
1326++ if (res != ADCLI_SUCCESS) {
1327++ warnx ("couldn't print data for %s: %s",
1328++ argv[0], adcli_get_last_error ());
1329++ adcli_enroll_unref (enroll);
1330++ return -res;
1331++ }
1332++
1333++ adcli_enroll_unref (enroll);
1334++ return 0;
1335++}
1336+diff --git a/tools/tools.c b/tools/tools.c
1337+index fc9fa9a..9d422f2 100644
1338+--- a/tools/tools.c
1339++++ b/tools/tools.c
1340+@@ -59,6 +59,7 @@ struct {
1341+ { "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", },
1342+ { "reset-computer", adcli_tool_computer_reset, "Reset a computer account", },
1343+ { "delete-computer", adcli_tool_computer_delete, "Delete a computer account", },
1344++ { "show-computer", adcli_tool_computer_show, "Show computer account attributes stored in AD", },
1345+ { "create-user", adcli_tool_user_create, "Create a user account", },
1346+ { "delete-user", adcli_tool_user_delete, "Delete a user account", },
1347+ { "create-group", adcli_tool_group_create, "Create a group", },
1348+diff --git a/tools/tools.h b/tools/tools.h
1349+index 8cebbf9..3702875 100644
1350+--- a/tools/tools.h
1351++++ b/tools/tools.h
1352+@@ -78,6 +78,10 @@ int adcli_tool_computer_delete (adcli_conn *conn,
1353+ int argc,
1354+ char *argv[]);
1355+
1356++int adcli_tool_computer_show (adcli_conn *conn,
1357++ int argc,
1358++ char *argv[]);
1359++
1360+ int adcli_tool_user_create (adcli_conn *conn,
1361+ int argc,
1362+ char *argv[]);
1363+--
1364+GitLab
1365+
1366diff --git a/debian/patches/tools-disable-SSSD-s-locator-plugin.patch b/debian/patches/tools-disable-SSSD-s-locator-plugin.patch
1367new file mode 100644
1368index 0000000..8fa4ecb
1369--- /dev/null
1370+++ b/debian/patches/tools-disable-SSSD-s-locator-plugin.patch
1371@@ -0,0 +1,43 @@
1372+From 50d580c58dab5928cadfc6ca82aedccee58eaced Mon Sep 17 00:00:00 2001
1373+From: Sumit Bose <sbose@redhat.com>
1374+Date: Fri, 5 Jun 2020 17:28:28 +0200
1375+Subject: [PATCH] tools: disable SSSD's locator plugin
1376+
1377+MIT's libkrb5 checks available locator plugins first before checking the
1378+config file. This might cause issues when the locator plugin returns a
1379+different DC than the one used for the LDAP connection if some data must
1380+be replicated.
1381+
1382+This patch sets the SSSD_KRB5_LOCATOR_DISABLE environment variable to
1383+'true' to disable SSSD's locator plugin for adcli.
1384+
1385+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1762633
1386+---
1387+ tools/tools.c | 2 ++
1388+ 1 file changed, 2 insertions(+)
1389+
1390+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/50d580c58dab5928cadfc6ca82aedccee58eaced
1391+Last-Update: 2020-09-02
1392+diff --git a/tools/tools.c b/tools/tools.c
1393+index 9d422f2..1b6d879 100644
1394+--- a/tools/tools.c
1395++++ b/tools/tools.c
1396+@@ -296,6 +296,7 @@ cleanup_krb5_conf_directory (void)
1397+ }
1398+
1399+ unsetenv ("KRB5_CONFIG");
1400++ unsetenv ("SSSD_KRB5_LOCATOR_DISABLE");
1401+ }
1402+
1403+ static void
1404+@@ -394,6 +395,7 @@ setup_krb5_conf_directory (adcli_conn *conn)
1405+ adcli_krb5_conf_filename = filename;
1406+ adcli_krb5_d_directory = snippets;
1407+ setenv ("KRB5_CONFIG", adcli_krb5_conf_filename, 1);
1408++ setenv ("SSSD_KRB5_LOCATOR_DISABLE", "true", 1);
1409+
1410+ } else {
1411+ free (filename);
1412+--
1413+GitLab
1414+
1415diff --git a/debian/patches/tools-fix-typo-in-show-password-help-output.patch b/debian/patches/tools-fix-typo-in-show-password-help-output.patch
1416new file mode 100644
1417index 0000000..cf712b2
1418--- /dev/null
1419+++ b/debian/patches/tools-fix-typo-in-show-password-help-output.patch
1420@@ -0,0 +1,28 @@
1421+From d70075c597e7ebc1683d407409c45b04110676a0 Mon Sep 17 00:00:00 2001
1422+From: Sumit Bose <sbose@redhat.com>
1423+Date: Mon, 15 Jun 2020 15:41:53 +0200
1424+Subject: [PATCH] tools: fix typo in show-password help output
1425+
1426+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791611
1427+---
1428+ tools/computer.c | 2 +-
1429+ 1 file changed, 1 insertion(+), 1 deletion(-)
1430+
1431+Origin: upstream, https://gitlab.freedesktop.org/realmd/adcli/-/commit/d70075c597e7ebc1683d407409c45b04110676a0
1432+Last-Update: 2020-09-02
1433+diff --git a/tools/computer.c b/tools/computer.c
1434+index a90c4b2..24ea258 100644
1435+--- a/tools/computer.c
1436++++ b/tools/computer.c
1437+@@ -154,7 +154,7 @@ static adcli_tool_desc common_usages[] = {
1438+ "accounts" },
1439+ { opt_show_details, "show information about joining the domain after\n"
1440+ "a successful join" },
1441+- { opt_show_password, "show computer account password after after a\n"
1442++ { opt_show_password, "show computer account password after a\n"
1443+ "successful join" },
1444+ { opt_add_samba_data, "add domain SID and computer account password\n"
1445+ "to the Samba specific configuration database" },
1446+--
1447+GitLab
1448+

Subscribers

People subscribed via source and target branches