diff --git a/.gitignore b/.gitignore index a1343b9..ac6fbea 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /adcli-0.8.0.tar.gz /adcli-0.8.2.tar.gz /adcli-0.9.0.tar.gz +/adcli-0.9.1.tar.gz diff --git a/0001-delete-do-not-exit-if-keytab-cannot-be-read.patch b/0001-delete-do-not-exit-if-keytab-cannot-be-read.patch deleted file mode 100644 index 15aaf07..0000000 --- a/0001-delete-do-not-exit-if-keytab-cannot-be-read.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 40d3be22f6e518e4354aa7c3d0278291fcbed32f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 5 Jun 2020 17:06:58 +0200 -Subject: [PATCH] delete: do not exit if keytab cannot be read - -Reading the keytab is not required when deleting a host object in AD. It -is only needed in the case where the host was added with a manual set -NetBIOS name (--computer-name option) which does not match the short -hostname and no computer name was given at the delete-computer command -line. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1840752 ---- - tools/computer.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/tools/computer.c b/tools/computer.c -index 292c4d8..a90c4b2 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -952,8 +952,6 @@ adcli_tool_computer_delete (adcli_conn *conn, - if (res != ADCLI_SUCCESS) { - warnx ("couldn't lookup domain info from keytab: %s", - adcli_get_last_error ()); -- adcli_enroll_unref (enroll); -- return -res; - } - - res = adcli_conn_connect (conn); --- -2.26.2 - diff --git a/0001-man-move-note-to-the-right-section.patch b/0001-man-move-note-to-the-right-section.patch deleted file mode 100644 index c128204..0000000 --- a/0001-man-move-note-to-the-right-section.patch +++ /dev/null @@ -1,48 +0,0 @@ -From d2d3879bdfcea70757a8b0527882e79e8b5c6e70 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 27 Nov 2019 18:26:44 +0100 -Subject: [PATCH 1/6] man: move note to the right section - -Unfortunately the note about the password lifetime was added to the join -section. This patch move it to the update section where it belongs to. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1738573 - https://bugzilla.redhat.com/show_bug.cgi?id=1745931 - https://bugzilla.redhat.com/show_bug.cgi?id=1774622 ---- - doc/adcli.xml | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 4f201e0..9faf96a 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -330,11 +330,7 @@ Password for Administrator: - important here is currently the - option, see - smb.conf5 -- for details. -- Note that if the machine account password is not -- older than 30 days, you have to pass -- to -- force the update. -+ for details. - - - -@@ -472,7 +468,11 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - important here is currently the - option, see - smb.conf5 -- for details. -+ for details. -+ Note that if the machine account password is not -+ older than 30 days, you have to pass -+ to -+ force the update. - - - --- -2.25.1 - diff --git a/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch b/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch deleted file mode 100644 index 13a72a1..0000000 --- a/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 76ca1e6737742208d83e016d43a3379e378f8d90 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 14 Oct 2020 17:44:10 +0200 -Subject: [PATCH 01/10] tools: add missing use-ldaps option to update and - testjoin - -When adding the use-ldaps option the update and testjoin sub-commands -were forgotten. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1883467 ---- - tools/computer.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/tools/computer.c b/tools/computer.c -index 24ea258..5a97d8b 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -491,6 +491,7 @@ adcli_tool_computer_update (adcli_conn *conn, - struct option options[] = { - { "domain", required_argument, NULL, opt_domain }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "host-fqdn", required_argument, 0, opt_host_fqdn }, - { "computer-name", required_argument, 0, opt_computer_name }, - { "host-keytab", required_argument, 0, opt_host_keytab }, -@@ -612,6 +613,7 @@ adcli_tool_computer_testjoin (adcli_conn *conn, - struct option options[] = { - { "domain", required_argument, NULL, opt_domain }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "host-keytab", required_argument, 0, opt_host_keytab }, - { "verbose", no_argument, NULL, opt_verbose }, - { "help", no_argument, NULL, 'h' }, --- -2.28.0 - diff --git a/0001-tools-disable-SSSD-s-locator-plugin.patch b/0001-tools-disable-SSSD-s-locator-plugin.patch deleted file mode 100644 index 07d791e..0000000 --- a/0001-tools-disable-SSSD-s-locator-plugin.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 50d580c58dab5928cadfc6ca82aedccee58eaced Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 5 Jun 2020 17:28:28 +0200 -Subject: [PATCH] tools: disable SSSD's locator plugin - -MIT's libkrb5 checks available locator plugins first before checking the -config file. This might cause issues when the locator plugin returns a -different DC than the one used for the LDAP connection if some data must -be replicated. - -This patch sets the SSSD_KRB5_LOCATOR_DISABLE environment variable to -'true' to disable SSSD's locator plugin for adcli. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1762633 ---- - tools/tools.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/tools/tools.c b/tools/tools.c -index 9d422f2..1b6d879 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -296,6 +296,7 @@ cleanup_krb5_conf_directory (void) - } - - unsetenv ("KRB5_CONFIG"); -+ unsetenv ("SSSD_KRB5_LOCATOR_DISABLE"); - } - - static void -@@ -394,6 +395,7 @@ setup_krb5_conf_directory (adcli_conn *conn) - adcli_krb5_conf_filename = filename; - adcli_krb5_d_directory = snippets; - setenv ("KRB5_CONFIG", adcli_krb5_conf_filename, 1); -+ setenv ("SSSD_KRB5_LOCATOR_DISABLE", "true", 1); - - } else { - free (filename); --- -2.26.2 - diff --git a/0001-tools-fix-typo-in-show-password-help-output.patch b/0001-tools-fix-typo-in-show-password-help-output.patch deleted file mode 100644 index 3e16726..0000000 --- a/0001-tools-fix-typo-in-show-password-help-output.patch +++ /dev/null @@ -1,26 +0,0 @@ -From d70075c597e7ebc1683d407409c45b04110676a0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Jun 2020 15:41:53 +0200 -Subject: [PATCH 1/3] tools: fix typo in show-password help output - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791611 ---- - tools/computer.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/computer.c b/tools/computer.c -index a90c4b2..24ea258 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -154,7 +154,7 @@ static adcli_tool_desc common_usages[] = { - "accounts" }, - { opt_show_details, "show information about joining the domain after\n" - "a successful join" }, -- { opt_show_password, "show computer account password after after a\n" -+ { opt_show_password, "show computer account password after a\n" - "successful join" }, - { opt_add_samba_data, "add domain SID and computer account password\n" - "to the Samba specific configuration database" }, --- -2.26.2 - diff --git a/0002-join-update-set-dNSHostName-if-not-set.patch b/0002-join-update-set-dNSHostName-if-not-set.patch deleted file mode 100644 index 83fc958..0000000 --- a/0002-join-update-set-dNSHostName-if-not-set.patch +++ /dev/null @@ -1,59 +0,0 @@ -From beb7abfacc0010987d2cd8ab70f7c373d309eed9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 15 Oct 2020 18:01:12 +0200 -Subject: [PATCH 02/10] join/update: set dNSHostName if not set - -If during a join or update an existing AD computer object does not have -the dNSHostName attribute set it will be set with the current hostname. -This is important for cases where the user doing the join or update only -has "Validated write to service principal name" for the computer object. -The validated write with fully-qualified names can only be successful if -dNSHostName is set, see [MS-ADTS] section 3.1.1.5.3.1.1.4 "Validated -Writes - servicePrincipalName" for details. - -Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1734764 ---- - library/adenroll.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 246f658..e745295 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1403,21 +1403,29 @@ update_computer_account (adcli_enroll *enroll) - { - int res = 0; - LDAP *ldap; -+ char *value = NULL; - - ldap = adcli_conn_get_ldap_connection (enroll->conn); - return_if_fail (ldap != NULL); - - /* Only update attributes which are explicitly given on the command -- * line. Otherwise 'adcli update' must be always called with the same -- * set of options to make sure existing attributes are not deleted or -- * overwritten with different values. */ -- if (enroll->host_fqdn_explicit) { -+ * line or not set in the existing AD object. Otherwise 'adcli update' -+ * must be always called with the same set of options to make sure -+ * existing attributes are not deleted or overwritten with different -+ * values. */ -+ if (enroll->computer_attributes != NULL) { -+ value = _adcli_ldap_parse_value (ldap, -+ enroll->computer_attributes, -+ "dNSHostName"); -+ } -+ if (enroll->host_fqdn_explicit || value == NULL ) { - char *vals_dNSHostName[] = { enroll->host_fqdn, NULL }; - LDAPMod dNSHostName = { LDAP_MOD_REPLACE, "dNSHostName", { vals_dNSHostName, } }; - LDAPMod *mods[] = { &dNSHostName, NULL }; - - res |= update_computer_attribute (enroll, ldap, mods); - } -+ free (value); - - if (res == ADCLI_SUCCESS && enroll->trusted_for_delegation_explicit) { - char *vals_userAccountControl[] = { NULL , NULL }; --- -2.28.0 - diff --git a/0002-man-explain-optional-parameter-of-login-ccache-bette.patch b/0002-man-explain-optional-parameter-of-login-ccache-bette.patch deleted file mode 100644 index a76cbb6..0000000 --- a/0002-man-explain-optional-parameter-of-login-ccache-bette.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 93a39bd12db11dd407676f428cfbc30406a88c36 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Jun 2020 15:57:47 +0200 -Subject: [PATCH 2/3] man: explain optional parameter of login-ccache better - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791545 ---- - doc/adcli.xml | 20 +++++++++++++------- - 1 file changed, 13 insertions(+), 7 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index acced25..ecf8726 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -155,13 +155,19 @@ $ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.exa - - - Use the specified kerberos credential -- cache to authenticate with the domain. If no credential -- cache is specified, the default kerberos credential -- cache will be used. Credential caches of type FILE can -- be given with the path to the file. For other -- credential cache types, e.g. DIR, KEYRING or KCM, the -- type must be specified explicitly together with a -- suitable identifier. -+ cache to authenticate with the domain. If no credential -+ cache is specified, the default kerberos credential -+ cache will be used. Credential caches of type FILE can -+ be given with the path to the file. For other -+ credential cache types, e.g. DIR, KEYRING or KCM, the -+ type must be specified explicitly together with a -+ suitable identifier. -+ Please note that since the -+ ccache_name is optional the -+ =(equal) sign is mandatory. If = is missing the -+ parameter is treated as optionless extra argument. How -+ this is handled depends on the specific sub-command. -+ - - - --- -2.26.2 - diff --git a/0002-tools-add-show-computer-command.patch b/0002-tools-add-show-computer-command.patch deleted file mode 100644 index 67684d1..0000000 --- a/0002-tools-add-show-computer-command.patch +++ /dev/null @@ -1,338 +0,0 @@ -From 0a169bd9b2687293f74bb57694eb82f9769610c9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 27 Nov 2019 12:34:45 +0100 -Subject: [PATCH 2/6] tools: add show-computer command - -The show-computer command prints the LDAP attributes of the related -computer object from AD. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1737342 ---- - doc/adcli.xml | 28 ++++++++++++++ - library/adenroll.c | 78 +++++++++++++++++++++++++++++--------- - library/adenroll.h | 5 +++ - tools/computer.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ - tools/tools.c | 1 + - tools/tools.h | 4 ++ - 6 files changed, 191 insertions(+), 18 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 9faf96a..1f93186 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -93,6 +93,11 @@ - --domain=domain.example.com - computer - -+ -+ adcli show-computer -+ --domain=domain.example.com -+ computer -+ - - - -@@ -811,6 +816,29 @@ Password for Administrator: - - - -+ -+ Show Computer Account Attributes -+ -+ adcli show-computer show the computer account -+ attributes stored in AD. The account must already exist. -+ -+ -+$ adcli show-computer --domain=domain.example.com host2 -+Password for Administrator: -+ -+ -+ If the computer name contains a dot, then it is -+ treated as fully qualified host name, otherwise it is treated -+ as short computer name. -+ -+ If no computer name is specified, then the host name of the -+ computer adcli is running on is used, as returned by -+ gethostname(). -+ -+ The various global options can be used. -+ -+ -+ - - Bugs - -diff --git a/library/adenroll.c b/library/adenroll.c -index 524663a..8d2adeb 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -71,6 +71,21 @@ static krb5_enctype v51_earlier_enctypes[] = { - 0 - }; - -+static char *default_ad_ldap_attrs[] = { -+ "sAMAccountName", -+ "userPrincipalName", -+ "msDS-KeyVersionNumber", -+ "msDS-supportedEncryptionTypes", -+ "dNSHostName", -+ "servicePrincipalName", -+ "operatingSystem", -+ "operatingSystemVersion", -+ "operatingSystemServicePack", -+ "pwdLastSet", -+ "userAccountControl", -+ NULL, -+}; -+ - /* Some constants for the userAccountControl AD LDAP attribute, see e.g. - * https://support.microsoft.com/en-us/help/305144/how-to-use-the-useraccountcontrol-flags-to-manipulate-user-account-pro - * for details. */ -@@ -1213,19 +1228,6 @@ retrieve_computer_account (adcli_enroll *enroll) - char *end; - int ret; - -- char *attrs[] = { -- "msDS-KeyVersionNumber", -- "msDS-supportedEncryptionTypes", -- "dNSHostName", -- "servicePrincipalName", -- "operatingSystem", -- "operatingSystemVersion", -- "operatingSystemServicePack", -- "pwdLastSet", -- "userAccountControl", -- NULL, -- }; -- - assert (enroll->computer_dn != NULL); - assert (enroll->computer_attributes == NULL); - -@@ -1233,7 +1235,8 @@ retrieve_computer_account (adcli_enroll *enroll) - assert (ldap != NULL); - - ret = ldap_search_ext_s (ldap, enroll->computer_dn, LDAP_SCOPE_BASE, -- "(objectClass=*)", attrs, 0, NULL, NULL, NULL, -1, -+ "(objectClass=*)", default_ad_ldap_attrs, -+ 0, NULL, NULL, NULL, -1, - &enroll->computer_attributes); - - if (ret != LDAP_SUCCESS) { -@@ -2179,12 +2182,11 @@ adcli_enroll_load (adcli_enroll *enroll) - } - - adcli_result --adcli_enroll_update (adcli_enroll *enroll, -- adcli_enroll_flags flags) -+adcli_enroll_read_computer_account (adcli_enroll *enroll, -+ adcli_enroll_flags flags) - { - adcli_result res = ADCLI_SUCCESS; - LDAP *ldap; -- char *value; - - return_unexpected_if_fail (enroll != NULL); - -@@ -2214,7 +2216,18 @@ adcli_enroll_update (adcli_enroll *enroll, - } - - /* Get information about the computer account */ -- res = retrieve_computer_account (enroll); -+ return retrieve_computer_account (enroll); -+} -+ -+adcli_result -+adcli_enroll_update (adcli_enroll *enroll, -+ adcli_enroll_flags flags) -+{ -+ adcli_result res = ADCLI_SUCCESS; -+ LDAP *ldap; -+ char *value; -+ -+ res = adcli_enroll_read_computer_account (enroll, flags); - if (res != ADCLI_SUCCESS) - return res; - -@@ -2242,6 +2255,35 @@ adcli_enroll_update (adcli_enroll *enroll, - return enroll_join_or_update_tasks (enroll, flags); - } - -+adcli_result -+adcli_enroll_show_computer_attribute (adcli_enroll *enroll) -+{ -+ LDAP *ldap; -+ size_t c; -+ char **vals; -+ size_t v; -+ -+ ldap = adcli_conn_get_ldap_connection (enroll->conn); -+ assert (ldap != NULL); -+ -+ for (c = 0; default_ad_ldap_attrs[c] != NULL; c++) { -+ vals = _adcli_ldap_parse_values (ldap, -+ enroll->computer_attributes, -+ default_ad_ldap_attrs[c]); -+ printf ("%s:\n", default_ad_ldap_attrs[c]); -+ if (vals == NULL) { -+ printf (" - not set -\n"); -+ } else { -+ for (v = 0; vals[v] != NULL; v++) { -+ printf (" %s\n", vals[v]); -+ } -+ } -+ _adcli_strv_free (vals); -+ } -+ -+ return ADCLI_SUCCESS; -+} -+ - adcli_result - adcli_enroll_delete (adcli_enroll *enroll, - adcli_enroll_flags delete_flags) -diff --git a/library/adenroll.h b/library/adenroll.h -index 1d5d00d..11eb517 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -46,6 +46,11 @@ adcli_result adcli_enroll_join (adcli_enroll *enroll, - adcli_result adcli_enroll_update (adcli_enroll *enroll, - adcli_enroll_flags flags); - -+adcli_result adcli_enroll_read_computer_account (adcli_enroll *enroll, -+ adcli_enroll_flags flags); -+ -+adcli_result adcli_enroll_show_computer_attribute (adcli_enroll *enroll); -+ - adcli_result adcli_enroll_delete (adcli_enroll *enroll, - adcli_enroll_flags delete_flags); - -diff --git a/tools/computer.c b/tools/computer.c -index ac8a203..c8b96a4 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -964,3 +964,96 @@ adcli_tool_computer_delete (adcli_conn *conn, - adcli_enroll_unref (enroll); - return 0; - } -+ -+int -+adcli_tool_computer_show (adcli_conn *conn, -+ int argc, -+ char *argv[]) -+{ -+ adcli_enroll *enroll; -+ adcli_result res; -+ int opt; -+ -+ struct option options[] = { -+ { "domain", required_argument, NULL, opt_domain }, -+ { "domain-realm", required_argument, NULL, opt_domain_realm }, -+ { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "login-user", required_argument, NULL, opt_login_user }, -+ { "login-ccache", optional_argument, NULL, opt_login_ccache }, -+ { "login-type", required_argument, NULL, opt_login_type }, -+ { "no-password", no_argument, 0, opt_no_password }, -+ { "stdin-password", no_argument, 0, opt_stdin_password }, -+ { "prompt-password", no_argument, 0, opt_prompt_password }, -+ { "verbose", no_argument, NULL, opt_verbose }, -+ { "help", no_argument, NULL, 'h' }, -+ { 0 }, -+ }; -+ -+ static adcli_tool_desc usages[] = { -+ { 0, "usage: adcli show-computer --domain=xxxx host1.example.com" }, -+ { 0 }, -+ }; -+ -+ enroll = adcli_enroll_new (conn); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } -+ -+ 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: -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } -+ break; -+ } -+ } -+ -+ argc -= optind; -+ argv += optind; -+ -+ res = adcli_conn_connect (conn); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; -+ } -+ -+ if (argc == 1) { -+ parse_fqdn_or_name (enroll, argv[0]); -+ } -+ -+ res = adcli_enroll_read_computer_account (enroll, 0); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("couldn't read data for %s: %s", -+ adcli_enroll_get_host_fqdn (enroll) != NULL -+ ? adcli_enroll_get_host_fqdn (enroll) -+ : adcli_enroll_get_computer_name (enroll), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; -+ } -+ -+ res = adcli_enroll_show_computer_attribute (enroll); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("couldn't print data for %s: %s", -+ argv[0], adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; -+ } -+ -+ adcli_enroll_unref (enroll); -+ return 0; -+} -diff --git a/tools/tools.c b/tools/tools.c -index fc9fa9a..9d422f2 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -59,6 +59,7 @@ struct { - { "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", }, -+ { "show-computer", adcli_tool_computer_show, "Show computer account attributes stored in AD", }, - { "create-user", adcli_tool_user_create, "Create a user account", }, - { "delete-user", adcli_tool_user_delete, "Delete a user account", }, - { "create-group", adcli_tool_group_create, "Create a group", }, -diff --git a/tools/tools.h b/tools/tools.h -index 8cebbf9..3702875 100644 ---- a/tools/tools.h -+++ b/tools/tools.h -@@ -78,6 +78,10 @@ int adcli_tool_computer_delete (adcli_conn *conn, - int argc, - char *argv[]); - -+int adcli_tool_computer_show (adcli_conn *conn, -+ int argc, -+ char *argv[]); -+ - int adcli_tool_user_create (adcli_conn *conn, - int argc, - char *argv[]); --- -2.25.1 - diff --git a/0003-add-description-option-to-join-and-update.patch b/0003-add-description-option-to-join-and-update.patch deleted file mode 100644 index 43e1633..0000000 --- a/0003-add-description-option-to-join-and-update.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 3937a2a7db90611aa7a93248233b0c5d31e85a3e Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 27 Nov 2019 14:48:32 +0100 -Subject: [PATCH 3/6] add description option to join and update - -This new option allows to set the description LDAP attribute for the AD -computer object. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1737342 ---- - doc/adcli.xml | 10 ++++++++++ - library/adenroll.c | 29 +++++++++++++++++++++++++++++ - library/adenroll.h | 4 ++++ - tools/computer.c | 7 +++++++ - 4 files changed, 50 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 1f93186..dd30435 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -275,6 +275,11 @@ Password for Administrator: - Set the operating system version on the computer - account. Not set by default. - -+ -+ -+ Set the description attribute on the computer -+ account. Not set by default. -+ - - - Additional service name for a kerberos -@@ -416,6 +421,11 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - Set the operating system version on the computer - account. Not set by default. - -+ -+ -+ Set the description attribute on the computer -+ account. Not set by default. -+ - - - Additional service name for a Kerberos -diff --git a/library/adenroll.c b/library/adenroll.c -index 8d2adeb..246f658 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -83,6 +83,7 @@ static char *default_ad_ldap_attrs[] = { - "operatingSystemServicePack", - "pwdLastSet", - "userAccountControl", -+ "description", - NULL, - }; - -@@ -143,6 +144,7 @@ struct _adcli_enroll { - char *samba_data_tool; - bool trusted_for_delegation; - int trusted_for_delegation_explicit; -+ char *description; - }; - - static adcli_result -@@ -756,6 +758,8 @@ create_computer_account (adcli_enroll *enroll, - char *vals_userPrincipalName[] = { enroll->user_principal, NULL }; - LDAPMod userPrincipalName = { LDAP_MOD_ADD, "userPrincipalName", { vals_userPrincipalName, }, }; - LDAPMod servicePrincipalName = { LDAP_MOD_ADD, "servicePrincipalName", { enroll->service_principals, } }; -+ char *vals_description[] = { enroll->description, NULL }; -+ LDAPMod description = { LDAP_MOD_ADD, "description", { vals_description, }, }; - - char *val = NULL; - -@@ -774,6 +778,7 @@ create_computer_account (adcli_enroll *enroll, - &operatingSystemServicePack, - &userPrincipalName, - &servicePrincipalName, -+ &description, - NULL - }; - -@@ -1460,6 +1465,14 @@ update_computer_account (adcli_enroll *enroll) - res |= update_computer_attribute (enroll, ldap, mods); - } - -+ if (res == ADCLI_SUCCESS && enroll->description != NULL) { -+ char *vals_description[] = { enroll->description, NULL }; -+ LDAPMod description = { LDAP_MOD_REPLACE, "description", { vals_description, }, }; -+ LDAPMod *mods[] = { &description, NULL, }; -+ -+ res |= update_computer_attribute (enroll, ldap, mods); -+ } -+ - if (res != 0) - _adcli_info ("Updated existing computer account: %s", enroll->computer_dn); - } -@@ -2899,6 +2912,22 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, - enroll->trusted_for_delegation_explicit = 1; - } - -+void -+adcli_enroll_set_description (adcli_enroll *enroll, const char *value) -+{ -+ return_if_fail (enroll != NULL); -+ if (value != NULL && value[0] != '\0') { -+ _adcli_str_set (&enroll->description, value); -+ } -+} -+ -+const char * -+adcli_enroll_get_desciption (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ return enroll->description; -+} -+ - const char ** - adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll) - { -diff --git a/library/adenroll.h b/library/adenroll.h -index 11eb517..0606169 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -126,6 +126,10 @@ bool adcli_enroll_get_trusted_for_delegation (adcli_enroll *enroll - void adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, - bool value); - -+const char * adcli_enroll_get_desciption (adcli_enroll *enroll); -+void adcli_enroll_set_description (adcli_enroll *enroll, -+ const char *value); -+ - krb5_kvno adcli_enroll_get_kvno (adcli_enroll *enroll); - - void adcli_enroll_set_kvno (adcli_enroll *enroll, -diff --git a/tools/computer.c b/tools/computer.c -index c8b96a4..840e334 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -112,6 +112,7 @@ typedef enum { - opt_trusted_for_delegation, - opt_add_service_principal, - opt_remove_service_principal, -+ opt_description, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -142,6 +143,7 @@ static adcli_tool_desc common_usages[] = { - "in the userAccountControl attribute", }, - { opt_add_service_principal, "add the given service principal to the account\n" }, - { opt_remove_service_principal, "remove the given service principal from the account\n" }, -+ { opt_description, "add a description to the account\n" }, - { opt_no_password, "don't prompt for or read a password" }, - { opt_prompt_password, "prompt for a password if necessary" }, - { opt_stdin_password, "read a password from stdin (until EOF) if\n" -@@ -306,6 +308,9 @@ parse_option (Option opt, - case opt_remove_service_principal: - adcli_enroll_add_service_principal_to_remove (enroll, optarg); - return ADCLI_SUCCESS; -+ case opt_description: -+ adcli_enroll_set_description (enroll, optarg); -+ return ADCLI_SUCCESS; - case opt_verbose: - return ADCLI_SUCCESS; - -@@ -369,6 +374,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "os-name", required_argument, NULL, opt_os_name }, - { "os-version", required_argument, NULL, opt_os_version }, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, -+ { "description", optional_argument, NULL, opt_description }, - { "user-principal", optional_argument, NULL, opt_user_principal }, - { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation }, - { "add-service-principal", required_argument, NULL, opt_add_service_principal }, -@@ -487,6 +493,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "os-name", required_argument, NULL, opt_os_name }, - { "os-version", required_argument, NULL, opt_os_version }, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, -+ { "description", optional_argument, NULL, opt_description }, - { "user-principal", optional_argument, NULL, opt_user_principal }, - { "computer-password-lifetime", optional_argument, NULL, opt_computer_password_lifetime }, - { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation }, --- -2.25.1 - diff --git a/0003-doc-explain-required-AD-permissions.patch b/0003-doc-explain-required-AD-permissions.patch deleted file mode 100644 index d6d9024..0000000 --- a/0003-doc-explain-required-AD-permissions.patch +++ /dev/null @@ -1,242 +0,0 @@ -From fa5c5fb4f8e7bcadf3e5a3798bd060720fd35eaa Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 20 Oct 2020 13:34:41 +0200 -Subject: [PATCH 03/10] doc: explain required AD permissions - -When using a restricted account with adcli some operations might fail -because the account might not have all required permissions. The man -page is extended and now explains which permissions are needed under -given circumstances. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1852080 -Resolves: https://gitlab.freedesktop.org/realmd/adcli/-/issues/20 ---- - doc/Makefile.am | 10 ++++ - doc/adcli.xml | 132 +++++++++++++++++++++++++++++++++++++++++++++ - library/adenroll.c | 30 ++++++----- - 3 files changed, 160 insertions(+), 12 deletions(-) - -diff --git a/doc/Makefile.am b/doc/Makefile.am -index 4490688..50fb777 100644 ---- a/doc/Makefile.am -+++ b/doc/Makefile.am -@@ -33,14 +33,17 @@ EXTRA_DIST = \ - version.xml \ - samba_data_tool_path.xml.in \ - samba_data_tool_path.xml \ -+ permissions.xml \ - $(NULL) - - CLEANFILES = \ - $(man8_MANS) \ -+ permissions.xml \ - $(NULL) - - XSLTPROC_FLAGS = \ - --nonet \ -+ --xinclude \ - --stringparam man.output.quietly 1 \ - --stringparam funcsynopsis.style ansi \ - --stringparam man.th.extra1.suppress 1 \ -@@ -50,6 +53,13 @@ XSLTPROC_FLAGS = \ - XSLTPROC_MAN = \ - $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl - -+permissions.xml: ../library/adenroll.c adcli.xml -+ echo "" > $@ -+ grep '".*".*/\* :ADPermissions: ' $< | sed -e 's#.*"\(.*\)".*/\* :ADPermissions: \(.*\)\*/$$#\1\2#' | sed -e 's#\*##g' >> $@ -+ echo "" >> $@ -+ -+$(man8_MANS): permissions.xml -+ - .xml.8: - $(AM_V_GEN) $(XSLTPROC_MAN) $< - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 1437679..cc44fd8 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -885,6 +885,138 @@ Password for Administrator: - - - -+ -+ Delegated Permissions -+ It is common practice in AD to not use an account from the Domain -+ Administrators group to join a machine to a domain but use a dedicated -+ account which only has permissions to join a machine to one or more OUs -+ in the Active Directory tree. Giving the needed permissions to a single -+ account or a group in Active Directory is called Delegation. A typical -+ example on how to configured Delegation can be found in the Delegation -+ section of the blog post -+ Who can add workstation to the domain. -+ -+ -+ When using an account with delegated permissions with adcli -+ basically the same applies as well. However some aspects are explained -+ here in a bit more details to better illustrate different concepts of -+ Active Directory and to make it more easy to debug permissions issues -+ during the join. Please note that the following is not specific to -+ adcli but applies to all applications which would like to modify -+ certain properties or objects in Active Directory with an account with -+ limited permissions. -+ -+ First, as said in the blog post it is sufficient to have -+ "Create computer object" permissions to join a -+ computer to a domain. But this would only work as expected if the -+ computer object does not exist in Active Directory before the join. -+ Because only when a new object is created Active Directory does not -+ apply additional permission checks on the attributes of the new -+ computer object. This means the delegated user can add any kind of -+ attribute with any value to a new computer object also long as they -+ meet general constraints like e.g. that the attribute must be defined -+ in the schema and is allowed in a objectclass of the object, the value -+ must match the syntax defined in the schema or that the -+ must be unique in the domain. -+ -+ If you want to use the account with delegated permission to -+ remove computer objects in Active Directory (adcli delete-computer) you -+ should of course make sure that the account has -+ "Delete computer object" permissions. -+ -+ If the computer object already exists the -+ "Create computer object" permission does not apply -+ anymore since now an existing object must be modified. Now permissions -+ on the individual attributes are needed. e.g. -+ "Read and write Account Restrictions" or -+ "Reset Password". For some attributes Active -+ Directory has two types of permissions the plain -+ "Read and Write" permissions and the -+ "Validated Write" permissions. For the latter case -+ there are two specific permissions relevant for adcli, namely -+ -+ Validated write to DNS host name -+ Validated write to service principal name -+ -+ Details about the validation of the values can be found in the -+ "Validated Writes" section of -+ [MS-ADTS], especially -+ dNSHostName -+ and -+ servicePrincipalName. -+ To cut it short for "Validated write to DNS host name" -+ the domain part of the fully-qualified hostname must either match the -+ domain name of the domain you want to join to or must be listed in the -+ attribute. And for -+ "Validated write to service principal name" the -+ hostname part of the service principal name must match the name stored -+ in or some other attributes which are -+ not handled by adcli. This also means that -+ cannot be empty or only contain a short -+ name if the service principal name should contain a fully-qualified -+ name. -+ -+ To summarize, if you only have validated write permissions you -+ should make sure the domain part of the hostname matches the domain you -+ want to join or use the with a matching -+ name. -+ -+ The plain read write permissions do not run additional -+ validations but the attribute values must still be in agreement with -+ the general constraints mentioned above. If the computer object already -+ exists adcli might need the following permissions which are also needed -+ by Windows clients to modify existing attributes: -+ -+ Reset Password -+ Read and write Account Restrictions -+ Read and (validated) write to DNS host name -+ Read and (validated) write to service principal name -+ -+ additionally adcli needs -+ -+ Read and write msDS-supportedEncryptionTypes -+ -+ This is added for security reasons to avoid that Active Directory -+ stores Kerberos keys with (potentially weaker) encryption types than -+ the client supports since Active Directory is often configured to still -+ support older (weaker) encryption types for compatibility reasons. -+ -+ -+ All other attributes are only set or modified on demand, i.e. -+ adcli must be called with an option the would set or modify the given -+ attribute. In the following the attributes adcli can modify together -+ with the required permissions are listed: -+ -+ -+ -+ For the management of users and groups (adcli create-user, -+ adcli delete-user, adcli create-group, adcli delete-group) the same -+ applies only for different types of objects, i.e. users and groups. -+ Since currently adcli only supports the creation and the removal of -+ user and group objects it is sufficient to have the -+ "Create/Delete User objects" and -+ "Create/Delete Group objects" permissions. -+ -+ If you want to manage group members as well (adcli add-member, -+ adcli remove-member) "Read/Write Members" permissions -+ are needed as well. -+ -+ Depending on the version of Active Directory the -+ "Delegation of Control Wizard" might offer some -+ shortcuts for common task like e.g. -+ -+ Create, delete and manage user accounts -+ Create, delete and manage groups -+ Modify the membership of a group -+ -+ The first 2 shortcuts will provided full access to user and group -+ objects which, as explained above, is more than currently is needed. -+ After using those shortcut it is a good idea to verify in the -+ "Security" tab in the "Properties" -+ of the related Active Directory container that the assigned permissions -+ meet the expectations. -+ -+ - - Bugs - -diff --git a/library/adenroll.c b/library/adenroll.c -index e745295..98e9786 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -71,19 +71,25 @@ static krb5_enctype v51_earlier_enctypes[] = { - 0 - }; - -+/* The following list containst all attributes handled by adcli, some are -+ * read-only and the others can be written as well. To properly document the -+ * required permissions each attribute which adcli tries to modify should have -+ * a comment starting with ':ADPermissions:' and the related permissions in AD -+ * on the same line. Multiple permissions can be seperated with a '*'. For all -+ * other attribute a suitable comment is very welcome. */ - static char *default_ad_ldap_attrs[] = { -- "sAMAccountName", -- "userPrincipalName", -- "msDS-KeyVersionNumber", -- "msDS-supportedEncryptionTypes", -- "dNSHostName", -- "servicePrincipalName", -- "operatingSystem", -- "operatingSystemVersion", -- "operatingSystemServicePack", -- "pwdLastSet", -- "userAccountControl", -- "description", -+ "sAMAccountName", /* Only set during creation */ -+ "userPrincipalName", /* :ADPermissions: Read/Write userPrincipal Name */ -+ "msDS-KeyVersionNumber", /* Manages by AD */ -+ "msDS-supportedEncryptionTypes", /* :ADPermissions: Read/Write msDS-SupportedEncryptionTypes */ -+ "dNSHostName", /* :ADPermissions: Read/Write dNSHostName * Read and write DNS host name attributes * Validated write to DNS host name */ -+ "servicePrincipalName", /* :ADPermissions: Read/Write servicePrincipalName * Validated write to service principal name */ -+ "operatingSystem", /* :ADPermissions: Read/Write Operating System */ -+ "operatingSystemVersion", /* :ADPermissions: Read/Write Operating System Version */ -+ "operatingSystemServicePack", /* :ADPermissions: Read/Write operatingSystemServicePack */ -+ "pwdLastSet", /* Managed by AD */ -+ "userAccountControl", /* :ADPermissions: Read/Write userAccountControl */ -+ "description", /* :ADPermissions: Read/Write Description */ - NULL, - }; - --- -2.28.0 - diff --git a/0003-man-make-handling-of-optional-credential-cache-more-.patch b/0003-man-make-handling-of-optional-credential-cache-more-.patch deleted file mode 100644 index 328cc5a..0000000 --- a/0003-man-make-handling-of-optional-credential-cache-more-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 88fbb7e2395dec20b37697a213a097909870c21f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 13 Aug 2020 17:10:01 +0200 -Subject: [PATCH 3/3] man: make handling of optional credential cache more - clear - -The optional Kerberos credential cache can only be used with the long -option name --login-ccache and not with the short version -C. To make -this more clear each option get its own entry. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791545 ---- - doc/adcli.xml | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index ecf8726..1437679 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -153,10 +153,16 @@ $ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.exa - - - -- -- Use the specified kerberos credential -+ -+ Use the default Kerberos credential -+ cache to authenticate with the domain. -+ -+ -+ -+ -+ Use the specified Kerberos credential - cache to authenticate with the domain. If no credential -- cache is specified, the default kerberos credential -+ cache is specified, the default Kerberos credential - cache will be used. Credential caches of type FILE can - be given with the path to the file. For other - credential cache types, e.g. DIR, KEYRING or KCM, the --- -2.26.2 - diff --git a/0004-Use-GSS-SPNEGO-if-available.patch b/0004-Use-GSS-SPNEGO-if-available.patch deleted file mode 100644 index dba4893..0000000 --- a/0004-Use-GSS-SPNEGO-if-available.patch +++ /dev/null @@ -1,124 +0,0 @@ -From a6f795ba3d6048b32d7863468688bf7f42b2cafd Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 11 Oct 2019 16:39:25 +0200 -Subject: [PATCH 4/6] Use GSS-SPNEGO if available - -Currently adcli uses the GSSAPI SASL mechanism for LDAP authentication -and to establish encryption. While this works in general it does not -handle some of the more advanced features which can be required by AD -DCs. - -The GSS-SPNEGO mechanism can handle them and is used with this patch by -adcli if the AD DC indicates that it supports it. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420 ---- - library/adconn.c | 35 ++++++++++++++++++++++++++++++++++- - library/adconn.h | 3 +++ - 2 files changed, 37 insertions(+), 1 deletion(-) - -diff --git a/library/adconn.c b/library/adconn.c -index bcaced8..ffb54f9 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -77,6 +77,7 @@ struct _adcli_conn_ctx { - char *default_naming_context; - char *configuration_naming_context; - char **supported_capabilities; -+ char **supported_sasl_mechs; - - /* Connect state */ - LDAP *ldap; -@@ -845,6 +846,7 @@ connect_and_lookup_naming (adcli_conn *conn, - "defaultNamingContext", - "configurationNamingContext", - "supportedCapabilities", -+ "supportedSASLMechanisms", - NULL - }; - -@@ -897,6 +899,11 @@ connect_and_lookup_naming (adcli_conn *conn, - "supportedCapabilities"); - } - -+ if (conn->supported_sasl_mechs == NULL) { -+ conn->supported_sasl_mechs = _adcli_ldap_parse_values (ldap, results, -+ "supportedSASLMechanisms"); -+ } -+ - ldap_msgfree (results); - - if (conn->default_naming_context == NULL) { -@@ -1022,6 +1029,7 @@ authenticate_to_directory (adcli_conn *conn) - OM_uint32 minor; - ber_len_t ssf; - int ret; -+ const char *mech = "GSSAPI"; - - if (conn->ldap_authenticated) - return ADCLI_SUCCESS; -@@ -1038,7 +1046,11 @@ authenticate_to_directory (adcli_conn *conn) - ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); - return_unexpected_if_fail (ret == 0); - -- ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, "GSSAPI", NULL, NULL, -+ if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) { -+ mech = "GSS-SPNEGO"; -+ } -+ -+ ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL, - LDAP_SASL_QUIET, sasl_interact, NULL); - - /* Clear the credential cache GSSAPI to use (for this thread) */ -@@ -1231,6 +1243,7 @@ conn_free (adcli_conn *conn) - free (conn->default_naming_context); - free (conn->configuration_naming_context); - _adcli_strv_free (conn->supported_capabilities); -+ _adcli_strv_free (conn->supported_sasl_mechs); - - free (conn->computer_name); - free (conn->host_fqdn); -@@ -1606,6 +1619,26 @@ adcli_conn_server_has_capability (adcli_conn *conn, - return 0; - } - -+bool -+adcli_conn_server_has_sasl_mech (adcli_conn *conn, -+ const char *mech) -+{ -+ int i; -+ -+ return_val_if_fail (conn != NULL, false); -+ return_val_if_fail (mech != NULL, false); -+ -+ if (!conn->supported_sasl_mechs) -+ return false; -+ -+ for (i = 0; conn->supported_sasl_mechs[i] != NULL; i++) { -+ if (strcasecmp (mech, conn->supported_sasl_mechs[i]) == 0) -+ return true; -+ } -+ -+ return false; -+} -+ - bool adcli_conn_is_writeable (adcli_conn *conn) - { - disco_dance_if_necessary (conn); -diff --git a/library/adconn.h b/library/adconn.h -index 1ad5715..37ebdd9 100644 ---- a/library/adconn.h -+++ b/library/adconn.h -@@ -149,6 +149,9 @@ void adcli_conn_set_krb5_conf_dir (adcli_conn *conn, - int adcli_conn_server_has_capability (adcli_conn *conn, - const char *capability); - -+bool adcli_conn_server_has_sasl_mech (adcli_conn *conn, -+ const char *mech); -+ - bool adcli_conn_is_writeable (adcli_conn *conn); - - #endif /* ADCONN_H_ */ --- -2.25.1 - diff --git a/0004-enroll-add-is_service-member.patch b/0004-enroll-add-is_service-member.patch deleted file mode 100644 index d4057d9..0000000 --- a/0004-enroll-add-is_service-member.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 4e4dbf8d2b437808863f8be85e7f30865d88c7fc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 23 Oct 2020 16:46:43 +0200 -Subject: [PATCH 04/10] enroll: add is_service member - -Add helpers to indicate a managed service account. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 17 +++++++++++++++++ - library/adenroll.h | 4 ++++ - 2 files changed, 21 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 98e9786..5ae1f7b 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -103,6 +103,8 @@ static char *default_ad_ldap_attrs[] = { - struct _adcli_enroll { - int refs; - adcli_conn *conn; -+ bool is_service; -+ bool is_service_explicit; - - char *host_fqdn; - int host_fqdn_explicit; -@@ -2942,6 +2944,21 @@ adcli_enroll_get_desciption (adcli_enroll *enroll) - return enroll->description; - } - -+void -+adcli_enroll_set_is_service (adcli_enroll *enroll, bool value) -+{ -+ return_if_fail (enroll != NULL); -+ -+ enroll->is_service = value; -+ enroll->is_service_explicit = true; -+} -+ -+bool -+adcli_enroll_get_is_service (adcli_enroll *enroll) -+{ -+ return enroll->is_service; -+} -+ - const char ** - adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll) - { -diff --git a/library/adenroll.h b/library/adenroll.h -index 0606169..7765ed4 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -130,6 +130,10 @@ const char * adcli_enroll_get_desciption (adcli_enroll *enroll); - void adcli_enroll_set_description (adcli_enroll *enroll, - const char *value); - -+bool adcli_enroll_get_is_service (adcli_enroll *enroll); -+void adcli_enroll_set_is_service (adcli_enroll *enroll, -+ bool value); -+ - krb5_kvno adcli_enroll_get_kvno (adcli_enroll *enroll); - - void adcli_enroll_set_kvno (adcli_enroll *enroll, --- -2.28.0 - diff --git a/0005-add-option-use-ldaps.patch b/0005-add-option-use-ldaps.patch deleted file mode 100644 index 675f204..0000000 --- a/0005-add-option-use-ldaps.patch +++ /dev/null @@ -1,378 +0,0 @@ -From 85097245b57f190337225dbdbf6e33b58616c092 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 19 Dec 2019 07:22:33 +0100 -Subject: [PATCH 5/6] add option use-ldaps - -In general using the LDAP port with GSS-SPNEGO should satifiy all -requirements an AD DC should have for authentication on an encrypted -LDAP connection. - -But if e.g. the LDAP port is blocked by a firewall using the LDAPS port -with TLS encryption might be an alternative. For this use case the ---use-ldaps option is added. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420 ---- - doc/adcli.xml | 24 +++++++++++++++ - library/adconn.c | 79 ++++++++++++++++++++++++++++++++++++++++++------ - library/adconn.h | 4 +++ - tools/computer.c | 10 ++++++ - tools/entry.c | 11 +++++++ - 5 files changed, 119 insertions(+), 9 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index dd30435..acced25 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -128,6 +128,30 @@ - If not specified, then an appropriate domain controller - is automatically discovered. - -+ -+ -+ Connect to the domain controller -+ with LDAPS. By default the LDAP port is used and SASL -+ GSS-SPNEGO or GSSAPI is used for authentication and to -+ establish encryption. This should satisfy all -+ requirements set on the server side and LDAPS should -+ only be used if the LDAP port is not accessible due to -+ firewalls or other reasons. -+ Please note that the place where CA certificates -+ can be found to validate the AD DC certificates -+ must be configured in the OpenLDAP configuration -+ file, e.g. /etc/openldap/ldap.conf. -+ As an alternative it can be specified with the help of -+ an environment variable, e.g. -+ -+$ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.example.com -+... -+ -+ Please see -+ ldap.conf -+ 5 for details. -+ -+ - - - Use the specified kerberos credential -diff --git a/library/adconn.c b/library/adconn.c -index ffb54f9..7bab852 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -70,6 +70,7 @@ struct _adcli_conn_ctx { - char *domain_name; - char *domain_realm; - char *domain_controller; -+ bool use_ldaps; - char *canonical_host; - char *domain_short; - char *domain_sid; -@@ -773,7 +774,8 @@ int ldap_init_fd (ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap - - static LDAP * - connect_to_address (const char *host, -- const char *canonical_host) -+ const char *canonical_host, -+ bool use_ldaps) - { - struct addrinfo *res = NULL; - struct addrinfo *ai; -@@ -783,6 +785,16 @@ connect_to_address (const char *host, - char *url; - int sock; - int rc; -+ int opt_rc; -+ const char *port = "389"; -+ const char *proto = "ldap"; -+ const char *errmsg = NULL; -+ -+ if (use_ldaps) { -+ port = "636"; -+ proto = "ldaps"; -+ _adcli_info ("Using LDAPS to connect to %s", host); -+ } - - memset (&hints, '\0', sizeof(hints)); - #ifdef AI_ADDRCONFIG -@@ -794,7 +806,7 @@ connect_to_address (const char *host, - if (!canonical_host) - canonical_host = host; - -- rc = getaddrinfo (host, "389", &hints, &res); -+ rc = getaddrinfo (host, port, &hints, &res); - if (rc != 0) { - _adcli_err ("Couldn't resolve host name: %s: %s", host, gai_strerror (rc)); - return NULL; -@@ -810,7 +822,7 @@ connect_to_address (const char *host, - close (sock); - } else { - error = 0; -- if (asprintf (&url, "ldap://%s", canonical_host) < 0) -+ if (asprintf (&url, "%s://%s", proto, canonical_host) < 0) - return_val_if_reached (NULL); - rc = ldap_init_fd (sock, 1, url, &ldap); - free (url); -@@ -820,6 +832,25 @@ connect_to_address (const char *host, - ldap_err2string (rc)); - break; - } -+ -+ if (use_ldaps) { -+ rc = ldap_install_tls (ldap); -+ if (rc != LDAP_SUCCESS) { -+ opt_rc = ldap_get_option (ldap, -+ LDAP_OPT_DIAGNOSTIC_MESSAGE, -+ (void *) &errmsg); -+ if (opt_rc != LDAP_SUCCESS) { -+ errmsg = NULL; -+ } -+ _adcli_err ("Couldn't initialize TLS [%s]: %s", -+ ldap_err2string (rc), -+ errmsg == NULL ? "- no details -" -+ : errmsg); -+ ldap_unbind_ext_s (ldap, NULL, NULL); -+ ldap = NULL; -+ break; -+ } -+ } - } - } - -@@ -856,7 +887,8 @@ connect_and_lookup_naming (adcli_conn *conn, - if (!canonical_host) - canonical_host = disco->host_addr; - -- ldap = connect_to_address (disco->host_addr, canonical_host); -+ ldap = connect_to_address (disco->host_addr, canonical_host, -+ adcli_conn_get_use_ldaps (conn)); - if (ldap == NULL) - return ADCLI_ERR_DIRECTORY; - -@@ -1041,14 +1073,28 @@ authenticate_to_directory (adcli_conn *conn) - status = gss_krb5_ccache_name (&minor, conn->login_ccache_name, NULL); - return_unexpected_if_fail (status == 0); - -- /* Clumsily tell ldap + cyrus-sasl that we want encryption */ -- ssf = 1; -- ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); -- return_unexpected_if_fail (ret == 0); -+ if (adcli_conn_get_use_ldaps (conn)) { -+ /* do not use SASL encryption on LDAPS connection */ -+ ssf = 0; -+ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); -+ return_unexpected_if_fail (ret == 0); -+ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MAX, &ssf); -+ return_unexpected_if_fail (ret == 0); -+ } else { -+ /* Clumsily tell ldap + cyrus-sasl that we want encryption */ -+ ssf = 1; -+ ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); -+ return_unexpected_if_fail (ret == 0); -+ } - -- if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) { -+ /* There are issues with cryrus-sasl and GSS-SPNEGO with TLS even if -+ * ssf_max is set to 0. To be on the safe side GSS-SPNEGO is only used -+ * without LDAPS. */ -+ if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO") -+ && !adcli_conn_get_use_ldaps (conn)) { - mech = "GSS-SPNEGO"; - } -+ _adcli_info ("Using %s for SASL bind", mech); - - ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL, - LDAP_SASL_QUIET, sasl_interact, NULL); -@@ -1230,6 +1276,7 @@ adcli_conn_new (const char *domain_name) - conn->refs = 1; - conn->logins_allowed = ADCLI_LOGIN_COMPUTER_ACCOUNT | ADCLI_LOGIN_USER_ACCOUNT; - adcli_conn_set_domain_name (conn, domain_name); -+ adcli_conn_set_use_ldaps (conn, false); - return conn; - } - -@@ -1389,6 +1436,20 @@ adcli_conn_set_domain_controller (adcli_conn *conn, - no_more_disco (conn); - } - -+bool -+adcli_conn_get_use_ldaps (adcli_conn *conn) -+{ -+ return_val_if_fail (conn != NULL, NULL); -+ return conn->use_ldaps; -+} -+ -+void -+adcli_conn_set_use_ldaps (adcli_conn *conn, bool value) -+{ -+ return_if_fail (conn != NULL); -+ conn->use_ldaps = value; -+} -+ - const char * - adcli_conn_get_domain_short (adcli_conn *conn) - { -diff --git a/library/adconn.h b/library/adconn.h -index 37ebdd9..1d5faa8 100644 ---- a/library/adconn.h -+++ b/library/adconn.h -@@ -89,6 +89,10 @@ const char * adcli_conn_get_domain_controller (adcli_conn *conn); - void adcli_conn_set_domain_controller (adcli_conn *conn, - const char *value); - -+bool adcli_conn_get_use_ldaps (adcli_conn *conn); -+void adcli_conn_set_use_ldaps (adcli_conn *conn, -+ bool value); -+ - const char * adcli_conn_get_domain_short (adcli_conn *conn); - - const char * adcli_conn_get_domain_sid (adcli_conn *conn); -diff --git a/tools/computer.c b/tools/computer.c -index 840e334..292c4d8 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -113,12 +113,14 @@ typedef enum { - opt_add_service_principal, - opt_remove_service_principal, - opt_description, -+ opt_use_ldaps, - } Option; - - static adcli_tool_desc common_usages[] = { - { opt_domain, "active directory domain name" }, - { opt_domain_realm, "kerberos realm for the domain" }, - { opt_domain_controller, "domain controller to connect to" }, -+ { opt_use_ldaps, "use LDAPS port for communication" }, - { opt_host_fqdn, "override the fully qualified domain name of the\n" - "local machine" }, - { opt_host_keytab, "filename for the host kerberos keytab" }, -@@ -311,6 +313,9 @@ parse_option (Option opt, - case opt_description: - adcli_enroll_set_description (enroll, optarg); - return ADCLI_SUCCESS; -+ case opt_use_ldaps: -+ adcli_conn_set_use_ldaps (conn, true); -+ return ADCLI_SUCCESS; - case opt_verbose: - return ADCLI_SUCCESS; - -@@ -357,6 +362,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, - { "domain-server", required_argument, NULL, opt_domain_controller }, /* compat */ -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "user", required_argument, NULL, opt_login_user }, /* compat */ - { "login-ccache", optional_argument, NULL, opt_login_ccache }, -@@ -688,6 +694,7 @@ adcli_tool_computer_preset (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "domain-ou", required_argument, NULL, opt_domain_ou }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, -@@ -800,6 +807,7 @@ adcli_tool_computer_reset (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "login-type", required_argument, NULL, opt_login_type }, -@@ -888,6 +896,7 @@ adcli_tool_computer_delete (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, -@@ -985,6 +994,7 @@ adcli_tool_computer_show (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "login-type", required_argument, NULL, opt_login_type }, -diff --git a/tools/entry.c b/tools/entry.c -index f361845..05e4313 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -53,6 +53,7 @@ typedef enum { - opt_unix_gid, - opt_unix_shell, - opt_nis_domain, -+ opt_use_ldaps, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -67,6 +68,7 @@ static adcli_tool_desc common_usages[] = { - { opt_domain, "active directory domain name" }, - { opt_domain_realm, "kerberos realm for the domain" }, - { opt_domain_controller, "domain directory server to connect to" }, -+ { opt_use_ldaps, "use LDAPS port for communication" }, - { opt_login_ccache, "kerberos credential cache file which contains\n" - "ticket to used to connect to the domain" }, - { opt_login_user, "user (usually administrative) login name of\n" -@@ -136,6 +138,9 @@ parse_option (Option opt, - stdin_password = 1; - } - return ADCLI_SUCCESS; -+ case opt_use_ldaps: -+ adcli_conn_set_use_ldaps (conn, true); -+ return ADCLI_SUCCESS; - case opt_verbose: - return ADCLI_SUCCESS; - default: -@@ -172,6 +177,7 @@ adcli_tool_user_create (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, -@@ -306,6 +312,7 @@ adcli_tool_user_delete (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, -@@ -394,6 +401,7 @@ adcli_tool_group_create (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "domain-ou", required_argument, NULL, opt_domain_ou }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, -@@ -496,6 +504,7 @@ adcli_tool_group_delete (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, -@@ -622,6 +631,7 @@ adcli_tool_member_add (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, -@@ -722,6 +732,7 @@ adcli_tool_member_remove (adcli_conn *conn, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, - { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, - { "login-user", required_argument, NULL, opt_login_user }, - { "login-ccache", optional_argument, NULL, opt_login_ccache }, - { "no-password", no_argument, 0, opt_no_password }, --- -2.25.1 - diff --git a/0005-computer-add-create-msa-sub-command.patch b/0005-computer-add-create-msa-sub-command.patch deleted file mode 100644 index 552a3ca..0000000 --- a/0005-computer-add-create-msa-sub-command.patch +++ /dev/null @@ -1,646 +0,0 @@ -From 41379f7ad6a9442dd55cc43d832427911e86db31 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 23 Oct 2020 16:53:43 +0200 -Subject: [PATCH 05/10] computer: add create-msa sub-command - -Add new sub-command to create a managed service account in AD. This can -be used if LDAP access to AD is needed but the host is already joined to -a different domain. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - doc/adcli.xml | 140 ++++++++++++++++++++++++++++++++++++++ - library/adenroll.c | 164 ++++++++++++++++++++++++++++++++++++++------- - tools/computer.c | 125 ++++++++++++++++++++++++++++++++++ - tools/tools.c | 1 + - tools/tools.h | 4 ++ - 5 files changed, 409 insertions(+), 25 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index cc44fd8..14921f9 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -98,6 +98,10 @@ - --domain=domain.example.com - computer - -+ -+ adcli create-msa -+ --domain=domain.example.com -+ - - - -@@ -885,6 +889,142 @@ Password for Administrator: - - - -+ -+ Create a managed service account -+ -+ adcli create-msa creates a managed service -+ account (MSA) in the given Active Directory domain. This is useful if a -+ computer should not fully join the Active Directory domain but LDAP -+ access is needed. A typical use case is that the computer is already -+ joined an Active Directory domain and needs access to another Active -+ Directory domain in the same or a trusted forest where the host -+ credentials from the joined Active Directory domain are -+ not valid, e.g. there is only a one-way trust. -+ -+ -+$ adcli create-msa --domain=domain.example.com -+Password for Administrator: -+ -+ -+ The managed service account, as maintained by adcli, cannot have -+ additional service principals names (SPNs) associated with it. An SPN -+ is defined within the context of a Kerberos service which is tied to a -+ machine account in Active Directory. Since a machine can be joined to a -+ single Active Directory domain, managed service account in a different -+ Active Directory domain will not have the SPNs that otherwise are part -+ of another Active Directory domain's machine. -+ -+ Since it is expected that a client will most probably join to the -+ Active Directory domain matching its DNS domain the managed service -+ account will be needed for a different Active directory domain and as a -+ result the Active Directory domain name is a mandatory option. If -+ called with no other options adcli create-msa -+ will use the short hostname with an additional random suffix as -+ computer name to avoid name collisions. -+ -+ LDAP attribute sAMAccountName has a limit of 20 characters. -+ However, machine account's NetBIOS name must be at most 16 characters -+ long, including a trailing '$' sign. Since it is not expected that the -+ managed service accounts created by adcli will be used on the NetBIOS -+ level the remaining 4 characters can be used to add uniqueness. Managed -+ service account names will have a suffix of 3 random characters from -+ number and upper- and lowercase ASCII ranges appended to the chosen -+ short host name, using '!' as a separator. For a host with the -+ shortname 'myhost', a managed service account will have a common name -+ (CN attribute) 'myhost!A2c' and a NetBIOS name -+ (sAMAccountName attribute) will be 'myhost!A2c$'. A corresponding -+ Kerberos principal in the Active Directory domain where the managed -+ service account was created would be -+ 'myhost!A2c$@DOMAIN.EXAMPLE.COM'. -+ -+ A keytab for the managed service account is stored into a file -+ specified with -K option. If it is not specified, the file is named -+ after the default keytab file, with lowercase Active Directory domain -+ of the managed service account as a suffix. On most systems it would be -+ /etc/krb5.keytab with a suffix of -+ 'domain.example.com', e.g. -+ /etc/krb5.keytad.domain.example.com. -+ -+ adcli create-msa can be called multiple -+ times to reset the password of the managed service account. To identify -+ the right account with the random component in the name the -+ corresponding principal is read from the keytab. If the keytab got -+ deleted adcli will try to identify an existing -+ managed service account with the help of the fully-qualified name, if -+ this fails a new managed service account will be created. -+ -+ The managed service account password can be updated with -+ -+$ adcli update --domain=domain.example.com --host-keytab=/etc/krb5.keytad.domain.example.com -+ -+ and the managed service account can be deleted with -+ -+$ adcli delete-computer --domain=domain.example.com 'myhost!A2c' -+ -+ -+ -+ In addition to the global options, you can specify the following -+ options to control how this operation is done. -+ -+ -+ -+ -+ The short non-dotted name of the managed -+ service account that will be created in the Active -+ Directory domain. The long option name -+ is -+ kept to underline the similarity with the same option -+ of the other sub-commands. If not specified, -+ then the first portion of the -+ or its default is used with a random suffix. -+ -+ -+ -+ The full distinguished name of the OU in -+ which to create the managed service account. If not -+ specified, then the managed service account will be -+ created in a default location. -+ -+ -+ -+ Override the local machine's fully -+ qualified DNS domain name. If not specified, the local -+ machine's hostname will be retrieved via -+ gethostname(). -+ If gethostname() only returns a short name -+ getaddrinfo() with the AI_CANONNAME hint -+ is called to expand the name to a fully qualified DNS -+ domain name. -+ -+ -+ -+ Specify the path to the host keytab where -+ credentials of the managed service account will be -+ written after a successful creation. If not specified, -+ the default location will be used, usually -+ /etc/krb5.keytab with -+ the lower-cased Active Directory domain name added as a -+ suffix e.g. -+ /etc/krb5.keytab.domain.example.com. -+ -+ -+ -+ -+ After a successful creation print out -+ information about the created object. This is output in -+ a format that should be both human and machine -+ readable. -+ -+ -+ -+ After a successful creation print out -+ the managed service account password. This is output in -+ a format that should be both human and machine -+ readable. -+ -+ -+ -+ - - Delegated Permissions - It is common practice in AD to not use an account from the Domain -diff --git a/library/adenroll.c b/library/adenroll.c -index 5ae1f7b..dbfda36 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -155,6 +155,20 @@ struct _adcli_enroll { - char *description; - }; - -+static void -+check_if_service (adcli_enroll *enroll, -+ LDAP *ldap, -+ LDAPMessage *results) -+{ -+ char **objectclasses = NULL; -+ -+ objectclasses = _adcli_ldap_parse_values (ldap, results, "objectClass"); -+ enroll->is_service = _adcli_strv_has_ex (objectclasses, -+ "msDS-ManagedServiceAccount", -+ strcasecmp) == 1 ? true : false; -+ _adcli_strv_free (objectclasses); -+} -+ - static adcli_result - ensure_host_fqdn (adcli_result res, - adcli_enroll *enroll) -@@ -471,13 +485,15 @@ ensure_keytab_principals (adcli_result res, - { - krb5_context k5; - krb5_error_code code; -- int count; -+ int count = 0; - int at, i; - - /* Prepare the principals we're going to add to the keytab */ - -- return_unexpected_if_fail (enroll->service_principals); -- count = _adcli_strv_len (enroll->service_principals); -+ if (!enroll->is_service) { -+ return_unexpected_if_fail (enroll->service_principals); -+ count = _adcli_strv_len (enroll->service_principals); -+ } - - k5 = adcli_conn_get_krb5_context (enroll->conn); - return_unexpected_if_fail (k5 != NULL); -@@ -556,8 +572,12 @@ static adcli_result - lookup_computer_container (adcli_enroll *enroll, - LDAP *ldap) - { -- char *attrs[] = { "wellKnownObjects", NULL }; -- char *prefix = "B:32:AA312825768811D1ADED00C04FD8D5CD:"; -+ char *attrs[] = { enroll->is_service ? "otherWellKnownObjects" -+ : "wellKnownObjects", NULL }; -+ const char *prefix = enroll->is_service ? "B:32:1EB93889E40C45DF9F0C64D23BBB6237:" -+ : "B:32:AA312825768811D1ADED00C04FD8D5CD:"; -+ const char *filter = enroll->is_service ? "(&(objectClass=container)(cn=Managed Service Accounts))" -+ : "(&(objectClass=container)(cn=Computers))"; - int prefix_len; - LDAPMessage *results; - const char *base; -@@ -586,7 +606,7 @@ lookup_computer_container (adcli_enroll *enroll, - "Couldn't lookup computer container: %s", base); - } - -- values = _adcli_ldap_parse_values (ldap, results, "wellKnownObjects"); -+ values = _adcli_ldap_parse_values (ldap, results, attrs[0]); - ldap_msgfree (results); - - prefix_len = strlen (prefix); -@@ -604,8 +624,7 @@ lookup_computer_container (adcli_enroll *enroll, - - /* Try harder */ - if (!enroll->computer_container) { -- ret = ldap_search_ext_s (ldap, base, LDAP_SCOPE_BASE, -- "(&(objectClass=container)(cn=Computers))", -+ ret = ldap_search_ext_s (ldap, base, LDAP_SCOPE_BASE, filter, - attrs, 0, NULL, NULL, NULL, -1, &results); - if (ret == LDAP_SUCCESS) { - enroll->computer_container = _adcli_ldap_parse_dn (ldap, results); -@@ -747,7 +766,7 @@ static adcli_result - create_computer_account (adcli_enroll *enroll, - LDAP *ldap) - { -- char *vals_objectClass[] = { "computer", NULL }; -+ char *vals_objectClass[] = { enroll->is_service ? "msDS-ManagedServiceAccount" : "computer", NULL }; - LDAPMod objectClass = { LDAP_MOD_ADD, "objectClass", { vals_objectClass, } }; - char *vals_sAMAccountName[] = { enroll->computer_sam, NULL }; - LDAPMod sAMAccountName = { LDAP_MOD_ADD, "sAMAccountName", { vals_sAMAccountName, } }; -@@ -806,7 +825,7 @@ create_computer_account (adcli_enroll *enroll, - m = 0; - for (c = 0; c < mods_count - 1; c++) { - /* Skip empty LDAP sttributes */ -- if (all_mods[c]->mod_vals.modv_strvals[0] != NULL) { -+ if (all_mods[c]->mod_vals.modv_strvals != NULL && all_mods[c]->mod_vals.modv_strvals[0] != NULL) { - mods[m++] = all_mods[c]; - } - } -@@ -936,7 +955,7 @@ locate_computer_account (adcli_enroll *enroll, - LDAPMessage **rresults, - LDAPMessage **rentry) - { -- char *attrs[] = { "1.1", NULL }; -+ char *attrs[] = { "objectClass", NULL }; - LDAPMessage *results = NULL; - LDAPMessage *entry = NULL; - const char *base; -@@ -948,7 +967,9 @@ locate_computer_account (adcli_enroll *enroll, - /* If we don't yet know our computer dn, then try and find it */ - value = _adcli_ldap_escape_filter (enroll->computer_sam); - return_unexpected_if_fail (value != NULL); -- if (asprintf (&filter, "(&(objectClass=computer)(sAMAccountName=%s))", value) < 0) -+ if (asprintf (&filter, "(&(objectClass=%s)(sAMAccountName=%s))", -+ enroll->is_service ? "msDS-ManagedServiceAccount" : "computer", -+ value) < 0) - return_unexpected_if_reached (); - free (value); - -@@ -962,8 +983,11 @@ locate_computer_account (adcli_enroll *enroll, - if (ret == LDAP_SUCCESS) { - entry = ldap_first_entry (ldap, results); - -- /* If we found a computer account, make note of dn */ -+ /* If we found a computer/service account, make note of dn */ - if (entry) { -+ if (!enroll->is_service_explicit) { -+ check_if_service ( enroll, ldap, results); -+ } - dn = ldap_get_dn (ldap, entry); - free (enroll->computer_dn); - enroll->computer_dn = strdup (dn); -@@ -1003,7 +1027,7 @@ load_computer_account (adcli_enroll *enroll, - LDAPMessage **rresults, - LDAPMessage **rentry) - { -- char *attrs[] = { "1.1", NULL }; -+ char *attrs[] = { "objectClass", NULL }; - LDAPMessage *results = NULL; - LDAPMessage *entry = NULL; - int ret; -@@ -1081,6 +1105,12 @@ locate_or_create_computer_account (adcli_enroll *enroll, - if (res == ADCLI_SUCCESS && entry == NULL) - res = create_computer_account (enroll, ldap); - -+ /* Service account already exists, just continue and update the -+ * password */ -+ if (enroll->is_service && entry != NULL) { -+ res = ADCLI_SUCCESS; -+ } -+ - if (results) - ldap_msgfree (results); - -@@ -1413,6 +1443,11 @@ update_computer_account (adcli_enroll *enroll) - LDAP *ldap; - char *value = NULL; - -+ /* No updates for service accounts */ -+ if (enroll->is_service) { -+ return; -+ } -+ - ldap = adcli_conn_get_ldap_connection (enroll->conn); - return_if_fail (ldap != NULL); - -@@ -1501,6 +1536,11 @@ update_service_principals (adcli_enroll *enroll) - LDAP *ldap; - int ret; - -+ /* No updates for service accounts */ -+ if (enroll->is_service) { -+ return ADCLI_SUCCESS; -+ } -+ - ldap = adcli_conn_get_ldap_connection (enroll->conn); - return_unexpected_if_fail (ldap != NULL); - -@@ -1614,6 +1654,8 @@ load_keytab_entry (krb5_context k5, - enroll->computer_name = name; - name[len - 1] = '\0'; - _adcli_info ("Found computer name in keytab: %s", name); -+ adcli_conn_set_computer_name (enroll->conn, -+ enroll->computer_name); - name = NULL; - - } else if (!enroll->host_fqdn && _adcli_str_has_prefix (name, "host/") && strchr (name, '.')) { -@@ -2002,17 +2044,25 @@ adcli_enroll_prepare (adcli_enroll *enroll, - - adcli_clear_last_error (); - -- /* Basic discovery and figuring out enroll params */ -- res = ensure_host_fqdn (res, enroll); -- res = ensure_computer_name (res, enroll); -- res = ensure_computer_sam (res, enroll); -- res = ensure_user_principal (res, enroll); -- res = ensure_computer_password (res, enroll); -- if (!(flags & ADCLI_ENROLL_NO_KEYTAB)) -+ if (enroll->is_service) { -+ /* Ensure basic params for service accounts */ -+ res = ensure_computer_sam (res, enroll); -+ res = ensure_computer_password (res, enroll); - res = ensure_host_keytab (res, enroll); -- res = ensure_service_names (res, enroll); -- res = ensure_service_principals (res, enroll); -- res = ensure_keytab_principals (res, enroll); -+ res = ensure_keytab_principals (res, enroll); -+ } else { -+ /* Basic discovery and figuring out enroll params */ -+ res = ensure_host_fqdn (res, enroll); -+ res = ensure_computer_name (res, enroll); -+ res = ensure_computer_sam (res, enroll); -+ res = ensure_user_principal (res, enroll); -+ res = ensure_computer_password (res, enroll); -+ if (!(flags & ADCLI_ENROLL_NO_KEYTAB)) -+ res = ensure_host_keytab (res, enroll); -+ res = ensure_service_names (res, enroll); -+ res = ensure_service_principals (res, enroll); -+ res = ensure_keytab_principals (res, enroll); -+ } - - return res; - } -@@ -2157,6 +2207,58 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - return update_keytab_for_principals (enroll, flags); - } - -+static adcli_result -+adcli_enroll_add_description_for_service_account (adcli_enroll *enroll) -+{ -+ const char *fqdn; -+ char *desc; -+ -+ fqdn = adcli_conn_get_host_fqdn (enroll->conn); -+ return_unexpected_if_fail (fqdn != NULL); -+ if (asprintf (&desc, "Please do not edit, Service account for %s, " -+ "managed by adcli.", fqdn) < 0) { -+ return_unexpected_if_reached (); -+ } -+ -+ adcli_enroll_set_description (enroll, desc); -+ free (desc); -+ -+ return ADCLI_SUCCESS; -+} -+ -+static adcli_result -+adcli_enroll_add_keytab_for_service_account (adcli_enroll *enroll) -+{ -+ krb5_context k5; -+ krb5_error_code code; -+ char def_keytab_name[MAX_KEYTAB_NAME_LEN]; -+ char *lc_dom_name; -+ int ret; -+ -+ if (adcli_enroll_get_keytab_name (enroll) == NULL) { -+ k5 = adcli_conn_get_krb5_context (enroll->conn); -+ return_unexpected_if_fail (k5 != NULL); -+ -+ code = krb5_kt_default_name (k5, def_keytab_name, -+ sizeof (def_keytab_name)); -+ return_unexpected_if_fail (code == 0); -+ -+ lc_dom_name = strdup (adcli_conn_get_domain_name (enroll->conn)); -+ return_unexpected_if_fail (lc_dom_name != NULL); -+ _adcli_str_down (lc_dom_name); -+ -+ -+ ret = asprintf (&enroll->keytab_name, "%s.%s", def_keytab_name, -+ lc_dom_name); -+ free (lc_dom_name); -+ return_unexpected_if_fail (ret > 0); -+ } -+ -+ _adcli_info ("Using service account keytab: %s", enroll->keytab_name); -+ -+ return ADCLI_SUCCESS; -+} -+ - adcli_result - adcli_enroll_join (adcli_enroll *enroll, - adcli_enroll_flags flags) -@@ -2172,7 +2274,14 @@ adcli_enroll_join (adcli_enroll *enroll, - if (res != ADCLI_SUCCESS) - return res; - -- res = ensure_default_service_names (enroll); -+ if (enroll->is_service) { -+ res = adcli_enroll_add_description_for_service_account (enroll); -+ if (res == ADCLI_SUCCESS) { -+ res = adcli_enroll_add_keytab_for_service_account (enroll); -+ } -+ } else { -+ res = ensure_default_service_names (enroll); -+ } - if (res != ADCLI_SUCCESS) - return res; - -@@ -2281,6 +2390,11 @@ adcli_enroll_update (adcli_enroll *enroll, - } - free (value); - -+ /* We only support password changes for service accounts */ -+ if (enroll->is_service && (flags & ADCLI_ENROLL_PASSWORD_VALID)) { -+ return ADCLI_SUCCESS; -+ } -+ - return enroll_join_or_update_tasks (enroll, flags); - } - -diff --git a/tools/computer.c b/tools/computer.c -index 5a97d8b..63fd374 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -1074,3 +1074,128 @@ adcli_tool_computer_show (adcli_conn *conn, - adcli_enroll_unref (enroll); - return 0; - } -+ -+int -+adcli_tool_computer_managed_service_account (adcli_conn *conn, -+ int argc, -+ char *argv[]) -+{ -+ adcli_enroll *enroll; -+ adcli_result res; -+ int show_password = 0; -+ int details = 0; -+ int opt; -+ -+ struct option options[] = { -+ { "domain", required_argument, NULL, opt_domain }, -+ { "domain-realm", required_argument, NULL, opt_domain_realm }, -+ { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "use-ldaps", no_argument, 0, opt_use_ldaps }, -+ { "login-user", required_argument, NULL, opt_login_user }, -+ { "login-ccache", optional_argument, NULL, opt_login_ccache }, -+ { "host-fqdn", required_argument, 0, opt_host_fqdn }, -+ { "computer-name", required_argument, 0, opt_computer_name }, -+ { "host-keytab", required_argument, 0, opt_host_keytab }, -+ { "no-password", no_argument, 0, opt_no_password }, -+ { "stdin-password", no_argument, 0, opt_stdin_password }, -+ { "prompt-password", no_argument, 0, opt_prompt_password }, -+ { "domain-ou", required_argument, NULL, opt_domain_ou }, -+ { "show-details", no_argument, NULL, opt_show_details }, -+ { "show-password", no_argument, NULL, opt_show_password }, -+ { "verbose", no_argument, NULL, opt_verbose }, -+ { "help", no_argument, NULL, 'h' }, -+ { 0 }, -+ }; -+ -+ static adcli_tool_desc usages[] = { -+ { 0, "usage: adcli create-msa --domain=xxxx" }, -+ { 0 }, -+ }; -+ -+ enroll = adcli_enroll_new (conn); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } -+ -+ while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { -+ switch (opt) { -+ case opt_one_time_password: -+ adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_COMPUTER_ACCOUNT); -+ adcli_conn_set_computer_password (conn, optarg); -+ break; -+ case opt_show_details: -+ details = 1; -+ break; -+ case opt_show_password: -+ show_password = 1; -+ break; -+ 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: -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } -+ break; -+ } -+ } -+ -+ argc -= optind; -+ argv += optind; -+ -+ if (argc == 1) -+ adcli_conn_set_domain_name (conn, argv[0]); -+ else if (argc > 1) { -+ warnx ("extra arguments specified"); -+ adcli_enroll_unref (enroll); -+ return 2; -+ } -+ -+ if (adcli_conn_get_domain_name (conn) == NULL) { -+ warnx ("domain name is required"); -+ adcli_enroll_unref (enroll); -+ return 2; -+ } -+ -+ adcli_enroll_set_is_service (enroll, true); -+ adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); -+ -+ res = adcli_enroll_load (enroll); -+ if (res != ADCLI_SUCCESS) { -+ /* ignored */ -+ } -+ -+ res = adcli_conn_connect (conn); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; -+ } -+ -+ res = adcli_enroll_join (enroll, 0); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("Adding service account for %s failed: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; -+ } -+ -+ if (details) -+ dump_details (conn, enroll, show_password); -+ else if (show_password) -+ dump_password (conn, enroll); -+ -+ adcli_enroll_unref (enroll); -+ -+ return 0; -+} -diff --git a/tools/tools.c b/tools/tools.c -index 1b6d879..d0dcf98 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -60,6 +60,7 @@ struct { - { "reset-computer", adcli_tool_computer_reset, "Reset a computer account", }, - { "delete-computer", adcli_tool_computer_delete, "Delete a computer account", }, - { "show-computer", adcli_tool_computer_show, "Show computer account attributes stored in AD", }, -+ { "create-msa", adcli_tool_computer_managed_service_account, "Create a managed service account in the given AD domain", }, - { "create-user", adcli_tool_user_create, "Create a user account", }, - { "delete-user", adcli_tool_user_delete, "Delete a user account", }, - { "create-group", adcli_tool_group_create, "Create a group", }, -diff --git a/tools/tools.h b/tools/tools.h -index 3702875..82d5e4e 100644 ---- a/tools/tools.h -+++ b/tools/tools.h -@@ -82,6 +82,10 @@ int adcli_tool_computer_show (adcli_conn *conn, - int argc, - char *argv[]); - -+int adcli_tool_computer_managed_service_account (adcli_conn *conn, -+ int argc, -+ char *argv[]); -+ - int adcli_tool_user_create (adcli_conn *conn, - int argc, - char *argv[]); --- -2.28.0 - diff --git a/0006-discovery-fix.patch b/0006-discovery-fix.patch deleted file mode 100644 index 04568ce..0000000 --- a/0006-discovery-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 08bac0946de29f3e5de90743ce6dfc7118d4ad20 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 11 Feb 2020 17:42:03 +0100 -Subject: [PATCH 6/6] discovery fix - -Do not continue processing on closed connection. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1802258 ---- - library/addisco.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/library/addisco.c b/library/addisco.c -index 6e73ead..f3b3546 100644 ---- a/library/addisco.c -+++ b/library/addisco.c -@@ -622,6 +622,7 @@ ldap_disco (const char *domain, - "Couldn't perform discovery search"); - ldap_unbind_ext_s (ldap[i], NULL, NULL); - ldap[i] = NULL; -+ continue; - } - - /* From https://msdn.microsoft.com/en-us/library/ff718294.aspx first --- -2.25.1 - diff --git a/0006-enroll-use-computer-or-service-in-debug-messages.patch b/0006-enroll-use-computer-or-service-in-debug-messages.patch deleted file mode 100644 index 3b41636..0000000 --- a/0006-enroll-use-computer-or-service-in-debug-messages.patch +++ /dev/null @@ -1,358 +0,0 @@ -From eea6a8071b5e5df74808903bb15b30acf820ce3f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 23 Oct 2020 16:55:11 +0200 -Subject: [PATCH 06/10] enroll: use 'computer' or 'service' in debug messages - -Use proper account type in debug messages. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 115 ++++++++++++++++++++++++++++----------------- - 1 file changed, 72 insertions(+), 43 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index dbfda36..9cdc79b 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -155,6 +155,12 @@ struct _adcli_enroll { - char *description; - }; - -+static const char * -+s_or_c (adcli_enroll *enroll) -+{ -+ return enroll->is_service ? "service" : "computer"; -+} -+ - static void - check_if_service (adcli_enroll *enroll, - LDAP *ldap, -@@ -203,13 +209,15 @@ ensure_computer_name (adcli_result res, - return res; - - if (enroll->computer_name) { -- _adcli_info ("Enrolling computer name: %s", -+ _adcli_info ("Enrolling %s name: %s", -+ s_or_c (enroll), - enroll->computer_name); - return ADCLI_SUCCESS; - } - - if (!enroll->host_fqdn) { -- _adcli_err ("No host name from which to determine the computer name"); -+ _adcli_err ("No host name from which to determine the %s name", -+ s_or_c (enroll)); - return ADCLI_ERR_CONFIG; - } - -@@ -603,7 +611,8 @@ lookup_computer_container (adcli_enroll *enroll, - - } else if (ret != LDAP_SUCCESS) { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_DIRECTORY, -- "Couldn't lookup computer container: %s", base); -+ "Couldn't lookup %s container: %s", -+ s_or_c (enroll), base); - } - - values = _adcli_ldap_parse_values (ldap, results, attrs[0]); -@@ -614,8 +623,8 @@ lookup_computer_container (adcli_enroll *enroll, - if (strncmp (values[i], prefix, prefix_len) == 0) { - enroll->computer_container = strdup (values[i] + prefix_len); - return_unexpected_if_fail (enroll->computer_container != NULL); -- _adcli_info ("Found well known computer container at: %s", -- enroll->computer_container); -+ _adcli_info ("Found well known %s container at: %s", -+ s_or_c (enroll), enroll->computer_container); - break; - } - } -@@ -629,8 +638,9 @@ lookup_computer_container (adcli_enroll *enroll, - if (ret == LDAP_SUCCESS) { - enroll->computer_container = _adcli_ldap_parse_dn (ldap, results); - if (enroll->computer_container) { -- _adcli_info ("Well known computer container not " -+ _adcli_info ("Well known %s container not " - "found, but found suitable one at: %s", -+ s_or_c (enroll), - enroll->computer_container); - } - } -@@ -646,7 +656,8 @@ lookup_computer_container (adcli_enroll *enroll, - } - - if (!enroll->computer_container) { -- _adcli_err ("Couldn't find location to create computer accounts"); -+ _adcli_err ("Couldn't find location to create %s accounts", -+ s_or_c (enroll)); - return ADCLI_ERR_DIRECTORY; - } - -@@ -674,7 +685,8 @@ calculate_computer_account (adcli_enroll *enroll, - if (asprintf (&enroll->computer_dn, "CN=%s,%s", enroll->computer_name, enroll->computer_container) < 0) - return_unexpected_if_reached (); - -- _adcli_info ("Calculated computer account: %s", enroll->computer_dn); -+ _adcli_info ("Calculated %s account: %s", -+ s_or_c (enroll), enroll->computer_dn); - return ADCLI_SUCCESS; - } - -@@ -861,7 +873,8 @@ create_computer_account (adcli_enroll *enroll, - enroll->computer_dn); - } - -- _adcli_info ("Created computer account: %s", enroll->computer_dn); -+ _adcli_info ("Created %s account: %s", s_or_c (enroll), -+ enroll->computer_dn); - return ADCLI_SUCCESS; - } - -@@ -908,17 +921,17 @@ validate_computer_account (adcli_enroll *enroll, - assert (enroll->computer_dn != NULL); - - if (already_exists && !allow_overwrite) { -- _adcli_err ("The computer account %s already exists", -- enroll->computer_name); -+ _adcli_err ("The %s account %s already exists", -+ s_or_c (enroll), enroll->computer_name); - return ADCLI_ERR_CONFIG; - } - - /* Do we have an explicitly requested ou? */ - if (enroll->domain_ou && enroll->domain_ou_explicit && already_exists) { - if (!_adcli_ldap_dn_has_ancestor (enroll->computer_dn, enroll->domain_ou)) { -- _adcli_err ("The computer account %s already exists, " -+ _adcli_err ("The %s account %s already exists, " - "but is not in the desired organizational unit.", -- enroll->computer_name); -+ s_or_c (enroll), enroll->computer_name); - return ADCLI_ERR_CONFIG; - } - } -@@ -943,7 +956,8 @@ delete_computer_account (adcli_enroll *enroll, - "Couldn't delete computer account: %s", - enroll->computer_dn); - } else { -- _adcli_info ("Deleted computer account at: %s", enroll->computer_dn); -+ _adcli_info ("Deleted %s account at: %s", s_or_c (enroll), -+ enroll->computer_dn); - } - - return ADCLI_SUCCESS; -@@ -992,20 +1006,21 @@ locate_computer_account (adcli_enroll *enroll, - free (enroll->computer_dn); - enroll->computer_dn = strdup (dn); - return_unexpected_if_fail (enroll->computer_dn != NULL); -- _adcli_info ("Found computer account for %s at: %s", -- enroll->computer_sam, dn); -+ _adcli_info ("Found %s account for %s at: %s", -+ s_or_c (enroll), enroll->computer_sam, dn); - ldap_memfree (dn); - - } else { - ldap_msgfree (results); - results = NULL; -- _adcli_info ("Computer account for %s does not exist", -- enroll->computer_sam); -+ _adcli_info ("A %s account for %s does not exist", -+ s_or_c (enroll), enroll->computer_sam); - } - - } else { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_DIRECTORY, -- "Couldn't lookup computer account: %s", -+ "Couldn't lookup %s account: %s", -+ s_or_c (enroll), - enroll->computer_sam); - } - -@@ -1039,7 +1054,9 @@ load_computer_account (adcli_enroll *enroll, - if (ret == LDAP_SUCCESS) { - entry = ldap_first_entry (ldap, results); - if (entry) { -- _adcli_info ("Found computer account for %s at: %s", -+ check_if_service (enroll, ldap, results); -+ _adcli_info ("Found %s account for %s at: %s", -+ s_or_c (enroll), - enroll->computer_sam, enroll->computer_dn); - } - -@@ -1146,7 +1163,8 @@ set_password_with_user_creds (adcli_enroll *enroll) - &result_code_string, &result_string); - - if (code != 0) { -- _adcli_err ("Couldn't set password for computer account: %s: %s", -+ _adcli_err ("Couldn't set password for %s account: %s: %s", -+ s_or_c (enroll), - enroll->computer_sam, krb5_get_error_message (k5, code)); - /* TODO: Parse out these values */ - res = ADCLI_ERR_DIRECTORY; -@@ -1160,7 +1178,8 @@ set_password_with_user_creds (adcli_enroll *enroll) - if (result_string.length) - message = _adcli_str_dupn (result_string.data, result_string.length); - #endif -- _adcli_err ("Cannot set computer password: %.*s%s%s", -+ _adcli_err ("Cannot set %s password: %.*s%s%s", -+ s_or_c (enroll), - (int)result_code_string.length, result_code_string.data, - message ? ": " : "", message ? message : ""); - res = ADCLI_ERR_CREDENTIALS; -@@ -1170,7 +1189,7 @@ set_password_with_user_creds (adcli_enroll *enroll) - free (message); - #endif - } else { -- _adcli_info ("Set computer password"); -+ _adcli_info ("Set %s password", s_or_c (enroll)); - if (enroll->kvno > 0) { - enroll->kvno++; - _adcli_info ("kvno incremented to %d", enroll->kvno); -@@ -1203,7 +1222,8 @@ set_password_with_computer_creds (adcli_enroll *enroll) - - code = _adcli_kinit_computer_creds (enroll->conn, "kadmin/changepw", NULL, &creds); - if (code != 0) { -- _adcli_err ("Couldn't get change password ticket for computer account: %s: %s", -+ _adcli_err ("Couldn't get change password ticket for %s account: %s: %s", -+ s_or_c (enroll), - enroll->computer_sam, krb5_get_error_message (k5, code)); - return ADCLI_ERR_DIRECTORY; - } -@@ -1214,7 +1234,8 @@ set_password_with_computer_creds (adcli_enroll *enroll) - krb5_free_cred_contents (k5, &creds); - - if (code != 0) { -- _adcli_err ("Couldn't change password for computer account: %s: %s", -+ _adcli_err ("Couldn't change password for %s account: %s: %s", -+ s_or_c (enroll), - enroll->computer_sam, krb5_get_error_message (k5, code)); - /* TODO: Parse out these values */ - res = ADCLI_ERR_DIRECTORY; -@@ -1284,7 +1305,8 @@ retrieve_computer_account (adcli_enroll *enroll) - - if (ret != LDAP_SUCCESS) { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_DIRECTORY, -- "Couldn't retrieve computer account info: %s", -+ "Couldn't retrieve %s account info: %s", -+ s_or_c (enroll), - enroll->computer_dn); - } - -@@ -1294,15 +1316,15 @@ retrieve_computer_account (adcli_enroll *enroll) - if (value != NULL) { - kvno = strtoul (value, &end, 10); - if (end == NULL || *end != '\0') { -- _adcli_err ("Invalid kvno '%s' for computer account in directory: %s", -- value, enroll->computer_dn); -+ _adcli_err ("Invalid kvno '%s' for %s account in directory: %s", -+ value, s_or_c (enroll), enroll->computer_dn); - res = ADCLI_ERR_DIRECTORY; - - } else { - enroll->kvno = kvno; - -- _adcli_info ("Retrieved kvno '%s' for computer account in directory: %s", -- value, enroll->computer_dn); -+ _adcli_info ("Retrieved kvno '%s' for %s account in directory: %s", -+ value, s_or_c (enroll), enroll->computer_dn); - } - - free (value); -@@ -1311,8 +1333,8 @@ retrieve_computer_account (adcli_enroll *enroll) - /* Apparently old AD didn't have this attribute, use zero */ - enroll->kvno = 0; - -- _adcli_info ("No kvno found for computer account in directory: %s", -- enroll->computer_dn); -+ _adcli_info ("No kvno found for %s account in directory: %s", -+ s_or_c (enroll), enroll->computer_dn); - } - } - -@@ -1353,12 +1375,14 @@ update_and_calculate_enctypes (adcli_enroll *enroll) - - if (ret == LDAP_INSUFFICIENT_ACCESS) { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_CREDENTIALS, -- "Insufficient permissions to set encryption types on computer account: %s", -+ "Insufficient permissions to set encryption types on %s account: %s", -+ s_or_c (enroll), - enroll->computer_dn); - - } else if (ret != LDAP_SUCCESS) { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_DIRECTORY, -- "Couldn't set encryption types on computer account: %s", -+ "Couldn't set encryption types on %s account: %s", -+ s_or_c (enroll), - enroll->computer_dn); - } - -@@ -1381,13 +1405,14 @@ update_computer_attribute (adcli_enroll *enroll, - string = _adcli_ldap_mods_to_string (mods); - return_unexpected_if_fail (string != NULL); - -- _adcli_info ("Modifying computer account: %s", string); -+ _adcli_info ("Modifying %s account: %s", s_or_c (enroll), string); - - ret = ldap_modify_ext_s (ldap, enroll->computer_dn, mods, NULL, NULL); - - if (ret != LDAP_SUCCESS) { -- _adcli_warn ("Couldn't set %s on computer account: %s: %s", -- string, enroll->computer_dn, ldap_err2string (ret)); -+ _adcli_warn ("Couldn't set %s on %s account: %s: %s", -+ string, s_or_c (enroll), enroll->computer_dn, -+ ldap_err2string (ret)); - res = ADCLI_ERR_DIRECTORY; - } - -@@ -1411,8 +1436,8 @@ static char *get_user_account_control (adcli_enroll *enroll) - - attr_val = strtoul (uac_str, &end, 10); - if (*end != '\0' || attr_val > UINT32_MAX) { -- _adcli_warn ("Invalid userAccountControl '%s' for computer account in directory: %s, assuming 0", -- uac_str, enroll->computer_dn); -+ _adcli_warn ("Invalid userAccountControl '%s' for %s account in directory: %s, assuming 0", -+ uac_str, s_or_c (enroll), enroll->computer_dn); - } else { - uac = attr_val; - } -@@ -1653,7 +1678,8 @@ load_keytab_entry (krb5_context k5, - _adcli_str_has_suffix (name, "$") && !strchr (name, '/')) { - enroll->computer_name = name; - name[len - 1] = '\0'; -- _adcli_info ("Found computer name in keytab: %s", name); -+ _adcli_info ("Found %s name in keytab: %s", -+ s_or_c (enroll), name); - adcli_conn_set_computer_name (enroll->conn, - enroll->computer_name); - name = NULL; -@@ -2348,7 +2374,8 @@ adcli_enroll_read_computer_account (adcli_enroll *enroll, - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { -- _adcli_err ("No computer account for %s exists", enroll->computer_sam); -+ _adcli_err ("No %s account for %s exists", -+ s_or_c (enroll), enroll->computer_sam); - return ADCLI_ERR_CONFIG; - } - } -@@ -2460,7 +2487,8 @@ adcli_enroll_delete (adcli_enroll *enroll, - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { -- _adcli_err ("No computer account for %s exists", -+ _adcli_err ("No %s account for %s exists", -+ s_or_c (enroll), - enroll->computer_sam); - return ADCLI_ERR_CONFIG; - } -@@ -2503,7 +2531,8 @@ adcli_enroll_password (adcli_enroll *enroll, - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { -- _adcli_err ("No computer account for %s exists", -+ _adcli_err ("No %s account for %s exists", -+ s_or_c (enroll), - enroll->computer_sam); - return ADCLI_ERR_CONFIG; - } --- -2.28.0 - diff --git a/0007-enroll-more-filters-for-random-characters.patch b/0007-enroll-more-filters-for-random-characters.patch deleted file mode 100644 index b2ff629..0000000 --- a/0007-enroll-more-filters-for-random-characters.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 2750f536ac6746756335eec8332060d2365a4126 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 27 Oct 2020 14:44:07 +0100 -Subject: [PATCH 07/10] enroll: more filters for random characters - -Make handling of random strings more flexible. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 30 +++++++++++++++++++++++++++--- - 1 file changed, 27 insertions(+), 3 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 9cdc79b..44383cc 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -259,6 +259,29 @@ ensure_computer_sam (adcli_result res, - return ADCLI_SUCCESS; - } - -+typedef int (rand_filter) (char *password, int length); -+ -+static int -+filter_sam_chars (char *password, -+ int length) -+{ -+ int i, j; -+ -+ /* -+ * There are a couple of restrictions for characters in the -+ * sAMAccountName attribute value, for our purpose (random suffix) -+ * letters and numbers are sufficient. -+ */ -+ for (i = 0, j = 0; i < length; i++) { -+ if (password[i] >= 48 && password[i] <= 122 && -+ isalnum (password[i])) -+ password[j++] = password[i]; -+ } -+ -+ /* return the number of valid characters remaining */ -+ return j; -+} -+ - static int - filter_password_chars (char *password, - int length) -@@ -283,7 +306,8 @@ filter_password_chars (char *password, - - static char * - generate_host_password (adcli_enroll *enroll, -- size_t length) -+ size_t length, -+ rand_filter *filter) - { - char *password; - krb5_context k5; -@@ -305,7 +329,7 @@ generate_host_password (adcli_enroll *enroll, - code = krb5_c_random_make_octets (k5, &buffer); - return_val_if_fail (code == 0, NULL); - -- at += filter_password_chars (buffer.data, buffer.length); -+ at += filter (buffer.data, buffer.length); - assert (at <= length); - } - -@@ -333,7 +357,7 @@ ensure_computer_password (adcli_result res, - _adcli_info ("Using default reset computer password"); - - } else { -- enroll->computer_password = generate_host_password (enroll, length); -+ enroll->computer_password = generate_host_password (enroll, length, filter_password_chars); - return_unexpected_if_fail (enroll->computer_password != NULL); - _adcli_info ("Generated %d character computer password", length); - } --- -2.28.0 - diff --git a/0008-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch b/0008-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch deleted file mode 100644 index 9279f07..0000000 --- a/0008-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 81c98e367ba4bc8d77668acd31e462ad31cf12be Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 27 Oct 2020 14:47:31 +0100 -Subject: [PATCH 08/10] enroll: make - adcli_enroll_add_keytab_for_service_account public - -Determine keytab name more early to catch errors more early. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 13 +++++++------ - library/adenroll.h | 2 ++ - tools/computer.c | 6 ++++++ - 3 files changed, 15 insertions(+), 6 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 44383cc..05bb085 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -2276,9 +2276,10 @@ adcli_enroll_add_description_for_service_account (adcli_enroll *enroll) - return ADCLI_SUCCESS; - } - --static adcli_result -+adcli_result - adcli_enroll_add_keytab_for_service_account (adcli_enroll *enroll) - { -+ adcli_result res; - krb5_context k5; - krb5_error_code code; - char def_keytab_name[MAX_KEYTAB_NAME_LEN]; -@@ -2286,11 +2287,14 @@ adcli_enroll_add_keytab_for_service_account (adcli_enroll *enroll) - int ret; - - if (adcli_enroll_get_keytab_name (enroll) == NULL) { -- k5 = adcli_conn_get_krb5_context (enroll->conn); -- return_unexpected_if_fail (k5 != NULL); -+ res = _adcli_krb5_init_context (&k5); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } - - code = krb5_kt_default_name (k5, def_keytab_name, - sizeof (def_keytab_name)); -+ krb5_free_context (k5); - return_unexpected_if_fail (code == 0); - - lc_dom_name = strdup (adcli_conn_get_domain_name (enroll->conn)); -@@ -2326,9 +2330,6 @@ adcli_enroll_join (adcli_enroll *enroll, - - if (enroll->is_service) { - res = adcli_enroll_add_description_for_service_account (enroll); -- if (res == ADCLI_SUCCESS) { -- res = adcli_enroll_add_keytab_for_service_account (enroll); -- } - } else { - res = ensure_default_service_names (enroll); - } -diff --git a/library/adenroll.h b/library/adenroll.h -index 7765ed4..11a30c8 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -146,6 +146,8 @@ const char * adcli_enroll_get_keytab_name (adcli_enroll *enroll); - void adcli_enroll_set_keytab_name (adcli_enroll *enroll, - const char *value); - -+adcli_result adcli_enroll_add_keytab_for_service_account (adcli_enroll *enroll); -+ - krb5_enctype * adcli_enroll_get_keytab_enctypes (adcli_enroll *enroll); - - void adcli_enroll_set_keytab_enctypes (adcli_enroll *enroll, -diff --git a/tools/computer.c b/tools/computer.c -index 63fd374..98a0472 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -1166,6 +1166,12 @@ adcli_tool_computer_managed_service_account (adcli_conn *conn, - - adcli_enroll_set_is_service (enroll, true); - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); -+ res = adcli_enroll_add_keytab_for_service_account (enroll); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("Failed to set domain specific keytab name"); -+ adcli_enroll_unref (enroll); -+ return 2; -+ } - - res = adcli_enroll_load (enroll); - if (res != ADCLI_SUCCESS) { --- -2.28.0 - diff --git a/0009-enroll-allow-fqdn-for-locate_computer_account.patch b/0009-enroll-allow-fqdn-for-locate_computer_account.patch deleted file mode 100644 index a35e050..0000000 --- a/0009-enroll-allow-fqdn-for-locate_computer_account.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 2a695dfe09cafeee3a648d3b969c364f8d3f494f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 27 Oct 2020 14:49:55 +0100 -Subject: [PATCH 09/10] enroll: allow fqdn for locate_computer_account - -Make it possible to find existing manages service account by the -fully-qualified name. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 45 +++++++++++++++++++++++++++++++-------------- - 1 file changed, 31 insertions(+), 14 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 05bb085..98cd5fa 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -990,10 +990,11 @@ delete_computer_account (adcli_enroll *enroll, - static adcli_result - locate_computer_account (adcli_enroll *enroll, - LDAP *ldap, -+ bool use_fqdn, - LDAPMessage **rresults, - LDAPMessage **rentry) - { -- char *attrs[] = { "objectClass", NULL }; -+ char *attrs[] = { "objectClass", "CN", NULL }; - LDAPMessage *results = NULL; - LDAPMessage *entry = NULL; - const char *base; -@@ -1003,12 +1004,22 @@ locate_computer_account (adcli_enroll *enroll, - int ret = 0; - - /* If we don't yet know our computer dn, then try and find it */ -- value = _adcli_ldap_escape_filter (enroll->computer_sam); -- return_unexpected_if_fail (value != NULL); -- if (asprintf (&filter, "(&(objectClass=%s)(sAMAccountName=%s))", -- enroll->is_service ? "msDS-ManagedServiceAccount" : "computer", -- value) < 0) -- return_unexpected_if_reached (); -+ if (use_fqdn) { -+ return_unexpected_if_fail (enroll->host_fqdn != NULL); -+ value = _adcli_ldap_escape_filter (enroll->host_fqdn); -+ return_unexpected_if_fail (value != NULL); -+ if (asprintf (&filter, "(&(objectClass=%s)(dNSHostName=%s))", -+ enroll->is_service ? "msDS-ManagedServiceAccount" : "computer", -+ value) < 0) -+ return_unexpected_if_reached (); -+ } else { -+ value = _adcli_ldap_escape_filter (enroll->computer_sam); -+ return_unexpected_if_fail (value != NULL); -+ if (asprintf (&filter, "(&(objectClass=%s)(sAMAccountName=%s))", -+ enroll->is_service ? "msDS-ManagedServiceAccount" : "computer", -+ value) < 0) -+ return_unexpected_if_reached (); -+ } - free (value); - - base = adcli_conn_get_default_naming_context (enroll->conn); -@@ -1031,21 +1042,26 @@ locate_computer_account (adcli_enroll *enroll, - enroll->computer_dn = strdup (dn); - return_unexpected_if_fail (enroll->computer_dn != NULL); - _adcli_info ("Found %s account for %s at: %s", -- s_or_c (enroll), enroll->computer_sam, dn); -+ s_or_c (enroll), -+ use_fqdn ? enroll->host_fqdn -+ : enroll->computer_sam, dn); - ldap_memfree (dn); - - } else { - ldap_msgfree (results); - results = NULL; - _adcli_info ("A %s account for %s does not exist", -- s_or_c (enroll), enroll->computer_sam); -+ s_or_c (enroll), -+ use_fqdn ? enroll->host_fqdn -+ : enroll->computer_sam); - } - - } else { - return _adcli_ldap_handle_failure (ldap, ADCLI_ERR_DIRECTORY, - "Couldn't lookup %s account: %s", - s_or_c (enroll), -- enroll->computer_sam); -+ use_fqdn ? enroll->host_fqdn -+ :enroll->computer_sam); - } - - if (rresults) -@@ -1120,7 +1136,8 @@ locate_or_create_computer_account (adcli_enroll *enroll, - - /* Try to find the computer account */ - if (!enroll->computer_dn) { -- res = locate_computer_account (enroll, ldap, &results, &entry); -+ res = locate_computer_account (enroll, ldap, false, -+ &results, &entry); - if (res != ADCLI_SUCCESS) - return res; - searched = 1; -@@ -2395,7 +2412,7 @@ adcli_enroll_read_computer_account (adcli_enroll *enroll, - - /* Find the computer dn */ - if (!enroll->computer_dn) { -- res = locate_computer_account (enroll, ldap, NULL, NULL); -+ res = locate_computer_account (enroll, ldap, false, NULL, NULL); - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { -@@ -2508,7 +2525,7 @@ adcli_enroll_delete (adcli_enroll *enroll, - - /* Find the computer dn */ - if (!enroll->computer_dn) { -- res = locate_computer_account (enroll, ldap, NULL, NULL); -+ res = locate_computer_account (enroll, ldap, false, NULL, NULL); - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { -@@ -2552,7 +2569,7 @@ adcli_enroll_password (adcli_enroll *enroll, - - /* Find the computer dn */ - if (!enroll->computer_dn) { -- res = locate_computer_account (enroll, ldap, NULL, NULL); -+ res = locate_computer_account (enroll, ldap, false, NULL, NULL); - if (res != ADCLI_SUCCESS) - return res; - if (!enroll->computer_dn) { --- -2.28.0 - diff --git a/0010-service-account-add-random-suffix-to-account-name.patch b/0010-service-account-add-random-suffix-to-account-name.patch deleted file mode 100644 index 74a93fb..0000000 --- a/0010-service-account-add-random-suffix-to-account-name.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 6b94f9712378b8f1fa1bc530c64cb987abb0c43b Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 27 Oct 2020 15:23:04 +0100 -Subject: [PATCH 10/10] service-account: add random suffix to account name - -Add a random component to the default managed service account name to -avoid name collisions. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1854112 ---- - library/adenroll.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 79 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 98cd5fa..f693e58 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1121,6 +1121,59 @@ load_computer_account (adcli_enroll *enroll, - return ADCLI_SUCCESS; - } - -+static adcli_result -+refresh_service_account_name_sam_and_princ (adcli_enroll *enroll, -+ const char *name) -+{ -+ adcli_result res; -+ -+ adcli_enroll_set_computer_name (enroll, name); -+ res = ensure_computer_sam (ADCLI_SUCCESS, enroll); -+ res = ensure_keytab_principals (res, enroll); -+ -+ return res; -+} -+ -+static adcli_result -+calculate_random_service_account_name (adcli_enroll *enroll) -+{ -+ char *suffix; -+ char *new_name; -+ int ret; -+ adcli_result res; -+ -+ suffix = generate_host_password (enroll, 3, filter_sam_chars); -+ return_unexpected_if_fail (suffix != NULL); -+ -+ ret = asprintf (&new_name, "%s!%s", enroll->computer_name, suffix); -+ free (suffix); -+ return_unexpected_if_fail (ret > 0); -+ -+ res = refresh_service_account_name_sam_and_princ (enroll, new_name); -+ free (new_name); -+ -+ return res; -+} -+ -+static adcli_result -+get_service_account_name_from_ldap (adcli_enroll *enroll, LDAPMessage *results) -+{ -+ LDAP *ldap; -+ char *cn; -+ adcli_result res; -+ -+ ldap = adcli_conn_get_ldap_connection (enroll->conn); -+ assert (ldap != NULL); -+ -+ cn = _adcli_ldap_parse_value (ldap, results, "CN"); -+ return_unexpected_if_fail (cn != NULL); -+ -+ res = refresh_service_account_name_sam_and_princ (enroll, cn); -+ free (cn); -+ -+ return res; -+} -+ - static adcli_result - locate_or_create_computer_account (adcli_enroll *enroll, - int allow_overwrite) -@@ -1143,8 +1196,32 @@ locate_or_create_computer_account (adcli_enroll *enroll, - searched = 1; - } - -+ /* Try with fqdn for service accounts */ -+ if (!enroll->computer_dn && enroll->is_service -+ && enroll->host_fqdn != NULL) { -+ res = locate_computer_account (enroll, ldap, true, -+ &results, &entry); -+ if (res != ADCLI_SUCCESS) -+ return res; -+ searched = 1; -+ -+ if (results != NULL) { -+ res = get_service_account_name_from_ldap (enroll, -+ results); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ } -+ } -+ - /* Next try and come up with where we think it should be */ - if (enroll->computer_dn == NULL) { -+ if (enroll->is_service && !enroll->computer_name_explicit) { -+ res = calculate_random_service_account_name (enroll); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ } - res = calculate_computer_account (enroll, ldap); - if (res != ADCLI_SUCCESS) - return res; -@@ -2113,6 +2190,8 @@ adcli_enroll_prepare (adcli_enroll *enroll, - - if (enroll->is_service) { - /* Ensure basic params for service accounts */ -+ res = ensure_host_fqdn (res, enroll); -+ res = ensure_computer_name (res, enroll); - res = ensure_computer_sam (res, enroll); - res = ensure_computer_password (res, enroll); - res = ensure_host_keytab (res, enroll); --- -2.28.0 - diff --git a/adcli.spec b/adcli.spec index 507efba..b4ce2f9 100644 --- a/adcli.spec +++ b/adcli.spec @@ -1,49 +1,26 @@ -Name: adcli -Version: 0.9.0 -Release: 7%{?dist} -Summary: Active Directory enrollment -License: LGPLv2+ -URL: http://cgit.freedesktop.org/realmd/adcli -Source0: https://gitlab.freedesktop.org/realmd/adcli/uploads/02d8757266c24fdc10822306582287bf/adcli-%{version}.tar.gz +Name: adcli +Version: 0.9.1 +Release: 1%{?dist} +Summary: Active Directory enrollment +License: LGPLv2+ +URL: https://gitlab.freedesktop.org/realmd/adcli +Source0: https://gitlab.freedesktop.org/sbose/adcli/uploads/30880d967e79cee789194435e70fbf30/adcli-%{version}.tar.gz -Patch1: 0001-man-move-note-to-the-right-section.patch -Patch2: 0002-tools-add-show-computer-command.patch -Patch3: 0003-add-description-option-to-join-and-update.patch -Patch4: 0004-Use-GSS-SPNEGO-if-available.patch -Patch5: 0005-add-option-use-ldaps.patch -Patch6: 0006-discovery-fix.patch -Patch7: 0001-delete-do-not-exit-if-keytab-cannot-be-read.patch -Patch8: 0001-tools-disable-SSSD-s-locator-plugin.patch -Patch9: 0001-tools-fix-typo-in-show-password-help-output.patch -Patch10: 0002-man-explain-optional-parameter-of-login-ccache-bette.patch -Patch11: 0003-man-make-handling-of-optional-credential-cache-more-.patch - -Patch12: 0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch -Patch13: 0002-join-update-set-dNSHostName-if-not-set.patch -Patch14: 0003-doc-explain-required-AD-permissions.patch -Patch15: 0004-enroll-add-is_service-member.patch -Patch16: 0005-computer-add-create-msa-sub-command.patch -Patch17: 0006-enroll-use-computer-or-service-in-debug-messages.patch -Patch18: 0007-enroll-more-filters-for-random-characters.patch -Patch19: 0008-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch -Patch20: 0009-enroll-allow-fqdn-for-locate_computer_account.patch -Patch21: 0010-service-account-add-random-suffix-to-account-name.patch - -BuildRequires: gcc -BuildRequires: intltool pkgconfig -BuildRequires: libtool -BuildRequires: gettext-devel -BuildRequires: krb5-devel -BuildRequires: openldap-devel -BuildRequires: libxslt -BuildRequires: xmlto +BuildRequires: gcc +BuildRequires: intltool pkgconfig +BuildRequires: libtool +BuildRequires: gettext-devel +BuildRequires: krb5-devel +BuildRequires: openldap-devel +BuildRequires: libxslt +BuildRequires: xmlto BuildRequires: make -Requires: cyrus-sasl-gssapi +Requires: cyrus-sasl-gssapi # adcli no longer has a library of development files # the adcli tool itself is to be used by callers -Obsoletes: adcli-devel < 0.5 +Obsoletes: adcli-devel < 0.5 %description adcli is a tool for joining an Active Directory domain using @@ -86,6 +63,9 @@ documentation. %doc %{_datadir}/doc/adcli/* %changelog +* Sat Feb 20 2021 Sumit Bose - 0.9.1-1 +- Update to upstream release 0.9.1 + * Mon Jan 25 2021 Fedora Release Engineering - 0.9.0-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild diff --git a/sources b/sources index 4e3b7c0..d958e5d 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (adcli-0.9.0.tar.gz) = e9b210bf7a932750fc838d6f027ca1fbeca1bd6a0028b551c9a72c0fe3ee680d47031c614b74447613d06bd41462c489e8572d49e60b344d575ebb572c022344 +SHA512 (adcli-0.9.1.tar.gz) = 60562720bf28f2dec06f272bdb875e3486f223e77f8a9e96b3468d17dbebdf9ddabd147d7e65c5de9ba7d4e8c033ad6d28a4012d03297c7de25b78ef4890746d