diff --git a/.adcli.metadata b/.adcli.metadata index fda023a..871cb56 100644 --- a/.adcli.metadata +++ b/.adcli.metadata @@ -1 +1 @@ -f3f9537502eba38a22889fbab6e1100c32175ca2 SOURCES/adcli-0.8.2.tar.gz +5aba9ae88ad5a75f8ce143372cb8678b96ca5773 SOURCES/adcli-0.9.2.tar.gz diff --git a/.gitignore b/.gitignore index d651b5a..e330f41 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/adcli-0.8.2.tar.gz +SOURCES/adcli-0.9.2.tar.gz diff --git a/SOURCES/0001-Add-setattr-option.patch b/SOURCES/0001-Add-setattr-option.patch deleted file mode 100644 index abc40bb..0000000 --- a/SOURCES/0001-Add-setattr-option.patch +++ /dev/null @@ -1,384 +0,0 @@ -From c5b0cee2976682b4fc1aeb02636cc9f2c6dbc2a5 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 14 Jun 2021 07:54:01 +0200 -Subject: [PATCH 1/2] Add setattr option - -With the new option common LDAP attributes can be set. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1690920 ---- - doc/adcli.xml | 34 +++++++++ - library/adenroll.c | 169 ++++++++++++++++++++++++++++++++++++++++++++- - library/adenroll.h | 4 ++ - tools/computer.c | 10 +++ - 4 files changed, 216 insertions(+), 1 deletion(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 6c36297..8383aa7 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -374,6 +374,23 @@ Password for Administrator: - service should be accessible with a different host - name as well. - -+ -+ -+ Add the LDAP attribute -+ with the -+ given to -+ the new LDAP host object. -+ This option can be used multiple times to add multiple -+ different attributes. Multi-value attributes are -+ currently not supported. -+ Please note that the account used to join the -+ domain must have the required privileges to add the -+ given attributes. Some attributes might have -+ constraints with respect to syntax and allowed values -+ which must be met as well. Attributes managed by other -+ adcli options cannot be set with this option. -+ -+ - - - After a successful join print out information -@@ -543,6 +560,23 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - Remove a service principal name from - the keytab and the AD host object. - -+ -+ -+ Add the LDAP attribute -+ with the -+ given to -+ the LDAP host object. -+ This option can be used multiple times to add multiple -+ different attributes. Multi-value attributes are -+ currently not supported. -+ Please note that the account used to update the -+ host object must have the required privileges to modify -+ the given attributes. Some attributes might have -+ constraints with respect to syntax and allowed values -+ which must be met as well. Attributes managed by other -+ adcli options cannot be set with this option. -+ -+ - - - After a successful join print out information -diff --git a/library/adenroll.c b/library/adenroll.c -index 0b1c066..dd51567 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -150,4 +150,5 @@ struct _adcli_enroll { - char *description; -+ char **setattr; - }; - - static const char * -@@ -795,6 +796,56 @@ calculate_enctypes (adcli_enroll *enroll, char **enctype) - return ADCLI_SUCCESS; - } - -+static LDAPMod ** -+get_mods_for_attrs (adcli_enroll *enroll, int mod_op) -+{ -+ size_t len; -+ size_t c; -+ char *end; -+ LDAPMod **mods = NULL; -+ -+ len = _adcli_strv_len (enroll->setattr); -+ if (len == 0) { -+ return NULL; -+ } -+ -+ mods = calloc (len + 1, sizeof (LDAPMod *)); -+ return_val_if_fail (mods != NULL, NULL); -+ -+ for (c = 0; c < len; c++) { -+ end = strchr (enroll->setattr[c], '='); -+ if (end == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ -+ mods[c] = calloc (1, sizeof (LDAPMod)); -+ if (mods[c] == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ -+ mods[c]->mod_op = mod_op; -+ *end = '\0'; -+ mods[c]->mod_type = strdup (enroll->setattr[c]); -+ *end = '='; -+ mods[c]->mod_values = calloc (2, sizeof (char *)); -+ if (mods[c]->mod_type == NULL || mods[c]->mod_values == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ -+ mods[c]->mod_values[0] = strdup (end + 1); -+ if (mods[c]->mod_values[0] == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ } -+ -+ return mods; -+} -+ -+ - static adcli_result - create_computer_account (adcli_enroll *enroll, - LDAP *ldap) -@@ -828,6 +879,7 @@ create_computer_account (adcli_enroll *enroll, - size_t m; - uint32_t uac = UAC_WORKSTATION_TRUST_ACCOUNT | UAC_DONT_EXPIRE_PASSWORD ; - char *uac_str = NULL; -+ LDAPMod **extra_mods = NULL; - - LDAPMod *all_mods[] = { - &objectClass, -@@ -845,7 +897,7 @@ create_computer_account (adcli_enroll *enroll, - }; - - size_t mods_count = sizeof (all_mods) / sizeof (LDAPMod *); -- LDAPMod *mods[mods_count]; -+ LDAPMod **mods; - - if (adcli_enroll_get_trusted_for_delegation (enroll)) { - uac |= UAC_TRUSTED_FOR_DELEGATION; -@@ -868,6 +920,17 @@ create_computer_account (adcli_enroll *enroll, - } - vals_supportedEncryptionTypes[0] = val; - -+ if (enroll->setattr != NULL) { -+ extra_mods = get_mods_for_attrs (enroll, LDAP_MOD_ADD); -+ if (extra_mods == NULL) { -+ _adcli_err ("Failed to add setattr attributes, " -+ "just using defaults"); -+ } -+ } -+ -+ mods = calloc (mods_count + seq_count (extra_mods) + 1, sizeof (LDAPMod *)); -+ return_val_if_fail (mods != NULL, ADCLI_ERR_UNEXPECTED); -+ - m = 0; - for (c = 0; c < mods_count - 1; c++) { - /* Skip empty LDAP sttributes */ -@@ -875,9 +938,15 @@ create_computer_account (adcli_enroll *enroll, - mods[m++] = all_mods[c]; - } - } -+ -+ for (c = 0; c < seq_count (extra_mods); c++) { -+ mods[m++] = extra_mods[c]; -+ } - mods[m] = NULL; - - ret = ldap_add_ext_s (ldap, enroll->computer_dn, mods, NULL, NULL); -+ ldap_mods_free (extra_mods, 1); -+ free (mods); - free (uac_str); - free (val); - -@@ -1698,6 +1767,14 @@ update_computer_account (adcli_enroll *enroll) - res |= update_computer_attribute (enroll, ldap, mods); - } - -+ if (res == ADCLI_SUCCESS && enroll->setattr != NULL) { -+ LDAPMod **mods = get_mods_for_attrs (enroll, LDAP_MOD_REPLACE); -+ if (mods != NULL) { -+ res |= update_computer_attribute (enroll, ldap, mods); -+ ldap_mods_free (mods, 1); -+ } -+ } -+ - if (res != 0) - _adcli_info ("Updated existing computer account: %s", enroll->computer_dn); - } -@@ -2751,6 +2828,7 @@ enroll_free (adcli_enroll *enroll) - free (enroll->user_principal); - _adcli_strv_free (enroll->service_names); - _adcli_strv_free (enroll->service_principals); -+ _adcli_strv_free (enroll->setattr); - _adcli_password_free (enroll->computer_password); - - adcli_enroll_set_keytab_name (enroll, NULL); -@@ -3332,6 +3410,72 @@ adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll, - return_if_fail (enroll->service_principals_to_remove != NULL); - } - -+static int comp_attr_name (const char *s1, const char *s2) -+{ -+ size_t c = 0; -+ -+ /* empty strings cannot contain an attribute name */ -+ if (s1 == NULL || s2 == NULL || *s1 == '\0' || *s2 == '\0') { -+ return 1; -+ } -+ -+ for (c = 0 ; s1[c] != '\0' && s2[c] != '\0'; c++) { -+ if (s1[c] == '=' && s2[c] == '=') { -+ return 0; -+ } else if (tolower (s1[c]) != tolower (s2[c])) { -+ return 1; -+ } -+ } -+ -+ return 1; -+} -+ -+adcli_result -+adcli_enroll_add_setattr (adcli_enroll *enroll, const char *value) -+{ -+ char *delim; -+ -+ return_val_if_fail (enroll != NULL, ADCLI_ERR_CONFIG); -+ return_val_if_fail (value != NULL, ADCLI_ERR_CONFIG); -+ -+ delim = strchr (value, '='); -+ if (delim == NULL) { -+ _adcli_err ("Missing '=' in setattr option [%s]", value); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ if (*(delim + 1) == '\0') { -+ _adcli_err ("Missing value in setattr option [%s]", value); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ *delim = '\0'; -+ if (_adcli_strv_has_ex (default_ad_ldap_attrs, value, strcasecmp) == 1) { -+ _adcli_err ("Attribute [%s] cannot be set with setattr", value); -+ return ADCLI_ERR_CONFIG; -+ } -+ *delim = '='; -+ -+ if (_adcli_strv_has_ex (enroll->setattr, value, comp_attr_name) == 1) { -+ _adcli_err ("Attribute [%s] already set", value); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ enroll->setattr = _adcli_strv_add (enroll->setattr, strdup (value), -+ NULL); -+ return_val_if_fail (enroll->setattr != NULL, ADCLI_ERR_CONFIG); -+ -+ return ADCLI_SUCCESS; -+} -+ -+const char ** -+adcli_enroll_get_setattr (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ return (const char **) enroll->setattr; -+} -+ -+ - #ifdef ADENROLL_TESTS - - #include "test.h" -@@ -3401,12 +3545,35 @@ test_adcli_enroll_get_permitted_keytab_enctypes (void) - adcli_conn_unref (conn); - } - -+static void -+test_comp_attr_name (void) -+{ -+ assert_num_eq (1, comp_attr_name (NULL ,NULL)); -+ assert_num_eq (1, comp_attr_name ("" ,NULL)); -+ assert_num_eq (1, comp_attr_name ("" ,"")); -+ assert_num_eq (1, comp_attr_name (NULL ,"")); -+ assert_num_eq (1, comp_attr_name (NULL ,"abc=xyz")); -+ assert_num_eq (1, comp_attr_name ("" ,"abc=xyz")); -+ assert_num_eq (1, comp_attr_name ("abc=xyz", NULL)); -+ assert_num_eq (1, comp_attr_name ("abc=xyz", "")); -+ assert_num_eq (1, comp_attr_name ("abc=xyz", "ab=xyz")); -+ assert_num_eq (1, comp_attr_name ("ab=xyz", "abc=xyz")); -+ assert_num_eq (1, comp_attr_name ("abcxyz", "abc=xyz")); -+ assert_num_eq (1, comp_attr_name ("abc=xyz", "abcxyz")); -+ assert_num_eq (1, comp_attr_name ("abc=xyz", "a")); -+ assert_num_eq (1, comp_attr_name ("a", "abc=xyz")); -+ -+ assert_num_eq (0, comp_attr_name ("abc=xyz", "abc=xyz")); -+ assert_num_eq (0, comp_attr_name ("abc=xyz", "abc=123")); -+} -+ - int - main (int argc, - char *argv[]) - { - test_func (test_adcli_enroll_get_permitted_keytab_enctypes, - "/attrs/adcli_enroll_get_permitted_keytab_enctypes"); -+ test_func (test_comp_attr_name, "/attrs/comp_attr_name"); - return test_run (argc, argv); - } - -diff --git a/library/adenroll.h b/library/adenroll.h -index 34dc683..862bb60 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -138,6 +138,10 @@ const char * adcli_enroll_get_desciption (adcli_enroll *enroll); - void adcli_enroll_set_description (adcli_enroll *enroll, - const char *value); - -+const char ** adcli_enroll_get_setattr (adcli_enroll *enroll); -+adcli_result adcli_enroll_add_setattr (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); -diff --git a/tools/computer.c b/tools/computer.c -index 16a1983..af38894 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -114,6 +114,7 @@ typedef enum { - opt_add_service_principal, - opt_remove_service_principal, - opt_description, -+ opt_setattr, - opt_use_ldaps, - } Option; - -@@ -152,6 +153,7 @@ static adcli_tool_desc common_usages[] = { - { 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_setattr, "add an attribute with a value\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" -@@ -333,6 +335,12 @@ parse_option (Option opt, - case opt_description: - adcli_enroll_set_description (enroll, optarg); - return ADCLI_SUCCESS; -+ case opt_setattr: -+ ret = adcli_enroll_add_setattr (enroll, optarg); -+ if (ret != ADCLI_SUCCESS) { -+ warnx ("parsing setattr option failed"); -+ } -+ return ret; - case opt_use_ldaps: - adcli_conn_set_use_ldaps (conn, true); - return ADCLI_SUCCESS; -@@ -401,6 +409,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "os-version", required_argument, NULL, opt_os_version }, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "description", optional_argument, NULL, opt_description }, -+ { "setattr", required_argument, NULL, opt_setattr }, - { "user-principal", optional_argument, NULL, opt_user_principal }, - { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation }, - { "dont-expire-password", required_argument, NULL, opt_dont_expire_password }, -@@ -524,6 +533,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "os-version", required_argument, NULL, opt_os_version }, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "description", optional_argument, NULL, opt_description }, -+ { "setattr", required_argument, NULL, opt_setattr }, - { "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.31.1 - diff --git a/SOURCES/0001-Do-not-use-arcfour-hmac-md5-when-discovering-the-sal.patch b/SOURCES/0001-Do-not-use-arcfour-hmac-md5-when-discovering-the-sal.patch deleted file mode 100644 index 4c2323c..0000000 --- a/SOURCES/0001-Do-not-use-arcfour-hmac-md5-when-discovering-the-sal.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 158468507bb723aa62196846749c23c121d4b298 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 8 Apr 2019 10:55:39 +0200 -Subject: [PATCH] Do not use arcfour-hmac-md5 when discovering the salt - -Since the arcfour-hmac-md5 encryption types does not use salts it cannot -be used to discover the right salt. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1683745 ---- - library/adkrb5.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/library/adkrb5.c b/library/adkrb5.c -index da835d7..be3ede5 100644 ---- a/library/adkrb5.c -+++ b/library/adkrb5.c -@@ -395,15 +395,33 @@ _adcli_krb5_keytab_discover_salt (krb5_context k5, - krb5_keytab scratch; - krb5_error_code code; - int i; -+ krb5_enctype *salt_enctypes = NULL; -+ size_t c; -+ size_t s; - - /* TODO: This should be a unique name */ - - code = krb5_kt_resolve (k5, "MEMORY:adcli-discover-salt", &scratch); - return_val_if_fail (code == 0, code); - -+ for (c = 0; enctypes[c] != 0; c++); /* count enctypes */ -+ salt_enctypes = calloc (c + 1, sizeof (krb5_enctype)); -+ return_val_if_fail (salt_enctypes != NULL, ENOMEM); -+ -+ /* ENCTYPE_ARCFOUR_HMAC does not use salts, so it cannot be used to -+ * discover the right salt. */ -+ s = 0; -+ for (c = 0; enctypes[c] != 0; c++) { -+ if (enctypes[c] == ENCTYPE_ARCFOUR_HMAC) { -+ continue; -+ } -+ -+ salt_enctypes[s++] = enctypes[c]; -+ } -+ - for (i = 0; salts[i].data != NULL; i++) { - code = _adcli_krb5_keytab_test_salt (k5, scratch, principal, kvno, -- password, enctypes, &salts[i]); -+ password, salt_enctypes, &salts[i]); - if (code == 0) { - *discovered = i; - break; -@@ -412,6 +430,7 @@ _adcli_krb5_keytab_discover_salt (krb5_context k5, - } - } - -+ free (salt_enctypes); - krb5_kt_close (k5, scratch); - return code; - } --- -2.21.0 - diff --git a/SOURCES/0001-Fix-for-dont-expire-password-option-and-join.patch b/SOURCES/0001-Fix-for-dont-expire-password-option-and-join.patch deleted file mode 100644 index 9740f31..0000000 --- a/SOURCES/0001-Fix-for-dont-expire-password-option-and-join.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 924465af7a4f37390bfdfdb4971e88421f52f3d9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 3 Jun 2021 15:03:20 +0200 -Subject: [PATCH] Fix for dont-expire-password option and join - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1769644 ---- - library/adenroll.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index f3d606e..5b0dcd5 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -856,7 +856,8 @@ create_computer_account (adcli_enroll *enroll, - uac |= UAC_TRUSTED_FOR_DELEGATION; - } - -- if (!adcli_enroll_get_dont_expire_password (enroll)) { -+ if (enroll->dont_expire_password_explicit -+ && !adcli_enroll_get_dont_expire_password (enroll)) { - uac &= ~(UAC_DONT_EXPIRE_PASSWORD); - } - --- -2.31.1 - diff --git a/SOURCES/0001-Fix-for-issue-found-by-Coverity.patch b/SOURCES/0001-Fix-for-issue-found-by-Coverity.patch deleted file mode 100644 index b5159c8..0000000 --- a/SOURCES/0001-Fix-for-issue-found-by-Coverity.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5da6d34e2659f915e830932fd366c635801ecd91 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 12 Aug 2019 17:28:20 +0200 -Subject: [PATCH] Fix for issue found by Coverity - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/3 ---- - library/adenroll.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 53cd812..524663a 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -2681,7 +2681,10 @@ adcli_enroll_get_permitted_keytab_enctypes (adcli_enroll *enroll) - for (c = 0; cur_enctypes[c] != 0; c++); - - new_enctypes = calloc (c + 1, sizeof (krb5_enctype)); -- return_val_if_fail (new_enctypes != NULL, NULL); -+ if (new_enctypes == NULL) { -+ krb5_free_enctypes (k5, permitted_enctypes); -+ return NULL; -+ } - - n = 0; - for (c = 0; cur_enctypes[c] != 0; c++) { --- -2.21.0 - diff --git a/SOURCES/0001-Fix-for-issues-found-by-Coverity.patch b/SOURCES/0001-Fix-for-issues-found-by-Coverity.patch deleted file mode 100644 index c7e698e..0000000 --- a/SOURCES/0001-Fix-for-issues-found-by-Coverity.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 3c93c96eb6ea2abd3869921ee4c89e1a4d9e4c44 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 14 Aug 2018 13:08:52 +0200 -Subject: [PATCH] Fix for issues found by Coverity - ---- - library/adenroll.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 02bd9e3..de2242a 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1575,7 +1575,7 @@ load_host_keytab (adcli_enroll *enroll) - } - - krb5_free_context (k5); -- return ADCLI_SUCCESS; -+ return res; - } - - typedef struct { -@@ -1756,12 +1756,12 @@ add_principal_to_keytab (adcli_enroll *enroll, - enroll->kvno, &password, enctypes, &salts[*which_salt]); - - free_principal_salts (k5, salts); -+ } - -- if (code != 0) { -- _adcli_err ("Couldn't add keytab entries: %s: %s", -- enroll->keytab_name, krb5_get_error_message (k5, code)); -- return ADCLI_ERR_FAIL; -- } -+ if (code != 0) { -+ _adcli_err ("Couldn't add keytab entries: %s: %s", -+ enroll->keytab_name, krb5_get_error_message (k5, code)); -+ return ADCLI_ERR_FAIL; - } - - --- -2.21.0 - diff --git a/SOURCES/0001-Implement-adcli-testjoin.patch b/SOURCES/0001-Implement-adcli-testjoin.patch deleted file mode 100644 index d75cbf2..0000000 --- a/SOURCES/0001-Implement-adcli-testjoin.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 6fd99ff6c5dd6ef0be8d942989b1c6dcee3102d9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 22 Mar 2019 12:37:39 +0100 -Subject: [PATCH] Implement 'adcli testjoin' - -By calling adcli testjoin it will be checked if the host credentials -stored in the keytab are still valid. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1622583 ---- - doc/adcli.xml | 34 +++++++++++++++++++++++ - tools/computer.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ - tools/tools.c | 1 + - tools/tools.h | 4 +++ - 4 files changed, 111 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index af73433..9605b4a 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -43,6 +43,9 @@ - - adcli update - -+ -+ adcli testjoin -+ - - adcli create-user - --domain=domain.example.com -@@ -474,6 +477,37 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - - - -+ -+ Testing if the machine account password is valid -+ -+ adcli testjoin uses the current credentials in -+ the keytab and tries to authenticate with the machine account to the AD -+ domain. If this works the machine account password and the join are -+ still valid. If it fails the machine account password or the whole -+ machine account have to be refreshed with -+ adcli join or adcli update. -+ -+ -+ -+$ adcli testjoin -+ -+ -+ Only the global options not related to authentication are -+ available, additionally you can specify the following options to -+ control how this operation is done. -+ -+ -+ -+ -+ Specify the path to the host keytab where -+ current host credentials are stored and the new ones -+ will be written to. If not specified, the default -+ location will be used, usually -+ /etc/krb5.keytab. -+ -+ -+ -+ - - Creating a User - -diff --git a/tools/computer.c b/tools/computer.c -index 112340e..610ed2b 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -566,6 +566,78 @@ adcli_tool_computer_update (adcli_conn *conn, - return 0; - } - -+int -+adcli_tool_computer_testjoin (adcli_conn *conn, -+ int argc, -+ char *argv[]) -+{ -+ adcli_enroll *enroll; -+ adcli_result res; -+ const char *ktname; -+ int opt; -+ -+ struct option options[] = { -+ { "domain", required_argument, NULL, opt_domain }, -+ { "domain-controller", required_argument, NULL, opt_domain_controller }, -+ { "host-keytab", required_argument, 0, opt_host_keytab }, -+ { "verbose", no_argument, NULL, opt_verbose }, -+ { "help", no_argument, NULL, 'h' }, -+ { 0 }, -+ }; -+ -+ static adcli_tool_desc usages[] = { -+ { 0, "usage: adcli testjoin" }, -+ { 0 }, -+ }; -+ -+ enroll = adcli_enroll_new (conn); -+ if (enroll == NULL) -+ errx (-1, "unexpected memory problems"); -+ -+ while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { -+ switch (opt) { -+ case 'h': -+ case '?': -+ case ':': -+ adcli_tool_usage (options, usages); -+ adcli_tool_usage (options, common_usages); -+ adcli_enroll_unref (enroll); -+ return opt == 'h' ? 0 : 2; -+ default: -+ parse_option ((Option)opt, optarg, conn, enroll); -+ break; -+ } -+ } -+ -+ /* Force use of a keytab to test the join/machine account password */ -+ adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_COMPUTER_ACCOUNT); -+ ktname = adcli_enroll_get_keytab_name (enroll); -+ adcli_conn_set_login_keytab_name (conn, ktname ? ktname : ""); -+ -+ res = adcli_enroll_load (enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ adcli_conn_unref (conn); -+ errx (-res, "couldn't lookup domain info from keytab: %s", -+ adcli_get_last_error ()); -+ } -+ -+ res = adcli_conn_connect (conn); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ adcli_conn_unref (conn); -+ errx (-res, "couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ } -+ -+ printf ("Sucessfully validated join to domain %s\n", -+ adcli_conn_get_domain_name (conn)); -+ -+ adcli_enroll_unref (enroll); -+ -+ return 0; -+} - - int - adcli_tool_computer_preset (adcli_conn *conn, -diff --git a/tools/tools.c b/tools/tools.c -index 915130e..c4e2851 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -55,6 +55,7 @@ struct { - { "info", adcli_tool_info, "Print information about a domain", CONNECTION_LESS }, - { "join", adcli_tool_computer_join, "Join this machine to a domain", }, - { "update", adcli_tool_computer_update, "Update machine membership in a domain", }, -+ { "testjoin", adcli_tool_computer_testjoin, "Test if machine account password is valid", }, - { "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", }, - { "reset-computer", adcli_tool_computer_reset, "Reset a computer account", }, - { "delete-computer", adcli_tool_computer_delete, "Delete a computer account", }, -diff --git a/tools/tools.h b/tools/tools.h -index 6c97ccf..8cebbf9 100644 ---- a/tools/tools.h -+++ b/tools/tools.h -@@ -70,6 +70,10 @@ int adcli_tool_computer_update (adcli_conn *conn, - int argc, - char *argv[]); - -+int adcli_tool_computer_testjoin (adcli_conn *conn, -+ int argc, -+ char *argv[]); -+ - int adcli_tool_computer_delete (adcli_conn *conn, - int argc, - char *argv[]); --- -2.20.1 - diff --git a/SOURCES/0001-Increment-kvno-after-password-change-with-user-creds.patch b/SOURCES/0001-Increment-kvno-after-password-change-with-user-creds.patch deleted file mode 100644 index aeef509..0000000 --- a/SOURCES/0001-Increment-kvno-after-password-change-with-user-creds.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5cf1723c308e21cdbe9b98ed2aaa42cb997456fb Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 15 Mar 2019 14:31:12 +0100 -Subject: [PATCH] Increment kvno after password change with user creds - -Originally only the host credential part was fixed in the context of -https://bugs.freedesktop.org/show_bug.cgi?id=91185. This patch adds the -fix to the case when user credentials are used. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1642546 ---- - library/adenroll.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index e02f403..58362c2 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1057,6 +1057,10 @@ set_password_with_user_creds (adcli_enroll *enroll) - #endif - } else { - _adcli_info ("Set computer password"); -+ if (enroll->kvno > 0) { -+ enroll->kvno++; -+ _adcli_info ("kvno incremented to %d", enroll->kvno); -+ } - res = ADCLI_SUCCESS; - } - --- -2.20.1 - diff --git a/SOURCES/0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch b/SOURCES/0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch deleted file mode 100644 index f37f2f1..0000000 --- a/SOURCES/0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch +++ /dev/null @@ -1,216 +0,0 @@ -From 0a0d0f66409eb83e06b7dc50543c2f6c15a36bc4 Mon Sep 17 00:00:00 2001 -From: Alexey A Nikitin -Date: Mon, 29 Oct 2018 20:40:36 -0700 -Subject: [PATCH] Make 'adcli info' DC location mechanism more compliant with - [MS-ADTS] and [MS-NRPC] - -AD specifications say that DC locator must attempt to find a suitable DC for the client. That means going through all of the DCs in SRV RRs one by one until one of them answers. - -The problem with adcli's original behavior is that it queries only five DCs from SRV, ever. This becomes a problem if for any reason there is a large number of DCs in the domain from which the client cannot get a CLDAP response. ---- - library/addisco.c | 146 +++++++++++++++++++++++++++++----------------- - 1 file changed, 94 insertions(+), 52 deletions(-) - -diff --git a/library/addisco.c b/library/addisco.c -index 8cc5bf0..6e73ead 100644 ---- a/library/addisco.c -+++ b/library/addisco.c -@@ -41,8 +41,10 @@ - #include - #include - --/* Number of servers to do discovery against */ --#define DISCO_COUNT 5 -+/* Number of servers to do discovery against. -+ * For AD DS maximum number of DCs is 1200. -+ */ -+#define DISCO_COUNT 1200 - - /* The time period in which to do rapid requests */ - #define DISCO_FEVER 1 -@@ -453,6 +455,51 @@ parse_disco (LDAP *ldap, - return usability; - } - -+static int -+ldap_disco_poller (LDAP **ldap, -+ LDAPMessage **message, -+ adcli_disco **results, -+ const char **addrs) -+{ -+ int found = ADCLI_DISCO_UNUSABLE; -+ int close_ldap; -+ int parsed; -+ int ret = 0; -+ struct timeval tvpoll = { 0, 0 }; -+ -+ switch (ldap_result (*ldap, LDAP_RES_ANY, 1, &tvpoll, message)) { -+ case LDAP_RES_SEARCH_ENTRY: -+ case LDAP_RES_SEARCH_RESULT: -+ parsed = parse_disco (*ldap, *addrs, *message, results); -+ if (parsed > found) -+ found = parsed; -+ ldap_msgfree (*message); -+ close_ldap = 1; -+ break; -+ case -1: -+ ldap_get_option (*ldap, LDAP_OPT_RESULT_CODE, &ret); -+ close_ldap = 1; -+ break; -+ default: -+ ldap_msgfree (*message); -+ close_ldap = 0; -+ break; -+ } -+ -+ if (ret != LDAP_SUCCESS) { -+ _adcli_ldap_handle_failure (*ldap, ADCLI_ERR_CONFIG, -+ "Couldn't perform discovery search"); -+ } -+ -+ /* Done with this connection */ -+ if (close_ldap) { -+ ldap_unbind_ext_s (*ldap, NULL, NULL); -+ *ldap = NULL; -+ } -+ -+ return found; -+} -+ - static int - ldap_disco (const char *domain, - srvinfo *srv, -@@ -477,6 +524,7 @@ ldap_disco (const char *domain, - int num, i; - int ret; - int have_any = 0; -+ struct timeval interval; - - if (domain) { - value = _adcli_ldap_escape_filter (domain); -@@ -540,7 +588,6 @@ ldap_disco (const char *domain, - version = LDAP_VERSION3; - ldap_set_option (ldap[num], LDAP_OPT_PROTOCOL_VERSION, &version); - ldap_set_option (ldap[num], LDAP_OPT_REFERRALS , 0); -- _adcli_info ("Sending netlogon pings to domain controller: %s", url); - addrs[num] = srv->hostname; - have_any = 1; - num++; -@@ -555,70 +602,65 @@ ldap_disco (const char *domain, - freeaddrinfo (res); - } - -- /* Wait for the first response. Poor mans fd watch */ -- for (started = now = time (NULL); -- have_any && found != ADCLI_DISCO_USABLE && now < started + DISCO_TIME; -- now = time (NULL)) { -+ /* Initial send and short time wait */ -+ interval.tv_sec = 0; -+ for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) { -+ int parsed; -+ -+ if (NULL == ldap[i]) -+ continue; - -- struct timeval tvpoll = { 0, 0 }; -- struct timeval interval; -+ have_any = 1; -+ _adcli_info ("Sending NetLogon ping to domain controller: %s", addrs[i]); - -- /* If in the initial period, send feverishly */ -- if (now < started + DISCO_FEVER) { -- interval.tv_sec = 0; -- interval.tv_usec = 100 * 1000; -+ ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE, -+ filter, attrs, 0, NULL, NULL, NULL, -+ -1, &msgidp); -+ -+ if (ret != LDAP_SUCCESS) { -+ _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG, -+ "Couldn't perform discovery search"); -+ ldap_unbind_ext_s (ldap[i], NULL, NULL); -+ ldap[i] = NULL; -+ } -+ -+ /* From https://msdn.microsoft.com/en-us/library/ff718294.aspx first -+ * five DCs are given 0.4 seconds timeout, next five are given 0.2 -+ * seconds, and the rest are given 0.1 seconds -+ */ -+ if (i < 5) { -+ interval.tv_usec = 400000; -+ } else if (i < 10) { -+ interval.tv_usec = 200000; - } else { -- interval.tv_sec = 1; -- interval.tv_usec = 0; -+ interval.tv_usec = 100000; - } -+ select (0, NULL, NULL, NULL, &interval); -+ -+ parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i])); -+ if (parsed > found) -+ found = parsed; -+ } -+ -+ /* Wait some more until LDAP timeout (DISCO_TIME) */ -+ for (started = now = time (NULL); -+ have_any && ADCLI_DISCO_UNUSABLE == found && now < started + DISCO_TIME; -+ now = time (NULL)) { - - select (0, NULL, NULL, NULL, &interval); - - have_any = 0; -- for (i = 0; found != ADCLI_DISCO_USABLE && i < num; i++) { -- int close_ldap; -+ for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) { - int parsed; - - if (ldap[i] == NULL) - continue; - -- ret = 0; - have_any = 1; -- switch (ldap_result (ldap[i], LDAP_RES_ANY, 1, &tvpoll, &message)) { -- case LDAP_RES_SEARCH_ENTRY: -- case LDAP_RES_SEARCH_RESULT: -- parsed = parse_disco (ldap[i], addrs[i], message, results); -- if (parsed > found) -- found = parsed; -- ldap_msgfree (message); -- close_ldap = 1; -- break; -- case 0: -- ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE, -- filter, attrs, 0, NULL, NULL, NULL, -- -1, &msgidp); -- close_ldap = (ret != 0); -- break; -- case -1: -- ldap_get_option (ldap[i], LDAP_OPT_RESULT_CODE, &ret); -- close_ldap = 1; -- break; -- default: -- ldap_msgfree (message); -- close_ldap = 0; -- break; -- } -- -- if (ret != LDAP_SUCCESS) { -- _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG, -- "Couldn't perform discovery search"); -- } - -- /* Done with this connection */ -- if (close_ldap) { -- ldap_unbind_ext_s (ldap[i], NULL, NULL); -- ldap[i] = NULL; -- } -+ parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i])); -+ if (parsed > found) -+ found = parsed; - } - } - --- -2.26.2 - diff --git a/SOURCES/0001-Remove-upper-case-only-check-when-looking-for-the-Ne.patch b/SOURCES/0001-Remove-upper-case-only-check-when-looking-for-the-Ne.patch deleted file mode 100644 index 964c6bf..0000000 --- a/SOURCES/0001-Remove-upper-case-only-check-when-looking-for-the-Ne.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d8eb0f5704f34cb7d411cd275d32c63ead297b8d Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 24 Aug 2016 15:37:41 +0200 -Subject: [PATCH 01/23] Remove upper-case only check when looking for the - NetBIOS name - -It is a convention to use only upper-case letters for NetBIOS names but -it is not enforced on the AD-side. With the new option to specify a -random NetBIOS name it is possible to create host entries in AD with -lower-case letters in the name. To properly determine the name from the -keytab the upper-case check should be dropped,dc= ---- - library/adenroll.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index a15e4be..d1020e9 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1309,7 +1309,7 @@ load_keytab_entry (krb5_context k5, - if (!enroll->host_fqdn_explicit && !enroll->computer_name_explicit) { - - /* Automatically use the netbios name */ -- if (!enroll->computer_name && len > 1 && _adcli_str_is_up (name) && -+ if (!enroll->computer_name && len > 1 && - _adcli_str_has_suffix (name, "$") && !strchr (name, '/')) { - enroll->computer_name = name; - name[len - 1] = '\0'; --- -2.14.4 - diff --git a/SOURCES/0001-Use-GSS-SPNEGO-if-available.patch b/SOURCES/0001-Use-GSS-SPNEGO-if-available.patch deleted file mode 100644 index bae8b22..0000000 --- a/SOURCES/0001-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 1/2] 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.21.0 - diff --git a/SOURCES/0001-adenroll-make-sure-only-allowed-enctypes-are-used-in.patch b/SOURCES/0001-adenroll-make-sure-only-allowed-enctypes-are-used-in.patch deleted file mode 100644 index ad69b70..0000000 --- a/SOURCES/0001-adenroll-make-sure-only-allowed-enctypes-are-used-in.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 341974aae7d0755fc32a0b7e2b34d8e1ef60d195 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 20 Dec 2018 21:05:35 +0100 -Subject: [PATCH 1/4] adenroll: make sure only allowed enctypes are used in - FIPS mode - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1717355 ---- - library/adenroll.c | 36 +++++++++++++++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 52aa8a8..f617f28 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -41,11 +41,19 @@ - #include - #include - #include -+#include -+#include - - #ifndef SAMBA_DATA_TOOL - #define SAMBA_DATA_TOOL "/usr/bin/net" - #endif - -+static krb5_enctype v60_later_enctypes_fips[] = { -+ ENCTYPE_AES256_CTS_HMAC_SHA1_96, -+ ENCTYPE_AES128_CTS_HMAC_SHA1_96, -+ 0 -+}; -+ - static krb5_enctype v60_later_enctypes[] = { - ENCTYPE_AES256_CTS_HMAC_SHA1_96, - ENCTYPE_AES128_CTS_HMAC_SHA1_96, -@@ -2594,6 +2602,28 @@ adcli_enroll_set_keytab_name (adcli_enroll *enroll, - enroll->keytab_name_is_krb5 = 0; - } - -+#define PROC_SYS_FIPS "/proc/sys/crypto/fips_enabled" -+ -+static bool adcli_fips_enabled (void) -+{ -+ int fd; -+ ssize_t len; -+ char buf[8]; -+ -+ fd = open (PROC_SYS_FIPS, O_RDONLY); -+ if (fd != -1) { -+ len = read (fd, buf, sizeof (buf)); -+ close (fd); -+ /* Assume FIPS in enabled if PROC_SYS_FIPS contains a -+ * non-0 value. */ -+ if ( ! (len == 2 && buf[0] == '0' && buf[1] == '\n')) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ - krb5_enctype * - adcli_enroll_get_keytab_enctypes (adcli_enroll *enroll) - { -@@ -2602,7 +2632,11 @@ adcli_enroll_get_keytab_enctypes (adcli_enroll *enroll) - return enroll->keytab_enctypes; - - if (adcli_conn_server_has_capability (enroll->conn, ADCLI_CAP_V60_OID)) -- return v60_later_enctypes; -+ if (adcli_fips_enabled ()) { -+ return v60_later_enctypes_fips; -+ } else { -+ return v60_later_enctypes; -+ } - else - return v51_earlier_enctypes; - } --- -2.21.0 - diff --git a/SOURCES/0001-adutil-add-_adcli_strv_add_unique.patch b/SOURCES/0001-adutil-add-_adcli_strv_add_unique.patch deleted file mode 100644 index f49f5f8..0000000 --- a/SOURCES/0001-adutil-add-_adcli_strv_add_unique.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 85d127fd52a8469f9f3ce0d1130fe17e756fdd75 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 16 Nov 2018 13:32:33 +0100 -Subject: [PATCH 1/2] adutil: add _adcli_strv_add_unique - -_adcli_strv_add_unique checks is the new value already exists in the -strv before adding it. Check can be done case-sensitive or not. - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/16 ---- - library/adprivate.h | 5 ++++ - library/adutil.c | 65 ++++++++++++++++++++++++++++++++++++++------- - 2 files changed, 61 insertions(+), 9 deletions(-) - -diff --git a/library/adprivate.h b/library/adprivate.h -index bc9df6d..0806430 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -111,6 +111,11 @@ char ** _adcli_strv_add (char **strv, - char *string, - int *length) GNUC_WARN_UNUSED; - -+char ** _adcli_strv_add_unique (char **strv, -+ char *string, -+ int *length, -+ bool case_sensitive) GNUC_WARN_UNUSED; -+ - void _adcli_strv_remove_unsorted (char **strv, - const char *string, - int *length); -diff --git a/library/adutil.c b/library/adutil.c -index 17d2caa..76ea158 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -221,6 +221,34 @@ _adcli_strv_add (char **strv, - return seq_push (strv, length, string); - } - -+static int -+_adcli_strv_has_ex (char **strv, -+ const char *str, -+ int (* compare) (const char *match, const char*value)) -+{ -+ int i; -+ -+ for (i = 0; strv && strv[i] != NULL; i++) { -+ if (compare (strv[i], str) == 0) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+char ** -+_adcli_strv_add_unique (char **strv, -+ char *string, -+ int *length, -+ bool case_sensitive) -+{ -+ if (_adcli_strv_has_ex (strv, string, case_sensitive ? strcmp : strcasecmp) == 1) { -+ return strv; -+ } -+ -+ return _adcli_strv_add (strv, string, length); -+} -+ - #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) - - void -@@ -241,19 +269,11 @@ _adcli_strv_remove_unsorted (char **strv, - (seq_compar)strcasecmp, free); - } - -- - int - _adcli_strv_has (char **strv, - const char *str) - { -- int i; -- -- for (i = 0; strv && strv[i] != NULL; i++) { -- if (strcmp (strv[i], str) == 0) -- return 1; -- } -- -- return 0; -+ return _adcli_strv_has_ex (strv, str, strcmp); - } - - void -@@ -704,6 +724,32 @@ test_strv_add_free (void) - _adcli_strv_free (strv); - } - -+static void -+test_strv_add_unique_free (void) -+{ -+ char **strv = NULL; -+ -+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("tWo"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false); -+ strv = _adcli_strv_add_unique (strv, strdup ("TWO"), NULL, true); -+ -+ assert_num_eq (_adcli_strv_len (strv), 4); -+ -+ assert_str_eq (strv[0], "one"); -+ assert_str_eq (strv[1], "two"); -+ assert_str_eq (strv[2], "three"); -+ assert_str_eq (strv[3], "TWO"); -+ assert (strv[4] == NULL); -+ -+ _adcli_strv_free (strv); -+} -+ -+ - static void - test_strv_dup (void) - { -@@ -856,6 +902,7 @@ main (int argc, - char *argv[]) - { - test_func (test_strv_add_free, "/util/strv_add_free"); -+ test_func (test_strv_add_unique_free, "/util/strv_add_unique_free"); - test_func (test_strv_dup, "/util/strv_dup"); - test_func (test_strv_count, "/util/strv_count"); - test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime"); --- -2.20.1 - diff --git a/SOURCES/0001-build-add-with-vendor-error-message-configure-option.patch b/SOURCES/0001-build-add-with-vendor-error-message-configure-option.patch deleted file mode 100644 index 75235ee..0000000 --- a/SOURCES/0001-build-add-with-vendor-error-message-configure-option.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0353d704879f20983184f8bded4f16538d72f7cc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 10 Mar 2021 18:12:09 +0100 -Subject: [PATCH] build: add --with-vendor-error-message configure option - -With the new configure option --with-vendor-error-message a packager or -a distribution can add a message if adcli returns with an error. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1889386 ---- - configure.ac | 15 +++++++++++++++ - tools/tools.c | 6 ++++++ - 2 files changed, 21 insertions(+) - -diff --git a/configure.ac b/configure.ac -index baa0d3b..7dfba97 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -123,6 +123,21 @@ if test "$sasl_invalid" = "yes"; then - AC_MSG_ERROR([Couldn't find Cyrus SASL headers]) - fi - -+# -------------------------------------------------------------------- -+# Vendor error message -+ -+AC_ARG_WITH([vendor-error-message], -+ [AS_HELP_STRING([--with-vendor-error-message=ARG], -+ [Add a vendor specific error message shown if a adcli command fails] -+ )], -+ [AS_IF([test "x$withval" != "x"], -+ [AC_DEFINE_UNQUOTED([VENDOR_MSG], -+ ["$withval"], -+ [Vendor specific error message])], -+ [AC_MSG_ERROR([--with-vendor-error-message requires an argument])] -+ )], -+ []) -+ - # -------------------------------------------------------------------- - # Documentation options - -diff --git a/tools/tools.c b/tools/tools.c -index d0dcf98..84bbba9 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -538,6 +538,12 @@ main (int argc, - - if (conn) - adcli_conn_unref (conn); -+#ifdef VENDOR_MSG -+ if (ret != 0) { -+ fprintf (stderr, VENDOR_MSG"\n"); -+ } -+#endif -+ - return ret; - } - --- -2.30.2 - diff --git a/SOURCES/0001-coverity-add-missing-NULL-checks.patch b/SOURCES/0001-coverity-add-missing-NULL-checks.patch deleted file mode 100644 index 2f41992..0000000 --- a/SOURCES/0001-coverity-add-missing-NULL-checks.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 13fe79c0a78028ccfe8e3d4e5ee16cfb9e143924 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 2 Jun 2021 13:39:31 +0200 -Subject: [PATCH 1/2] coverity: add missing NULL checks - ---- - library/adenroll.c | 2 ++ - library/adldap.c | 7 +++++++ - 2 files changed, 9 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index f693e58..c726093 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -3046,6 +3046,8 @@ adcli_enroll_set_keytab_enctypes (adcli_enroll *enroll, - krb5_enctype *newval = NULL; - int len; - -+ return_if_fail (enroll != NULL); -+ - if (value) { - for (len = 0; value[len] != 0; len++); - newval = malloc (sizeof (krb5_enctype) * (len + 1)); -diff --git a/library/adldap.c b/library/adldap.c -index d93efb7..b86014c 100644 ---- a/library/adldap.c -+++ b/library/adldap.c -@@ -231,6 +231,13 @@ _adcli_ldap_have_in_mod (LDAPMod *mod, - - vals = malloc (sizeof (struct berval) * (count + 1)); - pvals = malloc (sizeof (struct berval *) * (count + 1)); -+ if (vals == NULL || pvals == NULL) { -+ _adcli_err ("Memory allocation failed, assuming attribute must be updated."); -+ free (vals); -+ free (pvals); -+ return 0; -+ } -+ - for (i = 0; i < count; i++) { - vals[i].bv_val = mod->mod_vals.modv_strvals[i]; - vals[i].bv_len = strlen (vals[i].bv_val); --- -2.31.1 - diff --git a/SOURCES/0001-create-user-add-nis-domain-option.patch b/SOURCES/0001-create-user-add-nis-domain-option.patch deleted file mode 100644 index 32b0ca9..0000000 --- a/SOURCES/0001-create-user-add-nis-domain-option.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 1457b4a7623a8ae58fb8d6a652d1cc44904b8863 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 18 Mar 2019 11:02:57 +0100 -Subject: [PATCH 1/2] create-user: add nis-domain option - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/2 ---- - doc/adcli.xml | 8 ++++++++ - tools/entry.c | 6 ++++++ - 2 files changed, 14 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 4722c3a..18620c0 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -531,6 +531,14 @@ $ adcli create-user Fry --domain=domain.example.com \ - the new created user account, which should be the user's - numeric primary user id. - -+ -+ -+ Set the msSFU30NisDomain attribute of -+ the new created user account, which should be the user's -+ NIS domain is the NIS/YP service of Active Directory's Services for Unix (SFU) -+ are used. This is needed to let the 'UNIX attributes' tab of older Active -+ Directoy versions show the set UNIX specific attributes. -+ - - - -diff --git a/tools/entry.c b/tools/entry.c -index 7b6a200..69ce62c 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -52,6 +52,7 @@ typedef enum { - opt_unix_uid, - opt_unix_gid, - opt_unix_shell, -+ opt_nis_domain, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -62,6 +63,7 @@ static adcli_tool_desc common_usages[] = { - { opt_unix_uid, "unix uid number" }, - { opt_unix_gid, "unix gid number" }, - { opt_unix_shell, "unix shell" }, -+ { opt_nis_domain, "NIS domain" }, - { opt_domain, "active directory domain name" }, - { opt_domain_realm, "kerberos realm for the domain" }, - { opt_domain_controller, "domain directory server to connect to" }, -@@ -159,6 +161,7 @@ adcli_tool_user_create (adcli_conn *conn, - { "unix-uid", required_argument, NULL, opt_unix_uid }, - { "unix-gid", required_argument, NULL, opt_unix_gid }, - { "unix-shell", required_argument, NULL, opt_unix_shell }, -+ { "nis-domain", required_argument, NULL, opt_nis_domain }, - { "domain-ou", required_argument, NULL, opt_domain_ou }, - { "domain", required_argument, NULL, opt_domain }, - { "domain-realm", required_argument, NULL, opt_domain_realm }, -@@ -200,6 +203,9 @@ adcli_tool_user_create (adcli_conn *conn, - case opt_unix_shell: - adcli_attrs_add (attrs, "loginShell", optarg, NULL); - break; -+ case opt_nis_domain: -+ adcli_attrs_add (attrs, "msSFU30NisDomain", optarg, NULL); -+ break; - case opt_domain_ou: - ou = optarg; - break; --- -2.20.1 - diff --git a/SOURCES/0001-delete-do-not-exit-if-keytab-cannot-be-read.patch b/SOURCES/0001-delete-do-not-exit-if-keytab-cannot-be-read.patch deleted file mode 100644 index 15aaf07..0000000 --- a/SOURCES/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/SOURCES/0001-discovery-fix.patch b/SOURCES/0001-discovery-fix.patch deleted file mode 100644 index 7c1018d..0000000 --- a/SOURCES/0001-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] 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.26.2 - diff --git a/SOURCES/0001-doc-add-missing-samba_data_tool_path.xml-.in-to-EXTR.patch b/SOURCES/0001-doc-add-missing-samba_data_tool_path.xml-.in-to-EXTR.patch deleted file mode 100644 index 7fc04d3..0000000 --- a/SOURCES/0001-doc-add-missing-samba_data_tool_path.xml-.in-to-EXTR.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 2edc26afda17db1a92703deb16658e9de9f79e14 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 3 Sep 2019 14:39:37 +0200 -Subject: [PATCH] doc: add missing samba_data_tool_path.xml(.in) to EXTRA_DIST - ---- - doc/Makefile.am | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/doc/Makefile.am b/doc/Makefile.am -index 3a53843..4490688 100644 ---- a/doc/Makefile.am -+++ b/doc/Makefile.am -@@ -31,6 +31,8 @@ EXTRA_DIST = \ - static \ - version.xml.in \ - version.xml \ -+ samba_data_tool_path.xml.in \ -+ samba_data_tool_path.xml \ - $(NULL) - - CLEANFILES = \ --- -2.28.0 - diff --git a/SOURCES/0001-doc-explain-how-to-force-password-reset.patch b/SOURCES/0001-doc-explain-how-to-force-password-reset.patch deleted file mode 100644 index f3d25f4..0000000 --- a/SOURCES/0001-doc-explain-how-to-force-password-reset.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 9b187095edb8c914238419ed51fef6041864f4fc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 26 Aug 2019 13:33:24 +0200 -Subject: [PATCH] doc: explain how to force password reset - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1738573 ---- - doc/adcli.xml | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 094f577..4f201e0 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -330,7 +330,11 @@ Password for Administrator: - 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.21.0 - diff --git a/SOURCES/0001-doc-explain-required-AD-permissions.patch b/SOURCES/0001-doc-explain-required-AD-permissions.patch deleted file mode 100644 index fe0826a..0000000 --- a/SOURCES/0001-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] 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/SOURCES/0001-enroll-add-is_service-member.patch b/SOURCES/0001-enroll-add-is_service-member.patch deleted file mode 100644 index 0a5129a..0000000 --- a/SOURCES/0001-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 1/7] 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/SOURCES/0001-ensure_keytab_principals-do-not-leak-memory-when-cal.patch b/SOURCES/0001-ensure_keytab_principals-do-not-leak-memory-when-cal.patch deleted file mode 100644 index dfdf745..0000000 --- a/SOURCES/0001-ensure_keytab_principals-do-not-leak-memory-when-cal.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 3a84c2469c31967bc22c0490456f07723ef5fc86 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 20 Mar 2019 11:01:50 +0100 -Subject: [PATCH 1/4] ensure_keytab_principals: do not leak memory when called - twice - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187 ---- - library/adenroll.c | 32 +++++++++++++++++++++----------- - 1 file changed, 21 insertions(+), 11 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index d1f746c..48cb4cf 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -413,6 +413,25 @@ ensure_service_principals (adcli_result res, - return res; - } - -+static void enroll_clear_keytab_principals (adcli_enroll *enroll) -+{ -+ krb5_context k5; -+ size_t c; -+ -+ if (enroll->keytab_principals) { -+ k5 = adcli_conn_get_krb5_context (enroll->conn); -+ return_if_fail (k5 != NULL); -+ -+ for (c = 0; enroll->keytab_principals[c] != NULL; c++) -+ krb5_free_principal (k5, enroll->keytab_principals[c]); -+ -+ free (enroll->keytab_principals); -+ enroll->keytab_principals = NULL; -+ } -+ -+ return; -+} -+ - static adcli_result - ensure_keytab_principals (adcli_result res, - adcli_enroll *enroll) -@@ -430,6 +449,7 @@ ensure_keytab_principals (adcli_result res, - k5 = adcli_conn_get_krb5_context (enroll->conn); - return_unexpected_if_fail (k5 != NULL); - -+ enroll_clear_keytab_principals (enroll); - enroll->keytab_principals = calloc (count + 3, sizeof (krb5_principal)); - return_unexpected_if_fail (enroll->keytab_principals != NULL); - at = 0; -@@ -1860,18 +1880,8 @@ static void - enroll_clear_state (adcli_enroll *enroll) - { - krb5_context k5; -- int i; -- -- if (enroll->keytab_principals) { -- k5 = adcli_conn_get_krb5_context (enroll->conn); -- return_if_fail (k5 != NULL); -- -- for (i = 0; enroll->keytab_principals[i] != NULL; i++) -- krb5_free_principal (k5, enroll->keytab_principals[i]); - -- free (enroll->keytab_principals); -- enroll->keytab_principals = NULL; -- } -+ enroll_clear_keytab_principals (enroll); - - if (enroll->keytab) { - k5 = adcli_conn_get_krb5_context (enroll->conn); --- -2.20.1 - diff --git a/SOURCES/0001-fix-typo-in-flag-value.patch b/SOURCES/0001-fix-typo-in-flag-value.patch deleted file mode 100644 index 07577b7..0000000 --- a/SOURCES/0001-fix-typo-in-flag-value.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 870ecd8f982ebb97092a93d730ad4006bd78505c Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 8 Aug 2018 12:03:01 +0200 -Subject: [PATCH 1/4] fix typo in flag value - ---- - library/adenroll.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/adenroll.h b/library/adenroll.h -index f87dffa..abbbfd4 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -30,7 +30,7 @@ typedef enum { - ADCLI_ENROLL_NO_KEYTAB = 1 << 1, - ADCLI_ENROLL_ALLOW_OVERWRITE = 1 << 2, - ADCLI_ENROLL_PASSWORD_VALID = 1 << 3, -- ADCLI_ENROLL_ADD_SAMBA_DATA = 1 << 3, -+ ADCLI_ENROLL_ADD_SAMBA_DATA = 1 << 4, - } adcli_enroll_flags; - - typedef struct _adcli_enroll adcli_enroll; --- -2.17.1 - diff --git a/SOURCES/0001-join-always-add-service-principals.patch b/SOURCES/0001-join-always-add-service-principals.patch deleted file mode 100644 index 0281dc6..0000000 --- a/SOURCES/0001-join-always-add-service-principals.patch +++ /dev/null @@ -1,86 +0,0 @@ -From cd296bf24e7cc56fb8d00bad7e9a56c539894309 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 19 Mar 2019 20:44:36 +0100 -Subject: [PATCH 1/2] join: always add service principals - -If currently --service-name is given during the join only the service -names given by this option are added as service principal names. As a -result the default 'host' service principal name might be missing which -might cause issues e.g. with SSSD and sshd. - -The patch makes sure the default service principals 'host' and -'RestrictedKrbHost' are always added during join. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1644311 ---- - library/adenroll.c | 36 ++++++++++++++++++++++++++++++------ - 1 file changed, 30 insertions(+), 6 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 58362c2..d1f746c 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -288,16 +288,23 @@ ensure_computer_password (adcli_result res, - } - - static adcli_result --ensure_service_names (adcli_result res, -- adcli_enroll *enroll) -+ensure_default_service_names (adcli_enroll *enroll) - { - int length = 0; - -- if (res != ADCLI_SUCCESS) -- return res; -+ if (enroll->service_names != NULL) { -+ length = seq_count (enroll->service_names); - -- if (enroll->service_names || enroll->service_principals) -- return ADCLI_SUCCESS; -+ /* Make sure there is no entry with an unexpected case. AD -+ * would not care but since the client side is case-sensitive -+ * we should make sure we use the expected spelling. */ -+ seq_remove_unsorted (enroll->service_names, -+ &length, "host", -+ (seq_compar)strcasecmp, free); -+ seq_remove_unsorted (enroll->service_names, -+ &length, "RestrictedKrbHost", -+ (seq_compar)strcasecmp, free); -+ } - - /* The default ones specified by MS */ - enroll->service_names = _adcli_strv_add (enroll->service_names, -@@ -307,6 +314,19 @@ ensure_service_names (adcli_result res, - return ADCLI_SUCCESS; - } - -+static adcli_result -+ensure_service_names (adcli_result res, -+ adcli_enroll *enroll) -+{ -+ if (res != ADCLI_SUCCESS) -+ return res; -+ -+ if (enroll->service_names || enroll->service_principals) -+ return ADCLI_SUCCESS; -+ -+ return ensure_default_service_names (enroll); -+} -+ - static adcli_result - add_service_names_to_service_principals (adcli_enroll *enroll) - { -@@ -2039,6 +2059,10 @@ adcli_enroll_join (adcli_enroll *enroll, - if (res != ADCLI_SUCCESS) - return res; - -+ res = ensure_default_service_names (enroll); -+ if (res != ADCLI_SUCCESS) -+ return res; -+ - res = adcli_enroll_prepare (enroll, flags); - if (res != ADCLI_SUCCESS) - return res; --- -2.20.1 - diff --git a/SOURCES/0001-join-update-set-dNSHostName-if-not-set.patch b/SOURCES/0001-join-update-set-dNSHostName-if-not-set.patch deleted file mode 100644 index a27653e..0000000 --- a/SOURCES/0001-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] 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/SOURCES/0001-library-add-missing-strdup.patch b/SOURCES/0001-library-add-missing-strdup.patch deleted file mode 100644 index 378bb3c..0000000 --- a/SOURCES/0001-library-add-missing-strdup.patch +++ /dev/null @@ -1,34 +0,0 @@ -From a64cce9830c2e9c26e120f671b247ee71b45c888 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 12 Apr 2019 17:31:41 +0200 -Subject: [PATCH] library: add missing strdup - -In add_server_side_service_principals _adcli_strv_add_unique is called -which only adds a string to a list without copying to. Since the -original list will be freed later the value must be copied. - -This issue was introduce with 972f1a2f35829ed89f5353bd204683aa9ad6a2d2 -and hence - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187 ---- - library/adenroll.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 1cce86a..52aa8a8 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1987,7 +1987,8 @@ add_server_side_service_principals (adcli_enroll *enroll) - _adcli_info ("Checking %s", spn_list[c]); - if (!_adcli_strv_has_ex (enroll->service_principals_to_remove, spn_list[c], strcasecmp)) { - enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, -- spn_list[c], &length, false); -+ strdup (spn_list[c]), -+ &length, false); - assert (enroll->service_principals != NULL); - _adcli_info (" Added %s", spn_list[c]); - } --- -2.20.1 - diff --git a/SOURCES/0001-library-move-UAC-flags-to-a-more-common-header-file.patch b/SOURCES/0001-library-move-UAC-flags-to-a-more-common-header-file.patch deleted file mode 100644 index 0129517..0000000 --- a/SOURCES/0001-library-move-UAC-flags-to-a-more-common-header-file.patch +++ /dev/null @@ -1,50 +0,0 @@ -From a7a40ce4f47fe40305624b6d86c135b7d27c387d Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 11 Jun 2021 12:44:36 +0200 -Subject: [PATCH 1/3] library: move UAC flags to a more common header file - ---- - library/adenroll.c | 8 -------- - library/adprivate.h | 8 ++++++++ - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index f00d179..0b1c066 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -93,13 +93,6 @@ static char *default_ad_ldap_attrs[] = { - 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. */ --#define UAC_WORKSTATION_TRUST_ACCOUNT 0x1000 --#define UAC_DONT_EXPIRE_PASSWORD 0x10000 --#define UAC_TRUSTED_FOR_DELEGATION 0x80000 -- - struct _adcli_enroll { - int refs; - adcli_conn *conn; -diff --git a/library/adprivate.h b/library/adprivate.h -index 55e6234..822f919 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -39,6 +39,14 @@ - #define HOST_NAME_MAX 255 - #endif - -+/* 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. */ -+#define UAC_ACCOUNTDISABLE 0x0002 -+#define UAC_WORKSTATION_TRUST_ACCOUNT 0x1000 -+#define UAC_DONT_EXPIRE_PASSWORD 0x10000 -+#define UAC_TRUSTED_FOR_DELEGATION 0x80000 -+ - /* Utilities */ - - #if !defined(__cplusplus) && (__GNUC__ > 2) --- -2.31.1 - diff --git a/SOURCES/0001-library-use-getaddrinfo-with-AI_CANONNAME-to-find-a-.patch b/SOURCES/0001-library-use-getaddrinfo-with-AI_CANONNAME-to-find-a-.patch deleted file mode 100644 index c682c5a..0000000 --- a/SOURCES/0001-library-use-getaddrinfo-with-AI_CANONNAME-to-find-a-.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 85b835f8258a57e3b23de47a255dddd822d5bfb3 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 15 Mar 2019 17:33:44 +0100 -Subject: [PATCH] library: use getaddrinfo with AI_CANONNAME to find a FQDN - -Currently adcli creates service principals only with a short name if the -hostname of the client is a short name. This would fail is -Kerberos/GSSAPI clients will use the fully-qualified domain name (FQDN) -to access the host. - -With this patch adcli tries to expand the short name by calling -getaddrinfo with the AI_CANONNAME hint. - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/1 ---- - doc/adcli.xml | 6 +++++- - library/adconn.c | 30 +++++++++++++++++++++++++++++- - 2 files changed, 34 insertions(+), 2 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 97dec08..4722c3a 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -228,7 +228,11 @@ Password for Administrator: - - Override the local machine's fully qualified - domain name. If not specified, the local machine's hostname -- will be retrieved via gethostname(). -+ 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 domain -+ name. - - - -diff --git a/library/adconn.c b/library/adconn.c -index e2250e3..f6c23d3 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -86,11 +86,36 @@ struct _adcli_conn_ctx { - krb5_keytab keytab; - }; - -+static char *try_to_get_fqdn (const char *host_name) -+{ -+ int ret; -+ char *fqdn = NULL; -+ struct addrinfo *res; -+ struct addrinfo hints; -+ -+ memset (&hints, 0, sizeof (struct addrinfo)); -+ hints.ai_socktype = SOCK_DGRAM; -+ hints.ai_flags = AI_CANONNAME; -+ -+ ret = getaddrinfo (host_name, NULL, &hints, &res); -+ if (ret != 0) { -+ _adcli_err ("Failed to find FQDN: %s", gai_strerror (ret)); -+ return NULL; -+ } -+ -+ fqdn = strdup (res->ai_canonname); -+ -+ freeaddrinfo (res); -+ -+ return fqdn; -+} -+ - static adcli_result - ensure_host_fqdn (adcli_result res, - adcli_conn *conn) - { - char hostname[HOST_NAME_MAX + 1]; -+ char *fqdn = NULL; - int ret; - - if (res != ADCLI_SUCCESS) -@@ -107,7 +132,10 @@ ensure_host_fqdn (adcli_result res, - return ADCLI_ERR_UNEXPECTED; - } - -- conn->host_fqdn = strdup (hostname); -+ if (strchr (hostname, '.') == NULL) { -+ fqdn = try_to_get_fqdn (hostname); -+ } -+ conn->host_fqdn = fqdn != NULL ? fqdn : strdup (hostname); - return_unexpected_if_fail (conn->host_fqdn != NULL); - return ADCLI_SUCCESS; - } --- -2.20.1 - diff --git a/SOURCES/0001-man-explain-optional-parameter-of-login-ccache-bette.patch b/SOURCES/0001-man-explain-optional-parameter-of-login-ccache-bette.patch deleted file mode 100644 index 191fa3e..0000000 --- a/SOURCES/0001-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] 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/SOURCES/0001-man-make-handling-of-optional-credential-cache-more-.patch b/SOURCES/0001-man-make-handling-of-optional-credential-cache-more-.patch deleted file mode 100644 index 3d5955a..0000000 --- a/SOURCES/0001-man-make-handling-of-optional-credential-cache-more-.patch +++ /dev/null @@ -1,41 +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] 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/SOURCES/0001-man-move-note-to-the-right-section.patch b/SOURCES/0001-man-move-note-to-the-right-section.patch deleted file mode 100644 index 307dfc9..0000000 --- a/SOURCES/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] 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.21.0 - diff --git a/SOURCES/0001-service-account-fix-typo-in-the-man-page-entry.patch b/SOURCES/0001-service-account-fix-typo-in-the-man-page-entry.patch deleted file mode 100644 index b476a93..0000000 --- a/SOURCES/0001-service-account-fix-typo-in-the-man-page-entry.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 637cc53953ef61c90530ae5eaf26eb4911336465 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 10 Dec 2020 18:29:18 +0100 -Subject: [PATCH] service-account: fix typo in the man page entry - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1906303 ---- - doc/adcli.xml | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 14921f9..a64687a 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -943,7 +943,7 @@ Password for Administrator: - 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. -+ /etc/krb5.keytab.domain.example.com. - - adcli create-msa can be called multiple - times to reset the password of the managed service account. To identify -@@ -955,7 +955,7 @@ Password for Administrator: - - The managed service account password can be updated with - --$ adcli update --domain=domain.example.com --host-keytab=/etc/krb5.keytad.domain.example.com -+$ adcli update --domain=domain.example.com --host-keytab=/etc/krb5.keytab.domain.example.com - - and the managed service account can be deleted with - --- -2.29.2 - diff --git a/SOURCES/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch b/SOURCES/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch deleted file mode 100644 index a62fbe6..0000000 --- a/SOURCES/0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch +++ /dev/null @@ -1,36 +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] 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/SOURCES/0001-tools-add-show-computer-command.patch b/SOURCES/0001-tools-add-show-computer-command.patch deleted file mode 100644 index 1decaf6..0000000 --- a/SOURCES/0001-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 1/2] 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.21.0 - diff --git a/SOURCES/0001-tools-disable-SSSD-s-locator-plugin.patch b/SOURCES/0001-tools-disable-SSSD-s-locator-plugin.patch deleted file mode 100644 index 07d791e..0000000 --- a/SOURCES/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/SOURCES/0001-tools-fix-typo-in-show-password-help-output.patch b/SOURCES/0001-tools-fix-typo-in-show-password-help-output.patch deleted file mode 100644 index d82d49c..0000000 --- a/SOURCES/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] 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/SOURCES/0001-tools-remove-errx-from-computer-commands.patch b/SOURCES/0001-tools-remove-errx-from-computer-commands.patch deleted file mode 100644 index 71db611..0000000 --- a/SOURCES/0001-tools-remove-errx-from-computer-commands.patch +++ /dev/null @@ -1,328 +0,0 @@ -From fa7926c7a9d92bc7c42c610ba6f1706c635aa901 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Apr 2019 17:54:27 +0200 -Subject: [PATCH 1/7] tools: remove errx from computer commands - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/computer.c | 166 ++++++++++++++++++++++++++++++----------------- - 1 file changed, 107 insertions(+), 59 deletions(-) - -diff --git a/tools/computer.c b/tools/computer.c -index bee695c..9cbbb28 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -379,8 +379,10 @@ adcli_tool_computer_join (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { - switch (opt) { -@@ -415,21 +417,28 @@ adcli_tool_computer_join (adcli_conn *conn, - - if (argc == 1) - adcli_conn_set_domain_name (conn, argv[0]); -- else if (argc > 1) -- errx (2, "extra arguments specified"); -+ else if (argc > 1) { -+ warnx ("extra arguments specified"); -+ adcli_enroll_unref (enroll); -+ return 2; -+ } - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ 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, flags); - if (res != ADCLI_SUCCESS) { -- errx (-res, "joining domain %s failed: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("joining domain %s failed: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - if (details) -@@ -486,8 +495,10 @@ adcli_tool_computer_update (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { - switch (opt) { -@@ -525,22 +536,28 @@ adcli_tool_computer_update (adcli_conn *conn, - - res = adcli_enroll_load (enroll); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't lookup domain info from keytab: %s", -- adcli_get_last_error ()); -+ warnx ("couldn't lookup domain info from keytab: %s", -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ 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_update (enroll, flags); - if (res != ADCLI_SUCCESS) { -- errx (-res, "updating membership with domain %s failed: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("updating membership with domain %s failed: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - if (details) -@@ -578,8 +595,10 @@ adcli_tool_computer_testjoin (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { - switch (opt) { -@@ -604,18 +623,18 @@ adcli_tool_computer_testjoin (adcli_conn *conn, - res = adcli_enroll_load (enroll); - if (res != ADCLI_SUCCESS) { - adcli_enroll_unref (enroll); -- adcli_conn_unref (conn); -- errx (-res, "couldn't lookup domain info from keytab: %s", -- adcli_get_last_error ()); -+ warnx ("couldn't lookup domain info from keytab: %s", -+ adcli_get_last_error ()); -+ return -res; - } - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { - adcli_enroll_unref (enroll); -- adcli_conn_unref (conn); -- errx (-res, "couldn't connect to %s domain: %s", -+ warnx ("couldn't connect to %s domain: %s", - adcli_conn_get_domain_name (conn), - adcli_get_last_error ()); -+ return -res; - } - - printf ("Sucessfully validated join to domain %s\n", -@@ -665,8 +684,10 @@ adcli_tool_computer_preset (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - flags = ADCLI_ENROLL_NO_KEYTAB; - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { -@@ -694,17 +715,22 @@ adcli_tool_computer_preset (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc < 1) -- errx (EUSAGE, "specify one or more host names of computer accounts to preset"); -+ if (argc < 1) { -+ warnx ("specify one or more host names of computer accounts to preset"); -+ adcli_enroll_unref (enroll); -+ return EUSAGE; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - reset_password = (adcli_enroll_get_computer_password (enroll) == NULL); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - for (i = 0; i < argc; i++) { -@@ -715,9 +741,11 @@ adcli_tool_computer_preset (adcli_conn *conn, - - res = adcli_enroll_join (enroll, flags); - if (res != ADCLI_SUCCESS) { -- errx (-res, "presetting %s in %s domain failed: %s", argv[i], -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("presetting %s in %s domain failed: %s", argv[i], -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - printf ("computer-name: %s\n", adcli_enroll_get_computer_name (enroll)); -@@ -758,8 +786,10 @@ adcli_tool_computer_reset (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { - switch (opt) { -@@ -779,14 +809,19 @@ adcli_tool_computer_reset (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc != 1) -- errx (EUSAGE, "specify one host name of computer account to reset"); -+ if (argc != 1) { -+ warnx ("specify one host name of computer account to reset"); -+ adcli_enroll_unref (enroll); -+ return EUSAGE; -+ } - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - parse_fqdn_or_name (enroll, argv[0]); -@@ -794,9 +829,11 @@ adcli_tool_computer_reset (adcli_conn *conn, - - res = adcli_enroll_password (enroll, 0); - if (res != ADCLI_SUCCESS) { -- errx (-res, "resetting %s in %s domain failed: %s", argv[0], -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("resetting %s in %s domain failed: %s", argv[0], -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - adcli_enroll_unref (enroll); -@@ -832,8 +869,10 @@ adcli_tool_computer_delete (adcli_conn *conn, - }; - - enroll = adcli_enroll_new (conn); -- if (enroll == NULL) -- errx (-1, "unexpected memory problems"); -+ if (enroll == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) { - switch (opt) { -@@ -853,22 +892,29 @@ adcli_tool_computer_delete (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc > 1) -- errx (EUSAGE, "specify one host name of computer account to delete"); -+ if (argc > 1) { -+ warnx ("specify one host name of computer account to delete"); -+ adcli_enroll_unref (enroll); -+ return EUSAGE; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_enroll_load (enroll); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't lookup domain info from keytab: %s", -- adcli_get_last_error ()); -+ warnx ("couldn't lookup domain info from keytab: %s", -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ 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) -@@ -876,9 +922,11 @@ adcli_tool_computer_delete (adcli_conn *conn, - - res = adcli_enroll_delete (enroll, 0); - if (res != ADCLI_SUCCESS) { -- errx (-res, "deleting %s in %s domain failed: %s", argv[0], -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("deleting %s in %s domain failed: %s", argv[0], -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_enroll_unref (enroll); -+ return -res; - } - - adcli_enroll_unref (enroll); --- -2.20.1 - diff --git a/SOURCES/0002-Add-delattr-option.patch b/SOURCES/0002-Add-delattr-option.patch deleted file mode 100644 index 92cf623..0000000 --- a/SOURCES/0002-Add-delattr-option.patch +++ /dev/null @@ -1,191 +0,0 @@ -From cd5b6cdcf3e6bfc5776f2865f460f608421dfa3f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 14 Jun 2021 08:42:21 +0200 -Subject: [PATCH 2/2] Add delattr option - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1690920 ---- - doc/adcli.xml | 11 ++++++++ - library/adenroll.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ - library/adenroll.h | 4 +++ - tools/computer.c | 9 +++++++ - 4 files changed, 90 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 8383aa7..bcf4857 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -577,6 +577,17 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - adcli options cannot be set with this option. - - -+ -+ -+ Remove the LDAP attribute -+ from the -+ LDAP host object. This option can be used multiple -+ times to remove multiple different attributes. -+ Please note that the account used to update the -+ host object must have the required privileges to delete -+ the given attributes. Attributes managed by other adcli -+ options cannot be removed. -+ - - - After a successful join print out information -diff --git a/library/adenroll.c b/library/adenroll.c -index dd51567..9a06d52 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -151,5 +151,6 @@ struct _adcli_enroll { - char *description; - char **setattr; -+ char **delattr; - }; - - static const char * -@@ -845,6 +846,39 @@ get_mods_for_attrs (adcli_enroll *enroll, int mod_op) - return mods; - } - -+static LDAPMod ** -+get_del_mods_for_attrs (adcli_enroll *enroll, int mod_op) -+{ -+ size_t len; -+ size_t c; -+ LDAPMod **mods = NULL; -+ -+ len = _adcli_strv_len (enroll->delattr); -+ if (len == 0) { -+ return NULL; -+ } -+ -+ mods = calloc (len + 1, sizeof (LDAPMod *)); -+ return_val_if_fail (mods != NULL, NULL); -+ -+ for (c = 0; c < len; c++) { -+ mods[c] = calloc (1, sizeof (LDAPMod)); -+ if (mods[c] == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ -+ mods[c]->mod_op = mod_op; -+ mods[c]->mod_type = strdup (enroll->delattr[c]); -+ mods[c]->mod_values = NULL; -+ if (mods[c]->mod_type == NULL) { -+ ldap_mods_free (mods, 1); -+ return NULL; -+ } -+ } -+ -+ return mods; -+} - - static adcli_result - create_computer_account (adcli_enroll *enroll, -@@ -1775,6 +1809,14 @@ update_computer_account (adcli_enroll *enroll) - } - } - -+ if (res == ADCLI_SUCCESS && enroll->delattr != NULL) { -+ LDAPMod **mods = get_del_mods_for_attrs (enroll, LDAP_MOD_DELETE); -+ if (mods != NULL) { -+ res |= update_computer_attribute (enroll, ldap, mods); -+ ldap_mods_free (mods, 1); -+ } -+ } -+ - if (res != 0) - _adcli_info ("Updated existing computer account: %s", enroll->computer_dn); - } -@@ -3475,6 +3517,30 @@ adcli_enroll_get_setattr (adcli_enroll *enroll) - return (const char **) enroll->setattr; - } - -+adcli_result -+adcli_enroll_add_delattr (adcli_enroll *enroll, const char *value) -+{ -+ return_val_if_fail (enroll != NULL, ADCLI_ERR_CONFIG); -+ return_val_if_fail (value != NULL, ADCLI_ERR_CONFIG); -+ -+ if (_adcli_strv_has_ex (default_ad_ldap_attrs, value, strcasecmp) == 1) { -+ _adcli_err ("Attribute [%s] cannot be removed with delattr", value); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ enroll->delattr = _adcli_strv_add (enroll->delattr, strdup (value), -+ NULL); -+ return_val_if_fail (enroll->delattr != NULL, ADCLI_ERR_CONFIG); -+ -+ return ADCLI_SUCCESS; -+} -+ -+const char ** -+adcli_enroll_get_delattr (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ return (const char **) enroll->delattr; -+} - - #ifdef ADENROLL_TESTS - -diff --git a/library/adenroll.h b/library/adenroll.h -index 862bb60..e3ada33 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -142,6 +142,10 @@ const char ** adcli_enroll_get_setattr (adcli_enroll *enroll); - adcli_result adcli_enroll_add_setattr (adcli_enroll *enroll, - const char *value); - -+const char ** adcli_enroll_get_delattr (adcli_enroll *enroll); -+adcli_result adcli_enroll_add_delattr (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); -diff --git a/tools/computer.c b/tools/computer.c -index af38894..dffeecb 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -115,6 +115,7 @@ typedef enum { - opt_remove_service_principal, - opt_description, - opt_setattr, -+ opt_delattr, - opt_use_ldaps, - } Option; - -@@ -154,6 +155,7 @@ static adcli_tool_desc common_usages[] = { - { opt_remove_service_principal, "remove the given service principal from the account\n" }, - { opt_description, "add a description to the account\n" }, - { opt_setattr, "add an attribute with a value\n" }, -+ { opt_delattr, "remove an attribute\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" -@@ -341,6 +343,12 @@ parse_option (Option opt, - warnx ("parsing setattr option failed"); - } - return ret; -+ case opt_delattr: -+ ret = adcli_enroll_add_delattr (enroll, optarg); -+ if (ret != ADCLI_SUCCESS) { -+ warnx ("parsing delattr option failed"); -+ } -+ return ret; - case opt_use_ldaps: - adcli_conn_set_use_ldaps (conn, true); - return ADCLI_SUCCESS; -@@ -534,6 +542,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "description", optional_argument, NULL, opt_description }, - { "setattr", required_argument, NULL, opt_setattr }, -+ { "delattr", required_argument, NULL, opt_delattr }, - { "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.31.1 - diff --git a/SOURCES/0002-Add-dont-expire-password-option.patch b/SOURCES/0002-Add-dont-expire-password-option.patch deleted file mode 100644 index 0ae8a90..0000000 --- a/SOURCES/0002-Add-dont-expire-password-option.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 74b52a30c2b142118b7f26f78c014e7bee825e84 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 2 Jun 2021 17:24:07 +0200 -Subject: [PATCH 2/2] Add dont-expire-password option - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1769644 ---- - doc/adcli.xml | 28 ++++++++++++++++++++++ - library/adenroll.c | 58 +++++++++++++++++++++++++++++++++++++++++----- - library/adenroll.h | 4 ++++ - tools/computer.c | 12 ++++++++++ - 4 files changed, 96 insertions(+), 6 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index a64687a..7c2e126 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -347,6 +347,20 @@ Password for Administrator: - not allow that Kerberos tickets can be forwarded to the - host. - -+ -+ -+ Set or unset the DONT_EXPIRE_PASSWORD -+ flag in the userAccountControl attribute to indicate if -+ the machine account password should expire or not. By -+ default adcli will set this flag while joining the -+ domain which corresponds to the default behavior of -+ Windows clients. -+ Please note that if the password will expire -+ (--dont-expire-password=false) a renewal mechanism has -+ to be enabled on the client to not loose the -+ connectivity to AD if the password expires. -+ -+ - - - Add a service principal name. In -@@ -491,6 +505,20 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - not allow that Kerberos tickets can be forwarded to the - host. - -+ -+ -+ Set or unset the DONT_EXPIRE_PASSWORD -+ flag in the userAccountControl attribute to indicate if -+ the machine account password should expire or not. By -+ default adcli will set this flag while joining the -+ domain which corresponds to the default behavior of -+ Windows clients. -+ Please note that if the password will expire -+ (--dont-expire-password=false) a renewal mechanism has -+ to be enabled on the client to not loose the -+ connectivity to AD if the password expires. -+ -+ - - - Add a service principal name. In -diff --git a/library/adenroll.c b/library/adenroll.c -index c726093..01f149c 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -152,6 +152,8 @@ struct _adcli_enroll { - char *samba_data_tool; - bool trusted_for_delegation; - int trusted_for_delegation_explicit; -+ bool dont_expire_password; -+ int dont_expire_password_explicit; - char *description; - }; - -@@ -829,6 +831,8 @@ create_computer_account (adcli_enroll *enroll, - int ret; - size_t c; - size_t m; -+ uint32_t uac = UAC_WORKSTATION_TRUST_ACCOUNT | UAC_DONT_EXPIRE_PASSWORD ; -+ char *uac_str = NULL; - - LDAPMod *all_mods[] = { - &objectClass, -@@ -849,11 +853,21 @@ create_computer_account (adcli_enroll *enroll, - LDAPMod *mods[mods_count]; - - if (adcli_enroll_get_trusted_for_delegation (enroll)) { -- vals_userAccountControl[0] = "593920"; /* WORKSTATION_TRUST_ACCOUNT | DONT_EXPIRE_PASSWD | TRUSTED_FOR_DELEGATION */ -+ uac |= UAC_TRUSTED_FOR_DELEGATION; -+ } -+ -+ if (!adcli_enroll_get_dont_expire_password (enroll)) { -+ uac &= ~(UAC_DONT_EXPIRE_PASSWORD); -+ } -+ -+ if (asprintf (&uac_str, "%d", uac) < 0) { -+ return_val_if_reached (ADCLI_ERR_UNEXPECTED); - } -+ vals_userAccountControl[0] = uac_str; - - ret = calculate_enctypes (enroll, &val); - if (ret != ADCLI_SUCCESS) { -+ free (uac_str); - return ret; - } - vals_supportedEncryptionTypes[0] = val; -@@ -868,6 +882,7 @@ create_computer_account (adcli_enroll *enroll, - mods[m] = NULL; - - ret = ldap_add_ext_s (ldap, enroll->computer_dn, mods, NULL, NULL); -+ free (uac_str); - free (val); - - /* -@@ -1566,10 +1581,20 @@ static char *get_user_account_control (adcli_enroll *enroll) - uac = UAC_WORKSTATION_TRUST_ACCOUNT | UAC_DONT_EXPIRE_PASSWORD; - } - -- if (adcli_enroll_get_trusted_for_delegation (enroll)) { -- uac |= UAC_TRUSTED_FOR_DELEGATION; -- } else { -- uac &= ~(UAC_TRUSTED_FOR_DELEGATION); -+ if (enroll->trusted_for_delegation_explicit) { -+ if (adcli_enroll_get_trusted_for_delegation (enroll)) { -+ uac |= UAC_TRUSTED_FOR_DELEGATION; -+ } else { -+ uac &= ~(UAC_TRUSTED_FOR_DELEGATION); -+ } -+ } -+ -+ if (enroll->dont_expire_password_explicit) { -+ if (adcli_enroll_get_dont_expire_password (enroll)) { -+ uac |= UAC_DONT_EXPIRE_PASSWORD; -+ } else { -+ uac &= ~(UAC_DONT_EXPIRE_PASSWORD); -+ } - } - - if (asprintf (&uac_str, "%d", uac) < 0) { -@@ -1613,7 +1640,8 @@ update_computer_account (adcli_enroll *enroll) - } - free (value); - -- if (res == ADCLI_SUCCESS && enroll->trusted_for_delegation_explicit) { -+ if (res == ADCLI_SUCCESS && (enroll->trusted_for_delegation_explicit || -+ enroll->dont_expire_password_explicit)) { - char *vals_userAccountControl[] = { NULL , NULL }; - LDAPMod userAccountControl = { LDAP_MOD_REPLACE, "userAccountControl", { vals_userAccountControl, } }; - LDAPMod *mods[] = { &userAccountControl, NULL }; -@@ -3194,6 +3222,24 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, - enroll->trusted_for_delegation_explicit = 1; - } - -+bool -+adcli_enroll_get_dont_expire_password (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, false); -+ -+ return enroll->dont_expire_password; -+} -+ -+void -+adcli_enroll_set_dont_expire_password (adcli_enroll *enroll, -+ bool value) -+{ -+ return_if_fail (enroll != NULL); -+ -+ enroll->dont_expire_password = value; -+ enroll->dont_expire_password_explicit = 1; -+} -+ - void - adcli_enroll_set_description (adcli_enroll *enroll, const char *value) - { -diff --git a/library/adenroll.h b/library/adenroll.h -index 11a30c8..5190eb6 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); - -+bool adcli_enroll_get_dont_expire_password (adcli_enroll *enroll); -+void adcli_enroll_set_dont_expire_password (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); -diff --git a/tools/computer.c b/tools/computer.c -index 98a0472..954066a 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -110,6 +110,7 @@ typedef enum { - opt_add_samba_data, - opt_samba_data_tool, - opt_trusted_for_delegation, -+ opt_dont_expire_password, - opt_add_service_principal, - opt_remove_service_principal, - opt_description, -@@ -143,6 +144,8 @@ static adcli_tool_desc common_usages[] = { - { opt_computer_password_lifetime, "lifetime of the host accounts password in days", }, - { opt_trusted_for_delegation, "set/unset the TRUSTED_FOR_DELEGATION flag\n" - "in the userAccountControl attribute", }, -+ { opt_dont_expire_password, "set/unset the DONT_EXPIRE_PASSWORD flag\n" -+ "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" }, -@@ -304,6 +307,13 @@ parse_option (Option opt, - adcli_enroll_set_trusted_for_delegation (enroll, false); - } - return ADCLI_SUCCESS; -+ case opt_dont_expire_password: -+ if (strcasecmp (optarg, "true") == 0 || strcasecmp (optarg, "yes") == 0) { -+ adcli_enroll_set_dont_expire_password (enroll, true); -+ } else { -+ adcli_enroll_set_dont_expire_password (enroll, false); -+ } -+ return ADCLI_SUCCESS; - case opt_add_service_principal: - adcli_enroll_add_service_principal_to_add (enroll, optarg); - return ADCLI_SUCCESS; -@@ -383,6 +393,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "description", optional_argument, NULL, opt_description }, - { "user-principal", optional_argument, NULL, opt_user_principal }, - { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation }, -+ { "dont-expire-password", required_argument, NULL, opt_dont_expire_password }, - { "add-service-principal", required_argument, NULL, opt_add_service_principal }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, -@@ -504,6 +515,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "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 }, -+ { "dont-expire-password", required_argument, NULL, opt_dont_expire_password }, - { "add-service-principal", required_argument, NULL, opt_add_service_principal }, - { "remove-service-principal", required_argument, NULL, opt_remove_service_principal }, - { "show-details", no_argument, NULL, opt_show_details }, --- -2.31.1 - diff --git a/SOURCES/0002-Use-strdup-if-offset-are-used.patch b/SOURCES/0002-Use-strdup-if-offset-are-used.patch deleted file mode 100644 index 47ea1ad..0000000 --- a/SOURCES/0002-Use-strdup-if-offset-are-used.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 4ba49015ca1ad98c03a209a11862f8e00d00fbd0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 24 Aug 2016 16:19:36 +0200 -Subject: [PATCH 02/23] Use strdup() if offset are used - -Strings with an offset to the original starting point must be copied -because otherwise they cannot be properly freed later. ---- - library/adenroll.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index d1020e9..05885d0 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1318,9 +1318,9 @@ load_keytab_entry (krb5_context k5, - - } else if (!enroll->host_fqdn && _adcli_str_has_prefix (name, "host/") && strchr (name, '.')) { - /* Skip host/ prefix */ -- enroll->host_fqdn = name + 5; -- _adcli_info ("Found host qualified name in keytab: %s", name); -- name = NULL; -+ enroll->host_fqdn = strdup (name + 5); -+ return_val_if_fail (enroll->host_fqdn != NULL, FALSE); -+ _adcli_info ("Found host qualified name in keytab: %s", enroll->host_fqdn); - } - } - --- -2.14.4 - diff --git a/SOURCES/0002-_adcli_call_external_program-silence-noisy-debug-mes.patch b/SOURCES/0002-_adcli_call_external_program-silence-noisy-debug-mes.patch deleted file mode 100644 index 76fe1dc..0000000 --- a/SOURCES/0002-_adcli_call_external_program-silence-noisy-debug-mes.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 8cc4ef1cae7d4d753f2cf9aeb8021dd96cb75d36 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 8 Aug 2018 12:17:18 +0200 -Subject: [PATCH 2/4] _adcli_call_external_program: silence noisy debug message - ---- - library/adutil.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/adutil.c b/library/adutil.c -index 6334b52..17d2caa 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -672,7 +672,7 @@ done: - if (wret == -1) { - _adcli_err ("No sure what happend to net command."); - } else { -- if (WIFEXITED (status)) { -+ if (WIFEXITED (status) && WEXITSTATUS (status) != 0) { - _adcli_err ("net command failed with %d.", - WEXITSTATUS (status)); - } --- -2.17.1 - diff --git a/SOURCES/0002-adcli_entry-add-entry_attrs-with-userAccountControl-.patch b/SOURCES/0002-adcli_entry-add-entry_attrs-with-userAccountControl-.patch deleted file mode 100644 index 58d91ec..0000000 --- a/SOURCES/0002-adcli_entry-add-entry_attrs-with-userAccountControl-.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 7148ab196d0a96ede9b5ef463b0481d0fe372b21 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 11 Jun 2021 12:46:03 +0200 -Subject: [PATCH 2/3] adcli_entry: add entry_attrs with userAccountControl - attribute - ---- - library/adentry.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/library/adentry.c b/library/adentry.c -index 1cc0518..13dcaf8 100644 ---- a/library/adentry.c -+++ b/library/adentry.c -@@ -42,6 +42,7 @@ struct _adcli_entry { - char *entry_dn; - char *domain_ou; - char *entry_container; -+ LDAPMessage *entry_attrs; - }; - - static adcli_entry * -@@ -63,6 +64,7 @@ entry_new (adcli_conn *conn, - - entry->builder = builder; - entry->object_class = object_class; -+ entry->entry_attrs = NULL; - return entry; - } - -@@ -82,6 +84,7 @@ entry_free (adcli_entry *entry) - free (entry->entry_container); - free (entry->entry_dn); - free (entry->domain_ou); -+ ldap_msgfree (entry->entry_attrs); - adcli_conn_unref (entry->conn); - free (entry); - } -@@ -102,7 +105,7 @@ static adcli_result - update_entry_from_domain (adcli_entry *entry, - LDAP *ldap) - { -- const char *attrs[] = { "1.1", NULL }; -+ const char *attrs[] = { "userAccountControl", NULL }; - LDAPMessage *results; - LDAPMessage *first; - const char *base; -@@ -139,7 +142,8 @@ update_entry_from_domain (adcli_entry *entry, - return_unexpected_if_fail (entry->entry_dn != NULL); - } - -- ldap_msgfree (results); -+ ldap_msgfree (entry->entry_attrs); -+ entry->entry_attrs = results; - return ADCLI_SUCCESS; - } - --- -2.31.1 - diff --git a/SOURCES/0002-adconn-add-adcli_conn_set_krb5_context.patch b/SOURCES/0002-adconn-add-adcli_conn_set_krb5_context.patch deleted file mode 100644 index 769a022..0000000 --- a/SOURCES/0002-adconn-add-adcli_conn_set_krb5_context.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 2fc259a88be618871cea8ff8b8a13bd3e040aea4 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 13 Jun 2019 17:23:47 +0200 -Subject: [PATCH 2/4] adconn: add adcli_conn_set_krb5_context - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/3 ---- - library/adconn.c | 13 +++++++++++++ - library/adconn.h | 3 +++ - 2 files changed, 16 insertions(+) - -diff --git a/library/adconn.c b/library/adconn.c -index f6c23d3..bcaced8 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -1406,6 +1406,19 @@ adcli_conn_get_krb5_context (adcli_conn *conn) - return conn->k5; - } - -+void -+adcli_conn_set_krb5_context (adcli_conn *conn, -+ krb5_context k5) -+{ -+ return_if_fail (conn != NULL); -+ -+ if (conn->k5 != NULL) { -+ krb5_free_context (conn->k5); -+ } -+ -+ conn->k5 = k5; -+} -+ - const char * - adcli_conn_get_login_user (adcli_conn *conn) - { -diff --git a/library/adconn.h b/library/adconn.h -index 13cfd32..1ad5715 100644 ---- a/library/adconn.h -+++ b/library/adconn.h -@@ -97,6 +97,9 @@ LDAP * adcli_conn_get_ldap_connection (adcli_conn *conn); - - krb5_context adcli_conn_get_krb5_context (adcli_conn *conn); - -+void adcli_conn_set_krb5_context (adcli_conn *conn, -+ krb5_context k5); -+ - const char * adcli_conn_get_computer_name (adcli_conn *conn); - - void adcli_conn_set_computer_name (adcli_conn *conn, --- -2.21.0 - diff --git a/SOURCES/0002-add-description-option-to-join-and-update.patch b/SOURCES/0002-add-description-option-to-join-and-update.patch deleted file mode 100644 index a36dfc9..0000000 --- a/SOURCES/0002-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 2/2] 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.21.0 - diff --git a/SOURCES/0002-add-option-use-ldaps.patch b/SOURCES/0002-add-option-use-ldaps.patch deleted file mode 100644 index ab34272..0000000 --- a/SOURCES/0002-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 2/2] 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.21.0 - diff --git a/SOURCES/0002-adenroll-use-_adcli_strv_add_unique-for-service-prin.patch b/SOURCES/0002-adenroll-use-_adcli_strv_add_unique-for-service-prin.patch deleted file mode 100644 index e4a6bc5..0000000 --- a/SOURCES/0002-adenroll-use-_adcli_strv_add_unique-for-service-prin.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0c027538f398b3823bedbfbf5f388ad97784a0ec Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 16 Nov 2018 13:32:59 +0100 -Subject: [PATCH 2/2] adenroll: use _adcli_strv_add_unique for service - principals - -Check if service principals is already in the list before adding it. - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/16 ---- - library/adenroll.c | 31 ++++++++----------------------- - 1 file changed, 8 insertions(+), 23 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index de2242a..e02f403 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -313,7 +313,6 @@ add_service_names_to_service_principals (adcli_enroll *enroll) - char *name; - int length = 0; - int i; -- size_t c; - - if (enroll->service_principals != NULL) { - length = seq_count (enroll->service_principals); -@@ -322,28 +321,14 @@ add_service_names_to_service_principals (adcli_enroll *enroll) - for (i = 0; enroll->service_names[i] != NULL; i++) { - if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0) - return_unexpected_if_reached (); -- for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) { -- if (strcmp (name, enroll->service_principals[c]) == 0) { -- break; -- } -- } -- if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) { -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -- } -+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, -+ name, &length, false); - - if (enroll->host_fqdn) { - if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0) - return_unexpected_if_reached (); -- for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) { -- if (strcmp (name, enroll->service_principals[c]) == 0) { -- break; -- } -- } -- if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) { -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -- } -+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, -+ name, &length, false); - } - } - -@@ -364,9 +349,9 @@ add_and_remove_service_principals (adcli_enroll *enroll) - list = adcli_enroll_get_service_principals_to_add (enroll); - if (list != NULL) { - for (c = 0; list[c] != NULL; c++) { -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- strdup (list[c]), -- &length); -+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, -+ strdup (list[c]), -+ &length, false); - if (enroll->service_principals == NULL) { - return ADCLI_ERR_UNEXPECTED; - } -@@ -1525,7 +1510,7 @@ load_keytab_entry (krb5_context k5, - value = strdup (name); - return_val_if_fail (value != NULL, FALSE); - _adcli_info ("Found service principal in keytab: %s", value); -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, value, NULL); -+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, value, NULL, false); - } - } - --- -2.20.1 - diff --git a/SOURCES/0002-computer-add-create-msa-sub-command.patch b/SOURCES/0002-computer-add-create-msa-sub-command.patch deleted file mode 100644 index 7aaae8a..0000000 --- a/SOURCES/0002-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 2/7] 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/SOURCES/0002-create-user-try-to-find-NIS-domain-if-needed.patch b/SOURCES/0002-create-user-try-to-find-NIS-domain-if-needed.patch deleted file mode 100644 index 0ecdc90..0000000 --- a/SOURCES/0002-create-user-try-to-find-NIS-domain-if-needed.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 408880a11879b1a57a450e25c77ef2e310bdffd5 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 18 Mar 2019 16:45:54 +0100 -Subject: [PATCH 2/2] create-user: try to find NIS domain if needed - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/2 ---- - doc/adcli.xml | 4 +++- - library/adentry.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ - library/adentry.h | 2 ++ - tools/entry.c | 16 ++++++++++++++++ - 4 files changed, 65 insertions(+), 1 deletion(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 18620c0..af73433 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -537,7 +537,9 @@ $ adcli create-user Fry --domain=domain.example.com \ - the new created user account, which should be the user's - NIS domain is the NIS/YP service of Active Directory's Services for Unix (SFU) - are used. This is needed to let the 'UNIX attributes' tab of older Active -- Directoy versions show the set UNIX specific attributes. -+ Directoy versions show the set UNIX specific attributes. If not specified -+ adcli will try to determine the NIS domain automatically if needed. -+ - - - -diff --git a/library/adentry.c b/library/adentry.c -index 9b9e1c6..1cc0518 100644 ---- a/library/adentry.c -+++ b/library/adentry.c -@@ -484,3 +484,47 @@ adcli_entry_new_group (adcli_conn *conn, - return_val_if_fail (sam_name != NULL, NULL); - return entry_new (conn, "group", group_entry_builder, sam_name); - } -+ -+adcli_result -+adcli_get_nis_domain (adcli_entry *entry, -+ adcli_attrs *attrs) -+{ -+ LDAP *ldap; -+ const char *ldap_attrs[] = { "cn", NULL }; -+ LDAPMessage *results; -+ LDAPMessage *ldap_entry; -+ char *base; -+ const char *filter = "objectClass=msSFU30DomainInfo"; -+ char *cn; -+ int ret; -+ -+ ldap = adcli_conn_get_ldap_connection (entry->conn); -+ return_unexpected_if_fail (ldap != NULL); -+ -+ if (asprintf (&base, "CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System,%s", -+ adcli_conn_get_default_naming_context (entry->conn)) < 0) { -+ return_unexpected_if_reached (); -+ } -+ -+ ret = ldap_search_ext_s (ldap, base, LDAP_SCOPE_SUB, filter, (char **)ldap_attrs, -+ 0, NULL, NULL, NULL, -1, &results); -+ -+ free (base); -+ -+ if (ret != LDAP_SUCCESS) { -+ /* No NIS domain available */ -+ ldap_msgfree (results); -+ return ADCLI_SUCCESS; -+ } -+ -+ ldap_entry = ldap_first_entry (ldap, results); -+ if (ldap_entry != NULL) { -+ cn = _adcli_ldap_parse_value (ldap, ldap_entry, "cn"); -+ return_unexpected_if_fail (cn != NULL); -+ -+ adcli_attrs_add (attrs, "msSFU30NisDomain", cn, NULL); -+ } -+ ldap_msgfree (results); -+ -+ return ADCLI_SUCCESS; -+} -diff --git a/library/adentry.h b/library/adentry.h -index eb8bc00..ae90689 100644 ---- a/library/adentry.h -+++ b/library/adentry.h -@@ -58,4 +58,6 @@ const char * adcli_entry_get_sam_name (adcli_entry *entry); - - const char * adcli_entry_get_dn (adcli_entry *entry); - -+adcli_result adcli_get_nis_domain (adcli_entry *entry, -+ adcli_attrs *attrs); - #endif /* ADENTRY_H_ */ -diff --git a/tools/entry.c b/tools/entry.c -index 69ce62c..de56586 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -153,6 +153,8 @@ adcli_tool_user_create (adcli_conn *conn, - adcli_attrs *attrs; - const char *ou = NULL; - int opt; -+ bool has_unix_attr = false; -+ bool has_nis_domain = false; - - struct option options[] = { - { "display-name", required_argument, NULL, opt_display_name }, -@@ -193,18 +195,23 @@ adcli_tool_user_create (adcli_conn *conn, - break; - case opt_unix_home: - adcli_attrs_add (attrs, "unixHomeDirectory", optarg, NULL); -+ has_unix_attr = true; - break; - case opt_unix_uid: - adcli_attrs_add (attrs, "uidNumber", optarg, NULL); -+ has_unix_attr = true; - break; - case opt_unix_gid: - adcli_attrs_add (attrs, "gidNumber", optarg, NULL); -+ has_unix_attr = true; - break; - case opt_unix_shell: - adcli_attrs_add (attrs, "loginShell", optarg, NULL); -+ has_unix_attr = true; - break; - case opt_nis_domain: - adcli_attrs_add (attrs, "msSFU30NisDomain", optarg, NULL); -+ has_nis_domain = true; - break; - case opt_domain_ou: - ou = optarg; -@@ -242,6 +249,15 @@ adcli_tool_user_create (adcli_conn *conn, - adcli_get_last_error ()); - } - -+ if (has_unix_attr && !has_nis_domain) { -+ res = adcli_get_nis_domain (entry, attrs); -+ if (res != ADCLI_SUCCESS) { -+ adcli_entry_unref (entry); -+ adcli_attrs_free (attrs); -+ errx (-res, "couldn't get NIS domain"); -+ } -+ } -+ - res = adcli_entry_create (entry, attrs); - if (res != ADCLI_SUCCESS) { - errx (-res, "creating user %s in domain %s failed: %s", --- -2.20.1 - diff --git a/SOURCES/0002-library-make-_adcli_strv_has_ex-public.patch b/SOURCES/0002-library-make-_adcli_strv_has_ex-public.patch deleted file mode 100644 index db18951..0000000 --- a/SOURCES/0002-library-make-_adcli_strv_has_ex-public.patch +++ /dev/null @@ -1,42 +0,0 @@ -From e1b45e66bc185f5db4c252e1f3fb1b4400b4538e Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 22 Mar 2019 10:36:38 +0100 -Subject: [PATCH 2/4] library: make _adcli_strv_has_ex public - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187 ---- - library/adprivate.h | 4 ++++ - library/adutil.c | 2 +- - 2 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/library/adprivate.h b/library/adprivate.h -index 0806430..55e6234 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -125,6 +125,10 @@ void _adcli_strv_free (char **strv); - int _adcli_strv_has (char **strv, - const char *str); - -+int _adcli_strv_has_ex (char **strv, -+ const char *str, -+ int (* compare) (const char *match, const char*value)); -+ - char ** _adcli_strv_dup (char **strv) GNUC_WARN_UNUSED; - - char * _adcli_strv_join (char **strv, -diff --git a/library/adutil.c b/library/adutil.c -index 76ea158..9b0c47f 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -221,7 +221,7 @@ _adcli_strv_add (char **strv, - return seq_push (strv, length, string); - } - --static int -+int - _adcli_strv_has_ex (char **strv, - const char *str, - int (* compare) (const char *match, const char*value)) --- -2.20.1 - diff --git a/SOURCES/0002-library-return-error-if-no-matching-key-was-found.patch b/SOURCES/0002-library-return-error-if-no-matching-key-was-found.patch deleted file mode 100644 index f9c68d6..0000000 --- a/SOURCES/0002-library-return-error-if-no-matching-key-was-found.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 4987a21f4839ab7ea50e932c72df05075efb89b3 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 21 Mar 2019 15:05:33 +0100 -Subject: [PATCH 2/2] library: return error if no matching key was found - -To avoid a misleading debug message indicating success a proper erro -code should be returned the no matching key was found when trying to -copy an keytab entry for a new principal. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1644311 ---- - library/adkrb5.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/library/adkrb5.c b/library/adkrb5.c -index 033c181..7f77373 100644 ---- a/library/adkrb5.c -+++ b/library/adkrb5.c -@@ -298,11 +298,10 @@ _adcli_krb5_keytab_copy_entries (krb5_context k5, - - code = _adcli_krb5_get_keyblock (k5, keytab, &entry.key, - match_enctype_and_kvno, &closure); -- if (code != 0) { -- return code; -+ if (code != 0 || closure.matched == 0) { -+ return code != 0 ? code : ENOKEY; - } - -- - entry.principal = principal; - entry.vno = kvno; - --- -2.20.1 - diff --git a/SOURCES/0002-tools-remove-errx-from-user-and-group-commands.patch b/SOURCES/0002-tools-remove-errx-from-user-and-group-commands.patch deleted file mode 100644 index 36e5567..0000000 --- a/SOURCES/0002-tools-remove-errx-from-user-and-group-commands.patch +++ /dev/null @@ -1,398 +0,0 @@ -From cac0fa9df8888245399f2db187e05e31f93d1471 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Apr 2019 17:56:37 +0200 -Subject: [PATCH 2/7] tools: remove errx from user and group commands - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/entry.c | 232 +++++++++++++++++++++++++++++++++----------------- - 1 file changed, 154 insertions(+), 78 deletions(-) - -diff --git a/tools/entry.c b/tools/entry.c -index de56586..97ec6e7 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -232,21 +232,30 @@ adcli_tool_user_create (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc != 1) -- errx (2, "specify one user name to create"); -+ if (argc != 1) { -+ warnx ("specify one user name to create"); -+ adcli_attrs_free (attrs); -+ return 2; -+ } - - entry = adcli_entry_new_user (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ adcli_attrs_free (attrs); -+ return -1; -+ } - adcli_entry_set_domain_ou (entry, ou); - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ adcli_attrs_free (attrs); -+ return -res; - } - - if (has_unix_attr && !has_nis_domain) { -@@ -254,16 +263,20 @@ adcli_tool_user_create (adcli_conn *conn, - if (res != ADCLI_SUCCESS) { - adcli_entry_unref (entry); - adcli_attrs_free (attrs); -- errx (-res, "couldn't get NIS domain"); -+ warnx ("couldn't get NIS domain"); -+ return -res; - } - } - - res = adcli_entry_create (entry, attrs); - if (res != ADCLI_SUCCESS) { -- errx (-res, "creating user %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("creating user %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ adcli_attrs_free (attrs); -+ return -res; - } - - adcli_entry_unref (entry); -@@ -317,28 +330,36 @@ adcli_tool_user_delete (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc != 1) -- errx (2, "specify one user name to delete"); -+ if (argc != 1) { -+ warnx ("specify one user name to delete"); -+ return 2; -+ } - - entry = adcli_entry_new_user (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - res = adcli_entry_delete (entry); - if (res != ADCLI_SUCCESS) { -- errx (-res, "deleting user %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("deleting user %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - adcli_entry_unref (entry); -@@ -404,29 +425,41 @@ adcli_tool_group_create (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc != 1) -- errx (2, "specify one group to create"); -+ if (argc != 1) { -+ warnx ("specify one group to create"); -+ adcli_attrs_free (attrs); -+ return 2; -+ } - - entry = adcli_entry_new_group (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ adcli_attrs_free (attrs); -+ return -1; -+ } - adcli_entry_set_domain_ou (entry, ou); - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to domain %s: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to domain %s: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ adcli_attrs_free (attrs); -+ return -res; - } - - res = adcli_entry_create (entry, attrs); - if (res != ADCLI_SUCCESS) { -- errx (-res, "creating group %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("creating group %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ adcli_attrs_free (attrs); -+ return -res; - } - - adcli_entry_unref (entry); -@@ -480,28 +513,36 @@ adcli_tool_group_delete (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc != 1) -- errx (2, "specify one group name to delete"); -+ if (argc != 1) { -+ warnx ("specify one group name to delete"); -+ return 2; -+ } - - entry = adcli_entry_new_group (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - res = adcli_entry_delete (entry); - if (res != ADCLI_SUCCESS) { -- errx (-res, "deleting group %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("deleting group %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - adcli_entry_unref (entry); -@@ -509,7 +550,7 @@ adcli_tool_group_delete (adcli_conn *conn, - return 0; - } - --static void -+static int - expand_user_dn_as_member (adcli_conn *conn, - adcli_attrs *attrs, - const char *user, -@@ -523,16 +564,19 @@ expand_user_dn_as_member (adcli_conn *conn, - - res = adcli_entry_load (entry); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't lookup user %s in domain %s: %s", -- user, adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't lookup user %s in domain %s: %s", -+ user, adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - dn = adcli_entry_get_dn (entry); - if (dn == NULL) { -- errx (-ADCLI_ERR_CONFIG, -- "couldn't found user %s in domain %s", -- user, adcli_conn_get_domain_name (conn)); -+ warnx ("couldn't found user %s in domain %s", -+ user, adcli_conn_get_domain_name (conn)); -+ adcli_entry_unref (entry); -+ return -ADCLI_ERR_CONFIG; - } - - if (adding) -@@ -541,6 +585,8 @@ expand_user_dn_as_member (adcli_conn *conn, - adcli_attrs_delete1 (attrs, "member", dn); - - adcli_entry_unref (entry); -+ -+ return ADCLI_SUCCESS; - } - - int -@@ -590,33 +636,48 @@ adcli_tool_member_add (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc < 2) -- errx (2, "specify a group name and a user to add"); -+ if (argc < 2) { -+ warnx ("specify a group name and a user to add"); -+ return 2; -+ } - - entry = adcli_entry_new_group (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - attrs = adcli_attrs_new (); - -- for (i = 1; i < argc; i++) -- expand_user_dn_as_member (conn, attrs, argv[i], 1); -+ for (i = 1; i < argc; i++) { -+ res = expand_user_dn_as_member (conn, attrs, argv[i], 1); -+ if (res != ADCLI_SUCCESS) { -+ adcli_attrs_free (attrs); -+ adcli_entry_unref (entry); -+ return res; -+ } -+ } - - res = adcli_entry_modify (entry, attrs); - if (res != ADCLI_SUCCESS) { -- errx (-res, "adding member(s) to group %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("adding member(s) to group %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_attrs_free (attrs); -+ adcli_entry_unref (entry); -+ return -res; - } - - adcli_attrs_free (attrs); -@@ -672,33 +733,48 @@ adcli_tool_member_remove (adcli_conn *conn, - argc -= optind; - argv += optind; - -- if (argc < 2) -- errx (2, "specify a group name and a user to remove"); -+ if (argc < 2) { -+ warnx ("specify a group name and a user to remove"); -+ return 2; -+ } - - entry = adcli_entry_new_group (conn, argv[0]); -- if (entry == NULL) -- errx (-1, "unexpected memory problems"); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } - - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - res = adcli_conn_connect (conn); - if (res != ADCLI_SUCCESS) { -- errx (-res, "couldn't connect to %s domain: %s", -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("couldn't connect to %s domain: %s", -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; - } - - attrs = adcli_attrs_new (); - -- for (i = 1; i < argc; i++) -- expand_user_dn_as_member (conn, attrs, argv[i], 0); -+ for (i = 1; i < argc; i++) { -+ res = expand_user_dn_as_member (conn, attrs, argv[i], 0); -+ if (res != ADCLI_SUCCESS) { -+ adcli_attrs_free (attrs); -+ adcli_entry_unref (entry); -+ return res; -+ } -+ } - - res = adcli_entry_modify (entry, attrs); - if (res != ADCLI_SUCCESS) { -- errx (-res, "adding member(s) to group %s in domain %s failed: %s", -- adcli_entry_get_sam_name (entry), -- adcli_conn_get_domain_name (conn), -- adcli_get_last_error ()); -+ warnx ("adding member(s) to group %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_attrs_free (attrs); -+ adcli_entry_unref (entry); -+ return -res; - } - - adcli_attrs_free (attrs); --- -2.20.1 - diff --git a/SOURCES/0003-Do-not-add-service-principals-twice.patch b/SOURCES/0003-Do-not-add-service-principals-twice.patch deleted file mode 100644 index 5d0bfcf..0000000 --- a/SOURCES/0003-Do-not-add-service-principals-twice.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f05adc23d5cc9f1dfa5638e31949dcd81d632df9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 13 Aug 2018 17:32:24 +0200 -Subject: [PATCH 3/4] Do not add service principals twice - ---- - library/adenroll.c | 23 +++++++++++++++++++---- - 1 file changed, 19 insertions(+), 4 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index c4ba537..bb50365 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -313,6 +313,7 @@ add_service_names_to_service_principals (adcli_enroll *enroll) - char *name; - int length = 0; - int i; -+ size_t c; - - if (enroll->service_principals != NULL) { - length = seq_count (enroll->service_principals); -@@ -321,14 +322,28 @@ add_service_names_to_service_principals (adcli_enroll *enroll) - for (i = 0; enroll->service_names[i] != NULL; i++) { - if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0) - return_unexpected_if_reached (); -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -+ for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) { -+ if (strcmp (name, enroll->service_principals[c]) == 0) { -+ break; -+ } -+ } -+ if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) { -+ enroll->service_principals = _adcli_strv_add (enroll->service_principals, -+ name, &length); -+ } - - if (enroll->host_fqdn) { - if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0) - return_unexpected_if_reached (); -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -+ for (c = 0; enroll->service_principals != NULL && enroll->service_principals[c] != NULL; c++) { -+ if (strcmp (name, enroll->service_principals[c]) == 0) { -+ break; -+ } -+ } -+ if (enroll->service_principals == NULL || enroll->service_principals[c] == NULL) { -+ enroll->service_principals = _adcli_strv_add (enroll->service_principals, -+ name, &length); -+ } - } - } - --- -2.17.1 - diff --git a/SOURCES/0003-adenroll-add-adcli_enroll_get_permitted_keytab_encty.patch b/SOURCES/0003-adenroll-add-adcli_enroll_get_permitted_keytab_encty.patch deleted file mode 100644 index f810c13..0000000 --- a/SOURCES/0003-adenroll-add-adcli_enroll_get_permitted_keytab_encty.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0c09070e8beec734e3f0c70e14b0a04788077b73 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 13 Jun 2019 17:25:52 +0200 -Subject: [PATCH 3/4] adenroll: add adcli_enroll_get_permitted_keytab_enctypes - with tests - -The new call does not only return the current encryption types set in AD -or a default list but filters them with the list of permitted encryption -types on the client. This makes sure the client can create and use the -keys. - -Related to https://gitlab.freedesktop.org/realmd/adcli/issues/3 ---- - library/Makefile.am | 5 ++ - library/adenroll.c | 124 ++++++++++++++++++++++++++++++++++++++++++++ - library/adenroll.h | 2 + - 3 files changed, 131 insertions(+) - -diff --git a/library/Makefile.am b/library/Makefile.am -index 39e8fd1..4829555 100644 ---- a/library/Makefile.am -+++ b/library/Makefile.am -@@ -40,6 +40,7 @@ check_PROGRAMS = \ - test-util \ - test-ldap \ - test-attrs \ -+ test-adenroll \ - $(NULL) - - test_seq_SOURCES = seq.c test.c test.h -@@ -56,6 +57,10 @@ test_attrs_SOURCES = adattrs.c $(test_ldap_SOURCES) - test_attrs_CFLAGS = -DATTRS_TESTS - test_attrs_LDADD = $(test_ldap_LDADD) - -+test_adenroll_SOURCES = adenroll.c $(test_ldap_SOURCES) -+test_adenroll_CFLAGS = -DADENROLL_TESTS -+test_adenroll_LDADD = $(KRB5_LIBS) -+ - TESTS = $(check_PROGRAMS) - - MEMCHECK_ENV = $(TEST_RUNNER) valgrind --error-exitcode=80 --quiet --trace-children=yes -diff --git a/library/adenroll.c b/library/adenroll.c -index f617f28..95c07cd 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -2641,6 +2641,50 @@ adcli_enroll_get_keytab_enctypes (adcli_enroll *enroll) - return v51_earlier_enctypes; - } - -+krb5_enctype * -+adcli_enroll_get_permitted_keytab_enctypes (adcli_enroll *enroll) -+{ -+ krb5_enctype *cur_enctypes; -+ krb5_enctype *permitted_enctypes; -+ krb5_enctype *new_enctypes; -+ krb5_error_code code; -+ krb5_context k5; -+ size_t c; -+ size_t p; -+ size_t n; -+ -+ return_val_if_fail (enroll != NULL, NULL); -+ cur_enctypes = adcli_enroll_get_keytab_enctypes (enroll); -+ -+ k5 = adcli_conn_get_krb5_context (enroll->conn); -+ return_val_if_fail (k5 != NULL, NULL); -+ -+ code = krb5_get_permitted_enctypes (k5, &permitted_enctypes); -+ return_val_if_fail (code == 0, NULL); -+ -+ for (c = 0; cur_enctypes[c] != 0; c++); -+ -+ new_enctypes = calloc (c + 1, sizeof (krb5_enctype)); -+ return_val_if_fail (new_enctypes != NULL, NULL); -+ -+ n = 0; -+ for (c = 0; cur_enctypes[c] != 0; c++) { -+ for (p = 0; permitted_enctypes[p] != 0; p++) { -+ if (cur_enctypes[c] == permitted_enctypes[p]) { -+ new_enctypes[n++] = cur_enctypes[c]; -+ break; -+ } -+ } -+ if (permitted_enctypes[p] == 0) { -+ _adcli_info ("Encryption type [%d] not permitted.", cur_enctypes[c]); -+ } -+ } -+ -+ krb5_free_enctypes (k5, permitted_enctypes); -+ -+ return new_enctypes; -+} -+ - void - adcli_enroll_set_keytab_enctypes (adcli_enroll *enroll, - krb5_enctype *value) -@@ -2833,3 +2877,83 @@ adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll, - strdup (value), NULL); - return_if_fail (enroll->service_principals_to_remove != NULL); - } -+ -+#ifdef ADENROLL_TESTS -+ -+#include "test.h" -+ -+static void -+test_adcli_enroll_get_permitted_keytab_enctypes (void) -+{ -+ krb5_enctype *enctypes; -+ krb5_error_code code; -+ krb5_enctype *permitted_enctypes; -+ krb5_enctype check_enctypes[3] = { 0 }; -+ adcli_conn *conn; -+ adcli_enroll *enroll; -+ adcli_result res; -+ krb5_context k5; -+ size_t c; -+ -+ conn = adcli_conn_new ("test.dom"); -+ assert_ptr_not_null (conn); -+ -+ enroll = adcli_enroll_new (conn); -+ assert_ptr_not_null (enroll); -+ -+ enctypes = adcli_enroll_get_permitted_keytab_enctypes (NULL); -+ assert_ptr_eq (enctypes, NULL); -+ -+ /* krb5 context missing */ -+ enctypes = adcli_enroll_get_permitted_keytab_enctypes (enroll); -+ assert_ptr_eq (enctypes, NULL); -+ -+ /* check that all permitted enctypes can pass */ -+ res = _adcli_krb5_init_context (&k5); -+ assert_num_eq (res, ADCLI_SUCCESS); -+ -+ adcli_conn_set_krb5_context (conn, k5); -+ -+ code = krb5_get_permitted_enctypes (k5, &permitted_enctypes); -+ assert_num_eq (code, 0); -+ assert_ptr_not_null (permitted_enctypes); -+ assert_num_cmp (permitted_enctypes[0], !=, 0); -+ -+ adcli_enroll_set_keytab_enctypes (enroll, permitted_enctypes); -+ -+ enctypes = adcli_enroll_get_permitted_keytab_enctypes (enroll); -+ assert_ptr_not_null (enctypes); -+ for (c = 0; permitted_enctypes[c] != 0; c++) { -+ assert_num_eq (enctypes[c], permitted_enctypes[c]); -+ } -+ assert_num_eq (enctypes[c], 0); -+ krb5_free_enctypes (k5, enctypes); -+ -+ /* check that ENCTYPE_UNKNOWN is filtered out */ -+ check_enctypes[0] = permitted_enctypes[0]; -+ check_enctypes[1] = ENCTYPE_UNKNOWN; -+ check_enctypes[2] = 0; -+ adcli_enroll_set_keytab_enctypes (enroll, check_enctypes); -+ -+ enctypes = adcli_enroll_get_permitted_keytab_enctypes (enroll); -+ assert_ptr_not_null (enctypes); -+ assert_num_eq (enctypes[0], permitted_enctypes[0]); -+ assert_num_eq (enctypes[1], 0); -+ krb5_free_enctypes (k5, enctypes); -+ -+ krb5_free_enctypes (k5, permitted_enctypes); -+ -+ adcli_enroll_unref (enroll); -+ adcli_conn_unref (conn); -+} -+ -+int -+main (int argc, -+ char *argv[]) -+{ -+ test_func (test_adcli_enroll_get_permitted_keytab_enctypes, -+ "/attrs/adcli_enroll_get_permitted_keytab_enctypes"); -+ return test_run (argc, argv); -+} -+ -+#endif /* ADENROLL_TESTS */ -diff --git a/library/adenroll.h b/library/adenroll.h -index abbbfd4..1d5d00d 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -138,6 +138,8 @@ krb5_enctype * adcli_enroll_get_keytab_enctypes (adcli_enroll *enroll); - void adcli_enroll_set_keytab_enctypes (adcli_enroll *enroll, - krb5_enctype *enctypes); - -+krb5_enctype * adcli_enroll_get_permitted_keytab_enctypes (adcli_enroll *enroll); -+ - const char * adcli_enroll_get_os_name (adcli_enroll *enroll); - - void adcli_enroll_set_os_name (adcli_enroll *enroll, --- -2.21.0 - diff --git a/SOURCES/0003-correct-spelling-of-adcli_tool_computer_delete-descr.patch b/SOURCES/0003-correct-spelling-of-adcli_tool_computer_delete-descr.patch deleted file mode 100644 index 59fb6fe..0000000 --- a/SOURCES/0003-correct-spelling-of-adcli_tool_computer_delete-descr.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 85fa595baf689e85c0d897c5eef73fdf1ecc1581 Mon Sep 17 00:00:00 2001 -From: Striker Leggette -Date: Wed, 1 Nov 2017 11:16:39 +0100 -Subject: [PATCH 03/23] correct spelling of 'adcli_tool_computer_delete' - description - ---- - tools/tools.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/tools.c b/tools/tools.c -index 4b243de..915130e 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -57,7 +57,7 @@ struct { - { "update", adcli_tool_computer_update, "Update machine membership in a domain", }, - { "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", }, - { "reset-computer", adcli_tool_computer_reset, "Reset a computer account", }, -- { "delete-computer", adcli_tool_computer_delete, "Delete a computer acocunt", }, -+ { "delete-computer", adcli_tool_computer_delete, "Delete a computer account", }, - { "create-user", adcli_tool_user_create, "Create a user account", }, - { "delete-user", adcli_tool_user_delete, "Delete a user account", }, - { "create-group", adcli_tool_group_create, "Create a group", }, --- -2.14.4 - diff --git a/SOURCES/0003-enroll-use-computer-or-service-in-debug-messages.patch b/SOURCES/0003-enroll-use-computer-or-service-in-debug-messages.patch deleted file mode 100644 index 4e5aea5..0000000 --- a/SOURCES/0003-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 3/7] 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/SOURCES/0003-entry-add-passwd-user-sub-command.patch b/SOURCES/0003-entry-add-passwd-user-sub-command.patch deleted file mode 100644 index 413d7ab..0000000 --- a/SOURCES/0003-entry-add-passwd-user-sub-command.patch +++ /dev/null @@ -1,366 +0,0 @@ -From 6a673b236dfdfdf9c73cc3d2ccf3949eb1a5ddd0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 11 Jun 2021 12:47:37 +0200 -Subject: [PATCH 3/3] entry: add passwd-user sub-command - -The new command allows to set or reset a user password with the help of -an account privileged to set the password. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1952828 ---- - doc/adcli.xml | 20 +++++++ - library/adentry.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++ - library/adentry.h | 3 + - tools/entry.c | 99 +++++++++++++++++++++++++++++++++ - tools/tools.c | 1 + - tools/tools.h | 4 ++ - 6 files changed, 265 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 1ed5d3f..6c36297 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -56,6 +56,11 @@ - --domain=domain.example.com - user - -+ -+ adcli passwd-user -+ --domain=domain.example.com -+ user -+ - - adcli create-group - --domain=domain.example.com -@@ -696,6 +701,21 @@ $ adcli delete-user Fry --domain=domain.example.com - - - -+ -+ (Re)setting the password of a User with an Administrative Account -+ -+ adcli passwd-user sets or resets the password -+ of user account. The administrative account used for this operation -+ must have privileges to set a password. -+ -+ -+$ adcli passwd-user Fry --domain=domain.example.com -+ -+ -+ The various global options can be used. -+ -+ -+ - - - Creating a Group -diff --git a/library/adentry.c b/library/adentry.c -index 13dcaf8..0d9b9af 100644 ---- a/library/adentry.c -+++ b/library/adentry.c -@@ -409,6 +409,144 @@ adcli_entry_delete (adcli_entry *entry) - return ADCLI_SUCCESS; - } - -+static adcli_result -+adcli_entry_ensure_enabled (adcli_entry *entry) -+{ -+ adcli_result res; -+ LDAP *ldap; -+ adcli_attrs *attrs; -+ uint32_t uac = 0; -+ char *uac_str; -+ unsigned long attr_val; -+ char *end; -+ -+ return_unexpected_if_fail (entry->entry_attrs != NULL); -+ -+ ldap = adcli_conn_get_ldap_connection (entry->conn); -+ return_unexpected_if_fail (ldap != NULL); -+ -+ uac_str = _adcli_ldap_parse_value (ldap, entry->entry_attrs, -+ "userAccountControl"); -+ if (uac_str != NULL) { -+ attr_val = strtoul (uac_str, &end, 10); -+ if (*end != '\0' || attr_val > UINT32_MAX) { -+ _adcli_warn ("Invalid userAccountControl '%s' for %s account in directory: %s, assuming 0", -+ uac_str, entry->object_class, entry->entry_dn); -+ } else { -+ uac = attr_val; -+ } -+ free (uac_str); -+ } -+ if (uac & UAC_ACCOUNTDISABLE) { -+ uac &= ~(UAC_ACCOUNTDISABLE); -+ -+ if (asprintf (&uac_str, "%d", uac) < 0) { -+ _adcli_warn ("Cannot enable %s entry %s after password (re)set", -+ entry->object_class, entry->entry_dn); -+ return ADCLI_ERR_UNEXPECTED; -+ } -+ -+ attrs = adcli_attrs_new (); -+ adcli_attrs_replace (attrs, "userAccountControl", uac_str, -+ NULL); -+ res = adcli_entry_modify (entry, attrs); -+ if (res == ADCLI_SUCCESS) { -+ _adcli_info ("Enabled %s entry %s after password (re)set", -+ entry->object_class, entry->entry_dn); -+ } else { -+ _adcli_warn ("Failed to enable %s entry %s after password (re)set", -+ entry->object_class, entry->entry_dn); -+ } -+ free (uac_str); -+ adcli_attrs_free (attrs); -+ } else { -+ res = ADCLI_SUCCESS; -+ } -+ -+ return res; -+} -+ -+adcli_result -+adcli_entry_set_passwd (adcli_entry *entry, const char *user_pwd) -+{ -+ adcli_result res; -+ LDAP *ldap; -+ krb5_error_code code; -+ krb5_context k5; -+ krb5_ccache ccache; -+ krb5_data result_string = { 0, }; -+ krb5_data result_code_string = { 0, }; -+ int result_code; -+ char *message; -+ krb5_principal user_principal; -+ -+ ldap = adcli_conn_get_ldap_connection (entry->conn); -+ return_unexpected_if_fail (ldap != NULL); -+ -+ /* Find the user */ -+ res = update_entry_from_domain (entry, ldap); -+ if (res != ADCLI_SUCCESS) -+ return res; -+ -+ if (!entry->entry_dn) { -+ _adcli_err ("Cannot find the %s entry %s in the domain", -+ entry->object_class, entry->sam_name); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ k5 = adcli_conn_get_krb5_context (entry->conn); -+ return_unexpected_if_fail (k5 != NULL); -+ -+ code = _adcli_krb5_build_principal (k5, entry->sam_name, -+ adcli_conn_get_domain_realm (entry->conn), -+ &user_principal); -+ return_unexpected_if_fail (code == 0); -+ -+ ccache = adcli_conn_get_login_ccache (entry->conn); -+ return_unexpected_if_fail (ccache != NULL); -+ -+ memset (&result_string, 0, sizeof (result_string)); -+ memset (&result_code_string, 0, sizeof (result_code_string)); -+ -+ code = krb5_set_password_using_ccache (k5, ccache, user_pwd, -+ user_principal, &result_code, -+ &result_code_string, &result_string); -+ -+ if (code != 0) { -+ _adcli_err ("Couldn't set password for %s account: %s: %s", -+ entry->object_class, -+ entry->sam_name, krb5_get_error_message (k5, code)); -+ /* TODO: Parse out these values */ -+ res = ADCLI_ERR_DIRECTORY; -+ -+ } else if (result_code != 0) { -+#ifdef HAVE_KRB5_CHPW_MESSAGE -+ if (krb5_chpw_message (k5, &result_string, &message) != 0) -+ message = NULL; -+#else -+ message = NULL; -+ if (result_string.length) -+ message = _adcli_str_dupn (result_string.data, result_string.length); -+#endif -+ _adcli_err ("Cannot set %s password: %.*s%s%s", -+ entry->object_class, -+ (int)result_code_string.length, result_code_string.data, -+ message ? ": " : "", message ? message : ""); -+ res = ADCLI_ERR_CREDENTIALS; -+#ifdef HAVE_KRB5_CHPW_MESSAGE -+ krb5_free_string (k5, message); -+#else -+ free (message); -+#endif -+ } else { -+ _adcli_info ("Password (re)setted for %s: %s", entry->object_class, entry->entry_dn); -+ -+ res = adcli_entry_ensure_enabled (entry); -+ } -+ -+ return res; -+} -+ - const char * - adcli_entry_get_sam_name (adcli_entry *entry) - { -diff --git a/library/adentry.h b/library/adentry.h -index ae90689..f2382b1 100644 ---- a/library/adentry.h -+++ b/library/adentry.h -@@ -49,6 +49,9 @@ adcli_result adcli_entry_modify (adcli_entry *entry, - - adcli_result adcli_entry_delete (adcli_entry *entry); - -+adcli_result adcli_entry_set_passwd (adcli_entry *entry, -+ const char *user_pwd); -+ - const char * adcli_entry_get_domain_ou (adcli_entry *entry); - - void adcli_entry_set_domain_ou (adcli_entry *entry, -diff --git a/tools/entry.c b/tools/entry.c -index 05e4313..52d2546 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -24,6 +24,7 @@ - #include "config.h" - - #include "adcli.h" -+#include "adprivate.h" - #include "adattrs.h" - #include "tools.h" - -@@ -385,6 +386,104 @@ adcli_tool_user_delete (adcli_conn *conn, - return 0; - } - -+int -+adcli_tool_user_passwd (adcli_conn *conn, -+ int argc, -+ char *argv[]) -+{ -+ adcli_result res; -+ adcli_entry *entry; -+ int opt; -+ char *user_pwd = NULL; -+ -+ 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 }, -+ { "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 passwd-user --domain=xxxx user" }, -+ { 0 }, -+ }; -+ -+ 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); -+ return opt == 'h' ? 0 : 2; -+ default: -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ break; -+ } -+ } -+ -+ argc -= optind; -+ argv += optind; -+ -+ if (argc != 1) { -+ warnx ("specify one user name to (re)set password"); -+ return 2; -+ } -+ -+ entry = adcli_entry_new_user (conn, argv[0]); -+ if (entry == NULL) { -+ warnx ("unexpected memory problems"); -+ return -1; -+ } -+ -+ adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); -+ -+ 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_entry_unref (entry); -+ return -res; -+ } -+ -+ user_pwd = adcli_prompt_password_func (ADCLI_LOGIN_USER_ACCOUNT, -+ adcli_entry_get_sam_name(entry), -+ 0, NULL); -+ if (user_pwd == NULL || *user_pwd == '\0') { -+ warnx ("missing password"); -+ _adcli_password_free (user_pwd); -+ adcli_entry_unref (entry); -+ return 2; -+ } -+ -+ res = adcli_entry_set_passwd (entry, user_pwd); -+ _adcli_password_free (user_pwd); -+ if (res != ADCLI_SUCCESS) { -+ warnx ("(re)setting password for user %s in domain %s failed: %s", -+ adcli_entry_get_sam_name (entry), -+ adcli_conn_get_domain_name (conn), -+ adcli_get_last_error ()); -+ adcli_entry_unref (entry); -+ return -res; -+ } -+ -+ adcli_entry_unref (entry); -+ -+ return 0; -+} -+ - int - adcli_tool_group_create (adcli_conn *conn, - int argc, -diff --git a/tools/tools.c b/tools/tools.c -index 84bbba9..a14b9ca 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -63,6 +63,7 @@ struct { - { "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", }, -+ { "passwd-user", adcli_tool_user_passwd, "(Re)set a user password", }, - { "create-group", adcli_tool_group_create, "Create a group", }, - { "delete-group", adcli_tool_group_delete, "Delete a group", }, - { "add-member", adcli_tool_member_add, "Add users to a group", }, -diff --git a/tools/tools.h b/tools/tools.h -index 82d5e4e..d38aa32 100644 ---- a/tools/tools.h -+++ b/tools/tools.h -@@ -94,6 +94,10 @@ int adcli_tool_user_delete (adcli_conn *conn, - int argc, - char *argv[]); - -+int adcli_tool_user_passwd (adcli_conn *conn, -+ int argc, -+ char *argv[]); -+ - int adcli_tool_group_create (adcli_conn *conn, - int argc, - char *argv[]); --- -2.31.1 - diff --git a/SOURCES/0003-library-_adcli_krb5_build_principal-allow-principals.patch b/SOURCES/0003-library-_adcli_krb5_build_principal-allow-principals.patch deleted file mode 100644 index 217636c..0000000 --- a/SOURCES/0003-library-_adcli_krb5_build_principal-allow-principals.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 10a4dbb5978b6f05cf75f820d97da908e735ace8 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 22 Mar 2019 10:37:11 +0100 -Subject: [PATCH 3/4] library: _adcli_krb5_build_principal allow principals as - names - -Make _adcli_krb5_build_principal a bit more robust by checking if the -given name already contains a realm suffix. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187 ---- - library/adkrb5.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/library/adkrb5.c b/library/adkrb5.c -index 7f77373..da835d7 100644 ---- a/library/adkrb5.c -+++ b/library/adkrb5.c -@@ -41,12 +41,16 @@ _adcli_krb5_build_principal (krb5_context k5, - krb5_principal *principal) - { - krb5_error_code code; -- char *name; -+ char *name = NULL; - -- if (asprintf (&name, "%s@%s", user, realm) < 0) -- return_val_if_reached (ENOMEM); -+ /* Use user if user contains a @-character and add @realm otherwise */ -+ if (strchr (user, '@') == NULL) { -+ if (asprintf (&name, "%s@%s", user, realm) < 0) { -+ return_val_if_reached (ENOMEM); -+ } -+ } - -- code = krb5_parse_name (k5, name, principal); -+ code = krb5_parse_name (k5, name != NULL ? name : user, principal); - return_val_if_fail (code == 0, code); - - free (name); --- -2.20.1 - diff --git a/SOURCES/0003-tools-remove-errx-from-info-commands.patch b/SOURCES/0003-tools-remove-errx-from-info-commands.patch deleted file mode 100644 index c53cf50..0000000 --- a/SOURCES/0003-tools-remove-errx-from-info-commands.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 4794812cc98c8783921f534d20dae8b44f3826d2 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Apr 2019 17:57:37 +0200 -Subject: [PATCH 3/7] tools: remove errx from info commands - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/info.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/tools/info.c b/tools/info.c -index e7e20ad..c63e0ff 100644 ---- a/tools/info.c -+++ b/tools/info.c -@@ -162,21 +162,28 @@ adcli_tool_info (adcli_conn *unused, - - if (argc == 1) - domain = argv[0]; -- else if (argc != 0) -- errx (2, "specify one user name to create"); -+ else if (argc != 0) { -+ warnx ("specify one user name to create"); -+ return 2; -+ } - - if (server) { - adcli_disco_host (server, &disco); -- if (disco == NULL) -- errx (1, "couldn't discover domain controller: %s", server); -+ if (disco == NULL) { -+ warnx ("couldn't discover domain controller: %s", server); -+ return 1; -+ } - for_host = 1; - } else if (domain) { - adcli_disco_domain (domain, &disco); -- if (disco == NULL) -- errx (1, "couldn't discover domain: %s", domain); -+ if (disco == NULL) { -+ warnx ("couldn't discover domain: %s", domain); -+ return 1; -+ } - for_host = 0; - } else { -- errx (2, "specify a domain to discover"); -+ warnx ("specify a domain to discover"); -+ return 2; - } - - print_info (disco, for_host); --- -2.20.1 - diff --git a/SOURCES/0004-Do-not-depend-on-default_realm-in-krb5.conf.patch b/SOURCES/0004-Do-not-depend-on-default_realm-in-krb5.conf.patch deleted file mode 100644 index d12f335..0000000 --- a/SOURCES/0004-Do-not-depend-on-default_realm-in-krb5.conf.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 8f726817b9ff643a382fa12ea9ff489cd5ab9068 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 13 Aug 2018 18:24:58 +0200 -Subject: [PATCH 4/4] Do not depend on default_realm in krb5.conf - ---- - library/adenroll.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index bb50365..02bd9e3 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1661,7 +1661,9 @@ remove_principal_from_keytab (adcli_enroll *enroll, - krb5_principal principal; - match_principal_kvno closure; - -- code = krb5_parse_name (k5, principal_name, &principal); -+ code = _adcli_krb5_build_principal (k5, principal_name, -+ adcli_conn_get_domain_realm (enroll->conn), -+ &principal); - if (code != 0) { - _adcli_err ("Couldn't parse principal: %s: %s", - principal_name, krb5_get_error_message (k5, code)); --- -2.17.1 - diff --git a/SOURCES/0004-adenroll-use-only-enctypes-permitted-by-Kerberos-con.patch b/SOURCES/0004-adenroll-use-only-enctypes-permitted-by-Kerberos-con.patch deleted file mode 100644 index a496e32..0000000 --- a/SOURCES/0004-adenroll-use-only-enctypes-permitted-by-Kerberos-con.patch +++ /dev/null @@ -1,103 +0,0 @@ -From cc3ef52884a48863a81acbfc741735fe09cd85f7 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 13 Jun 2019 18:27:49 +0200 -Subject: [PATCH 4/4] adenroll: use only enctypes permitted by Kerberos config - -Realted to https://gitlab.freedesktop.org/realmd/adcli/issues/3 ---- - doc/adcli.xml | 10 ++++++++++ - library/adenroll.c | 22 +++++++++++++++++++--- - 2 files changed, 29 insertions(+), 3 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 9605b4a..094f577 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -342,6 +342,11 @@ Password for Administrator: - - - -+ If supported on the AD side the -+ attribute will be set as -+ well. Either the current value or the default list of AD's supported -+ encryption types filtered by the permitted encryption types of the -+ client's Kerberos configuration are written. - - - -@@ -475,6 +480,11 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - - - -+ If supported on the AD side the -+ attribute will be set as -+ well. Either the current value or the default list of AD's supported -+ encryption types filtered by the permitted encryption types of the -+ client's Kerberos configuration are written. - - - -diff --git a/library/adenroll.c b/library/adenroll.c -index 95c07cd..53cd812 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -639,6 +639,7 @@ calculate_enctypes (adcli_enroll *enroll, char **enctype) - { - char *value = NULL; - krb5_enctype *read_enctypes; -+ krb5_enctype *new_enctypes; - char *new_value = NULL; - int is_2008_or_later; - LDAP *ldap; -@@ -685,7 +686,14 @@ calculate_enctypes (adcli_enroll *enroll, char **enctype) - value = _adcli_krb5_format_enctypes (v51_earlier_enctypes); - } - -- new_value = _adcli_krb5_format_enctypes (adcli_enroll_get_keytab_enctypes (enroll)); -+ new_enctypes = adcli_enroll_get_permitted_keytab_enctypes (enroll); -+ if (new_enctypes == NULL) { -+ _adcli_warn ("No permitted encryption type found."); -+ return ADCLI_ERR_UNEXPECTED; -+ } -+ -+ new_value = _adcli_krb5_format_enctypes (new_enctypes); -+ krb5_free_enctypes (adcli_conn_get_krb5_context (enroll->conn), new_enctypes); - if (new_value == NULL) { - free (value); - _adcli_warn ("The encryption types desired are not available in active directory"); -@@ -1758,7 +1766,11 @@ add_principal_to_keytab (adcli_enroll *enroll, - enroll->keytab_name); - } - -- enctypes = adcli_enroll_get_keytab_enctypes (enroll); -+ enctypes = adcli_enroll_get_permitted_keytab_enctypes (enroll); -+ if (enctypes == NULL) { -+ _adcli_warn ("No permitted encryption type found."); -+ return ADCLI_ERR_UNEXPECTED; -+ } - - if (flags & ADCLI_ENROLL_PASSWORD_VALID) { - code = _adcli_krb5_keytab_copy_entries (k5, enroll->keytab, principal, -@@ -1774,7 +1786,10 @@ add_principal_to_keytab (adcli_enroll *enroll, - */ - - salts = build_principal_salts (enroll, k5, principal); -- return_unexpected_if_fail (salts != NULL); -+ if (salts == NULL) { -+ krb5_free_enctypes (k5, enctypes); -+ return ADCLI_ERR_UNEXPECTED; -+ } - - if (*which_salt < 0) { - code = _adcli_krb5_keytab_discover_salt (k5, principal, enroll->kvno, &password, -@@ -1794,6 +1809,7 @@ add_principal_to_keytab (adcli_enroll *enroll, - - free_principal_salts (k5, salts); - } -+ krb5_free_enctypes (k5, enctypes); - - if (code != 0) { - _adcli_err ("Couldn't add keytab entries: %s: %s", --- -2.21.0 - diff --git a/SOURCES/0004-doc-explain-that-all-credential-cache-types-are-supp.patch b/SOURCES/0004-doc-explain-that-all-credential-cache-types-are-supp.patch deleted file mode 100644 index e0dbc67..0000000 --- a/SOURCES/0004-doc-explain-that-all-credential-cache-types-are-supp.patch +++ /dev/null @@ -1,37 +0,0 @@ -From c3ec5121c1e79344ce615612ab3b576bc4745acb Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 1 Nov 2017 12:01:18 +0100 -Subject: [PATCH 04/23] doc: explain that all credential cache types are - supported - ---- - doc/adcli.xml | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index e18ba5d..c54cc1b 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -118,11 +118,15 @@ - is automatically discovered. - - -- -+ - Use the specified kerberos credential -- cache to authenticate with the domain. If no file is specified or -- is used, then the default kerberos credential cache will -- be used. -+ 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. - - - --- -2.14.4 - diff --git a/SOURCES/0004-enroll-more-filters-for-random-characters.patch b/SOURCES/0004-enroll-more-filters-for-random-characters.patch deleted file mode 100644 index 911e229..0000000 --- a/SOURCES/0004-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 4/7] 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/SOURCES/0004-library-make-sure-server-side-SPNs-are-preserved.patch b/SOURCES/0004-library-make-sure-server-side-SPNs-are-preserved.patch deleted file mode 100644 index 07cc8fb..0000000 --- a/SOURCES/0004-library-make-sure-server-side-SPNs-are-preserved.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 972f1a2f35829ed89f5353bd204683aa9ad6a2d2 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 22 Mar 2019 10:37:57 +0100 -Subject: [PATCH 4/4] library: make sure server side SPNs are preserved - -adcli should not delete service principal names (SPNs) unexpectedly. If -a SPN was added on the server while presetting a host or updating an -existing entry and upcoming adcli join or update should preserver this -change. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1630187 ---- - library/adenroll.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 48cb4cf..1cce86a 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1961,6 +1961,47 @@ adcli_enroll_prepare (adcli_enroll *enroll, - return res; - } - -+static adcli_result -+add_server_side_service_principals (adcli_enroll *enroll) -+{ -+ char **spn_list; -+ LDAP *ldap; -+ size_t c; -+ int length = 0; -+ adcli_result res; -+ -+ ldap = adcli_conn_get_ldap_connection (enroll->conn); -+ assert (ldap != NULL); -+ -+ spn_list = _adcli_ldap_parse_values (ldap, enroll->computer_attributes, -+ "servicePrincipalName"); -+ if (spn_list == NULL) { -+ return ADCLI_SUCCESS; -+ } -+ -+ if (enroll->service_principals != NULL) { -+ length = seq_count (enroll->service_principals); -+ } -+ -+ for (c = 0; spn_list[c] != NULL; c++) { -+ _adcli_info ("Checking %s", spn_list[c]); -+ if (!_adcli_strv_has_ex (enroll->service_principals_to_remove, spn_list[c], strcasecmp)) { -+ enroll->service_principals = _adcli_strv_add_unique (enroll->service_principals, -+ spn_list[c], &length, false); -+ assert (enroll->service_principals != NULL); -+ _adcli_info (" Added %s", spn_list[c]); -+ } -+ } -+ _adcli_strv_free (spn_list); -+ -+ res = ensure_keytab_principals (ADCLI_SUCCESS, enroll); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ -+ return ADCLI_SUCCESS; -+} -+ - static adcli_result - enroll_join_or_update_tasks (adcli_enroll *enroll, - adcli_enroll_flags flags) -@@ -2019,6 +2060,11 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - update_and_calculate_enctypes (enroll); - update_computer_account (enroll); - -+ res = add_server_side_service_principals (enroll); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ - /* service_names is only set from input on the command line, so no - * additional check for explicit is needed here */ - if (enroll->service_names != NULL) { --- -2.20.1 - diff --git a/SOURCES/0004-tools-remove-errx-from-adcli_read_password_func.patch b/SOURCES/0004-tools-remove-errx-from-adcli_read_password_func.patch deleted file mode 100644 index 1b53d7d..0000000 --- a/SOURCES/0004-tools-remove-errx-from-adcli_read_password_func.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 251d7d0c71226afb8e51f7bc5794a7a3164f5a20 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Apr 2019 17:59:17 +0200 -Subject: [PATCH 4/7] tools: remove errx from adcli_read_password_func - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/tools.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/tools/tools.c b/tools/tools.c -index c4e2851..bdf6d38 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -247,7 +247,9 @@ adcli_read_password_func (adcli_login_type login_type, - if (res < 0) { - if (errno == EAGAIN || errno == EINTR) - continue; -- err (EFAIL, "couldn't read password from stdin"); -+ warn ("couldn't read password from stdin"); -+ free (buffer); -+ return NULL; - - } else if (res == 0) { - buffer[offset] = '\0'; -@@ -261,8 +263,11 @@ adcli_read_password_func (adcli_login_type login_type, - return buffer; - - } else { -- if (memchr (buffer + offset, 0, res)) -- errx (EUSAGE, "unsupported null character present in password"); -+ if (memchr (buffer + offset, 0, res)) { -+ warnx ("unsupported null character present in password"); -+ free (buffer); -+ return NULL; -+ } - offset += res; - } - } --- -2.20.1 - diff --git a/SOURCES/0005-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch b/SOURCES/0005-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch deleted file mode 100644 index 4da2d9d..0000000 --- a/SOURCES/0005-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 5/7] 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/SOURCES/0005-library-add-adcli_conn_is_writeable.patch b/SOURCES/0005-library-add-adcli_conn_is_writeable.patch deleted file mode 100644 index 832bb0f..0000000 --- a/SOURCES/0005-library-add-adcli_conn_is_writeable.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d2cdc54b0e51436c30ffaf19b0530aa446440367 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 1 Nov 2017 16:29:19 +0100 -Subject: [PATCH 05/23] library: add adcli_conn_is_writeable() - ---- - library/adconn.c | 6 ++++++ - library/adconn.h | 2 ++ - 2 files changed, 8 insertions(+) - -diff --git a/library/adconn.c b/library/adconn.c -index a294dfd..67bdfd9 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -1528,3 +1528,9 @@ adcli_conn_server_has_capability (adcli_conn *conn, - - return 0; - } -+ -+bool adcli_conn_is_writeable (adcli_conn *conn) -+{ -+ disco_dance_if_necessary (conn); -+ return ( (conn->domain_disco->flags & ADCLI_DISCO_WRITABLE) != 0); -+} -diff --git a/library/adconn.h b/library/adconn.h -index a0cb1f8..ed1cc58 100644 ---- a/library/adconn.h -+++ b/library/adconn.h -@@ -144,4 +144,6 @@ void adcli_conn_set_krb5_conf_dir (adcli_conn *conn, - int adcli_conn_server_has_capability (adcli_conn *conn, - const char *capability); - -+bool adcli_conn_is_writeable (adcli_conn *conn); -+ - #endif /* ADCONN_H_ */ --- -2.14.4 - diff --git a/SOURCES/0005-tools-remove-errx-from-setup_krb5_conf_directory.patch b/SOURCES/0005-tools-remove-errx-from-setup_krb5_conf_directory.patch deleted file mode 100644 index 8fd9197..0000000 --- a/SOURCES/0005-tools-remove-errx-from-setup_krb5_conf_directory.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b8f5d995d30c17eb8bec3ac5e0777ea94f5b76c3 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 15 Apr 2019 18:00:52 +0200 -Subject: [PATCH 5/7] tools: remove errx from setup_krb5_conf_directory - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/tools.c | 38 ++++++++++++++++++++++++-------------- - 1 file changed, 24 insertions(+), 14 deletions(-) - -diff --git a/tools/tools.c b/tools/tools.c -index bdf6d38..fc9fa9a 100644 ---- a/tools/tools.c -+++ b/tools/tools.c -@@ -327,21 +327,31 @@ setup_krb5_conf_directory (adcli_conn *conn) - } - - if (asprintf (&directory, "%s%sadcli-krb5-XXXXXX", parent, -- (parent[0] && parent[strlen(parent) - 1] == '/') ? "" : "/") < 0) -- errx (1, "unexpected: out of memory"); -- -- if (mkdtemp (directory) == NULL) { -- errn = errno; -+ (parent[0] && parent[strlen(parent) - 1] == '/') ? "" : "/") < 0) { -+ warnx ("unexpected: out of memory"); -+ directory = NULL; /* content is undefined */ - failed = 1; -- warnx ("couldn't create temporary directory in: %s: %s", -- parent, strerror (errn)); -- } else { -- if (asprintf (&filename, "%s/krb5.conf", directory) < 0 || -- asprintf (&snippets, "%s/krb5.d", directory) < 0 || -- asprintf (&contents, "includedir %s\n%s%s\n", snippets, -- krb5_conf ? "include " : "", -- krb5_conf ? krb5_conf : "") < 0) -- errx (1, "unexpected: out of memory"); -+ } -+ -+ if (!failed) { -+ if (mkdtemp (directory) == NULL) { -+ errn = errno; -+ failed = 1; -+ warnx ("couldn't create temporary directory in: %s: %s", -+ parent, strerror (errn)); -+ } else { -+ if (asprintf (&filename, "%s/krb5.conf", directory) < 0 || -+ asprintf (&snippets, "%s/krb5.d", directory) < 0 || -+ asprintf (&contents, "includedir %s\n%s%s\n", snippets, -+ krb5_conf ? "include " : "", -+ krb5_conf ? krb5_conf : "") < 0) { -+ warnx ("unexpected: out of memory"); -+ filename = NULL; /* content is undefined */ -+ snippets = NULL; /* content is undefined */ -+ contents = NULL; /* content is undefined */ -+ failed = 1; -+ } -+ } - } - - if (!failed) { --- -2.20.1 - diff --git a/SOURCES/0006-Handle-kvno-increment-for-RODCs.patch b/SOURCES/0006-Handle-kvno-increment-for-RODCs.patch deleted file mode 100644 index 90f05a4..0000000 --- a/SOURCES/0006-Handle-kvno-increment-for-RODCs.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 6b60f4c08d811e4bc3a68d1a4770c2ce5619c890 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 1 Nov 2017 17:14:05 +0100 -Subject: [PATCH 06/23] Handle kvno increment for RODCs - -Since the actual password change does not happen on the read-only domain -controller (RODC) the kvno change has to be replicated back which might -take some time. So we check the kvno before and after the change if we -are connected to a RODC and increment the kvno if needed. ---- - library/adenroll.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 05885d0..bb970d1 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1633,8 +1633,30 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - adcli_enroll_flags flags) - { - adcli_result res; -+ krb5_kvno old_kvno = -1; - - if (!(flags & ADCLI_ENROLL_PASSWORD_VALID)) { -+ -+ /* Handle kvno changes for read-only domain controllers -+ * (RODC). Since the actual password change does not happen on -+ * the RODC the kvno change has to be replicated back which -+ * might take some time. So we check the kvno before and after -+ * the change if we are connected to a RODC and increment the -+ * kvno if needed. */ -+ if (!adcli_conn_is_writeable (enroll->conn)) { -+ if (enroll->computer_attributes == NULL) { -+ res = retrieve_computer_account (enroll); -+ if (res != ADCLI_SUCCESS) -+ return res; -+ } -+ old_kvno = adcli_enroll_get_kvno (enroll); -+ _adcli_info ("Found old kvno '%d'", old_kvno); -+ -+ ldap_msgfree (enroll->computer_attributes); -+ enroll->computer_attributes = NULL; -+ adcli_enroll_set_kvno (enroll, 0); -+ } -+ - res = set_computer_password (enroll); - if (res != ADCLI_SUCCESS) - return res; -@@ -1651,6 +1673,15 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - return res; - } - -+ /* Handle kvno changes for read-only domain controllers (RODC) */ -+ if (!adcli_conn_is_writeable (enroll->conn) && old_kvno != -1 && -+ adcli_enroll_get_kvno (enroll) != 0 && -+ adcli_enroll_get_kvno (enroll) == old_kvno) { -+ enroll->kvno++; -+ _adcli_info ("No kvno change detected on read-only DC, kvno " -+ "will be incremented by 1 to '%d'", enroll->kvno); -+ } -+ - /* We ignore failures of setting these fields */ - update_and_calculate_enctypes (enroll); - update_computer_account (enroll); --- -2.14.4 - diff --git a/SOURCES/0006-enroll-allow-fqdn-for-locate_computer_account.patch b/SOURCES/0006-enroll-allow-fqdn-for-locate_computer_account.patch deleted file mode 100644 index 9f6094a..0000000 --- a/SOURCES/0006-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 6/7] 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/SOURCES/0006-tools-entry-remove-errx-from-parse_option.patch b/SOURCES/0006-tools-entry-remove-errx-from-parse_option.patch deleted file mode 100644 index 17bb9c4..0000000 --- a/SOURCES/0006-tools-entry-remove-errx-from-parse_option.patch +++ /dev/null @@ -1,175 +0,0 @@ -From d9912e19e48ec482351b9c384140ad71922ec5c0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 8 Apr 2019 17:22:00 +0200 -Subject: [PATCH 6/7] tools: entry - remove errx from parse_option - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/entry.c | 70 ++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 47 insertions(+), 23 deletions(-) - -diff --git a/tools/entry.c b/tools/entry.c -index 97ec6e7..f361845 100644 ---- a/tools/entry.c -+++ b/tools/entry.c -@@ -81,7 +81,7 @@ static adcli_tool_desc common_usages[] = { - { 0 }, - }; - --static void -+static int - parse_option (Option opt, - const char *optarg, - adcli_conn *conn) -@@ -93,54 +93,58 @@ parse_option (Option opt, - switch (opt) { - case opt_login_ccache: - adcli_conn_set_login_ccache_name (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_login_user: - adcli_conn_set_login_user (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain: - adcli_conn_set_domain_name (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain_realm: - adcli_conn_set_domain_realm (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain_controller: - adcli_conn_set_domain_controller (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_no_password: - if (stdin_password || prompt_password) { -- errx (EUSAGE, "cannot use --no-password argument with %s", -- stdin_password ? "--stdin-password" : "--prompt-password"); -+ warnx ("cannot use --no-password argument with %s", -+ stdin_password ? "--stdin-password" : "--prompt-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, NULL, NULL, NULL); - no_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_prompt_password: - if (stdin_password || no_password) { -- errx (EUSAGE, "cannot use --prompt-password argument with %s", -- stdin_password ? "--stdin-password" : "--no-password"); -+ warnx ("cannot use --prompt-password argument with %s", -+ stdin_password ? "--stdin-password" : "--no-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, adcli_prompt_password_func, NULL, NULL); - prompt_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_stdin_password: - if (prompt_password || no_password) { -- errx (EUSAGE, "cannot use --stdin-password argument with %s", -- prompt_password ? "--prompt-password" : "--no-password"); -+ warnx ("cannot use --stdin-password argument with %s", -+ prompt_password ? "--prompt-password" : "--no-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, adcli_read_password_func, NULL, NULL); - stdin_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_verbose: -- return; -+ return ADCLI_SUCCESS; - default: - assert (0 && "not reached"); - break; - } - -- errx (EUSAGE, "failure to parse option '%c'", opt); -+ warnx ("failure to parse option '%c'", opt); -+ return EUSAGE; - } - - int -@@ -224,7 +228,11 @@ adcli_tool_user_create (adcli_conn *conn, - adcli_attrs_free (attrs); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ adcli_attrs_free (attrs); -+ return res; -+ } - break; - } - } -@@ -322,7 +330,10 @@ adcli_tool_user_delete (adcli_conn *conn, - adcli_tool_usage (options, common_usages); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } - break; - } - } -@@ -417,7 +428,11 @@ adcli_tool_group_create (adcli_conn *conn, - adcli_attrs_free (attrs); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ adcli_attrs_free (attrs); -+ return res; -+ } - break; - } - } -@@ -505,7 +520,10 @@ adcli_tool_group_delete (adcli_conn *conn, - adcli_tool_usage (options, common_usages); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } - break; - } - } -@@ -628,7 +646,10 @@ adcli_tool_member_add (adcli_conn *conn, - adcli_tool_usage (options, common_usages); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } - break; - } - } -@@ -725,7 +746,10 @@ adcli_tool_member_remove (adcli_conn *conn, - adcli_tool_usage (options, common_usages); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn); -+ res = parse_option ((Option)opt, optarg, conn); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } - break; - } - } --- -2.20.1 - diff --git a/SOURCES/0007-Fix-memory-leak-in-test_check_nt_time_string_lifetim.patch b/SOURCES/0007-Fix-memory-leak-in-test_check_nt_time_string_lifetim.patch deleted file mode 100644 index 18c8c9c..0000000 --- a/SOURCES/0007-Fix-memory-leak-in-test_check_nt_time_string_lifetim.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 3d312a6c89a88be444fb5ed768fbaa6155bf1cc9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:39:46 +0100 -Subject: [PATCH 07/23] Fix memory leak in test_check_nt_time_string_lifetime - -The test added with 650e5d33ef31437a049fb454ad3dc5457c56abe7 introduced -a small memory leak. - -Reviewed-by: Jakub Hrozek ---- - library/adutil.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/library/adutil.c b/library/adutil.c -index 21ccd27..cd40f45 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -501,6 +501,7 @@ test_check_nt_time_string_lifetime (void) - (time (NULL) + 10 + AD_TO_UNIX_TIME_CONST) * 1000 * 1000 *10) - != -1); - assert (!_adcli_check_nt_time_string_lifetime (time_str, 0)); -+ free (time_str); - - /* This test will fail some time after 2200AD as a reminder to reflect - * why adcli is still needed. */ --- -2.14.4 - diff --git a/SOURCES/0007-service-account-add-random-suffix-to-account-name.patch b/SOURCES/0007-service-account-add-random-suffix-to-account-name.patch deleted file mode 100644 index d2635ca..0000000 --- a/SOURCES/0007-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 7/7] 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/SOURCES/0007-tools-computer-remove-errx-from-parse_option.patch b/SOURCES/0007-tools-computer-remove-errx-from-parse_option.patch deleted file mode 100644 index 065fc9f..0000000 --- a/SOURCES/0007-tools-computer-remove-errx-from-parse_option.patch +++ /dev/null @@ -1,294 +0,0 @@ -From f127ddef23a532cd9763190527bf79b4e47fa2ab Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 8 Apr 2019 17:33:17 +0200 -Subject: [PATCH 7/7] tools: computer - remove errx from parse_option - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1588596 ---- - tools/computer.c | 128 +++++++++++++++++++++++++++++------------------ - 1 file changed, 80 insertions(+), 48 deletions(-) - -diff --git a/tools/computer.c b/tools/computer.c -index 9cbbb28..ac8a203 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -159,7 +159,7 @@ static adcli_tool_desc common_usages[] = { - { 0 }, - }; - --static void -+static int - parse_option (Option opt, - const char *optarg, - adcli_conn *conn, -@@ -175,132 +175,139 @@ parse_option (Option opt, - switch (opt) { - case opt_login_ccache: - adcli_conn_set_login_ccache_name (conn, optarg ? optarg : ""); -- return; -+ return ADCLI_SUCCESS; - case opt_login_user: - if (adcli_conn_get_allowed_login_types (conn) & ADCLI_LOGIN_USER_ACCOUNT) { - adcli_conn_set_login_user (conn, optarg); - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - } else { -- errx (EUSAGE, "cannot set --user if --login-type not set to 'user'"); -+ warnx ("cannot set --user if --login-type not set to 'user'"); -+ return EUSAGE; - } -- return; -+ return ADCLI_SUCCESS; - case opt_login_type: - if (optarg && strcmp (optarg, "computer") == 0) { -- if (adcli_conn_get_login_user (conn) != NULL) -- errx (EUSAGE, "cannot set --login-type to 'computer' if --user is set"); -- else -+ if (adcli_conn_get_login_user (conn) != NULL) { -+ warnx ("cannot set --login-type to 'computer' if --user is set"); -+ return EUSAGE; -+ } else - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_COMPUTER_ACCOUNT); - } else if (optarg && strcmp (optarg, "user") == 0) { - adcli_conn_set_allowed_login_types (conn, ADCLI_LOGIN_USER_ACCOUNT); - - } else { -- errx (EUSAGE, "unknown login type '%s'", optarg); -+ warnx ("unknown login type '%s'", optarg); -+ return EUSAGE; - } -- return; -+ return ADCLI_SUCCESS; - case opt_host_fqdn: - adcli_conn_set_host_fqdn (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_host_keytab: - adcli_enroll_set_keytab_name (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_computer_name: - adcli_conn_set_computer_name (conn, optarg); - adcli_enroll_set_computer_name (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain: - adcli_conn_set_domain_name (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain_realm: - adcli_conn_set_domain_realm (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain_controller: - adcli_conn_set_domain_controller (conn, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_domain_ou: - adcli_enroll_set_domain_ou (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_service_name: - adcli_enroll_add_service_name (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_no_password: - if (stdin_password || prompt_password) { -- errx (EUSAGE, "cannot use --no-password argument with %s", -- stdin_password ? "--stdin-password" : "--prompt-password"); -+ warnx ("cannot use --no-password argument with %s", -+ stdin_password ? "--stdin-password" : "--prompt-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, NULL, NULL, NULL); - no_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_prompt_password: - if (stdin_password || no_password) { -- errx (EUSAGE, "cannot use --prompt-password argument with %s", -- stdin_password ? "--stdin-password" : "--no-password"); -+ warnx ("cannot use --prompt-password argument with %s", -+ stdin_password ? "--stdin-password" : "--no-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, adcli_prompt_password_func, NULL, NULL); - prompt_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_stdin_password: - if (prompt_password || no_password) { -- errx (EUSAGE, "cannot use --stdin-password argument with %s", -- prompt_password ? "--prompt-password" : "--no-password"); -+ warnx ("cannot use --stdin-password argument with %s", -+ prompt_password ? "--prompt-password" : "--no-password"); -+ return EUSAGE; - } else { - adcli_conn_set_password_func (conn, adcli_read_password_func, NULL, NULL); - stdin_password = 1; - } -- return; -+ return ADCLI_SUCCESS; - case opt_os_name: - adcli_enroll_set_os_name (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_os_version: - adcli_enroll_set_os_version (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_os_service_pack: - adcli_enroll_set_os_service_pack (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_user_principal: - if (optarg && optarg[0]) - adcli_enroll_set_user_principal (enroll, optarg); - else - adcli_enroll_auto_user_principal (enroll); -- return; -+ return ADCLI_SUCCESS; - case opt_computer_password_lifetime: - errno = 0; - lifetime = strtoul (optarg, &endptr, 10); - if (errno != 0 || *endptr != '\0' || endptr == optarg) { -- errx (EUSAGE, -- "failure to parse value '%s' of option 'computer-password-lifetime'; " -- "expecting non-negative integer indicating the lifetime in days", -- optarg); -+ warnx ("failure to parse value '%s' of option 'computer-password-lifetime'; " -+ "expecting non-negative integer indicating the lifetime in days", -+ optarg); -+ return EUSAGE; - } - - adcli_enroll_set_computer_password_lifetime (enroll, lifetime); -- return; -+ return ADCLI_SUCCESS; - case opt_samba_data_tool: - errno = 0; - ret = access (optarg, X_OK); - if (ret != 0) { - ret = errno; -- errx (EUSAGE, "Failed to access tool to add Samba data: %s", strerror (ret)); -+ warnx ("Failed to access tool to add Samba data: %s", strerror (ret)); -+ return EUSAGE; - } else { - adcli_enroll_set_samba_data_tool (enroll, optarg); - } -- return; -+ return ADCLI_SUCCESS; - case opt_trusted_for_delegation: - if (strcasecmp (optarg, "true") == 0 || strcasecmp (optarg, "yes") == 0) { - adcli_enroll_set_trusted_for_delegation (enroll, true); - } else { - adcli_enroll_set_trusted_for_delegation (enroll, false); - } -- return; -+ return ADCLI_SUCCESS; - case opt_add_service_principal: - adcli_enroll_add_service_principal_to_add (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_remove_service_principal: - adcli_enroll_add_service_principal_to_remove (enroll, optarg); -- return; -+ return ADCLI_SUCCESS; - case opt_verbose: -- return; -+ return ADCLI_SUCCESS; - - /* Should be handled by caller */ - case opt_show_details: -@@ -311,7 +318,8 @@ parse_option (Option opt, - break; - } - -- errx (EUSAGE, "failure to parse option '%c'", opt); -+ warnx ("failure to parse option '%c'", opt); -+ return EUSAGE; - } - - static void -@@ -407,7 +415,11 @@ adcli_tool_computer_join (adcli_conn *conn, - adcli_enroll_unref (enroll); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } -@@ -519,7 +531,11 @@ adcli_tool_computer_update (adcli_conn *conn, - adcli_enroll_unref (enroll); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } -@@ -610,7 +626,11 @@ adcli_tool_computer_testjoin (adcli_conn *conn, - adcli_enroll_unref (enroll); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } -@@ -707,7 +727,11 @@ adcli_tool_computer_preset (adcli_conn *conn, - adcli_enroll_unref (enroll); - return 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } -@@ -801,7 +825,11 @@ adcli_tool_computer_reset (adcli_conn *conn, - adcli_enroll_unref (enroll); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } -@@ -884,7 +912,11 @@ adcli_tool_computer_delete (adcli_conn *conn, - adcli_enroll_unref (enroll); - return opt == 'h' ? 0 : 2; - default: -- parse_option ((Option)opt, optarg, conn, enroll); -+ res = parse_option ((Option)opt, optarg, conn, enroll); -+ if (res != ADCLI_SUCCESS) { -+ adcli_enroll_unref (enroll); -+ return res; -+ } - break; - } - } --- -2.20.1 - diff --git a/SOURCES/0008-library-add-_adcli_bin_sid_to_str.patch b/SOURCES/0008-library-add-_adcli_bin_sid_to_str.patch deleted file mode 100644 index c7d1c14..0000000 --- a/SOURCES/0008-library-add-_adcli_bin_sid_to_str.patch +++ /dev/null @@ -1,178 +0,0 @@ -From f28edf4e887cf8616fa21dacc2b0f0d31f5f92fb Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:37:05 +0100 -Subject: [PATCH 08/23] library: add _adcli_bin_sid_to_str() - -Convert a binary SID to the string representation. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - library/adprivate.h | 4 ++ - library/adutil.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 117 insertions(+) - -diff --git a/library/adprivate.h b/library/adprivate.h -index fc146af..e99f9fc 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - - #include - -@@ -132,6 +133,9 @@ int _adcli_str_has_prefix (const char *str, - int _adcli_str_has_suffix (const char *str, - const char *suffix); - -+char * _adcli_bin_sid_to_str (const uint8_t *data, -+ size_t len); -+ - char * _adcli_str_dupn (void *data, - size_t len); - -diff --git a/library/adutil.c b/library/adutil.c -index cd40f45..829cdd9 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -293,6 +293,83 @@ _adcli_strv_set (char ***field, - *field = newval; - } - -+char * -+_adcli_bin_sid_to_str (const uint8_t *data, -+ size_t len) -+{ -+ uint8_t sid_rev_num; -+ int8_t num_auths; -+ uint8_t id_auth[6]; -+ uint32_t id_auth_val; -+ uint32_t sub_auths[15]; -+ uint32_t val; -+ size_t p = 0; -+ size_t c; -+ int nc; -+ char *sid_buf; -+ size_t sid_buf_len; -+ -+ if (data == NULL || len < 8) { -+ return NULL; -+ } -+ -+ sid_rev_num = (uint8_t) data [p]; -+ p++; -+ -+ num_auths = (int8_t) data[p]; -+ p++; -+ -+ if (num_auths > 15 || len < 8 + (num_auths * sizeof (uint32_t))) { -+ return NULL; -+ } -+ -+ for (c = 0; c < 6; c++) { -+ id_auth[c] = (uint8_t) data[p]; -+ p++; -+ } -+ -+ /* Only 32bits are used for the string representation */ -+ id_auth_val = (id_auth[2] << 24) + -+ (id_auth[3] << 16) + -+ (id_auth[4] << 8) + -+ (id_auth[5]); -+ -+ for (c = 0; c < num_auths; c++) { -+ memcpy (&val, data + p, sizeof (uint32_t)); -+ sub_auths[c] = le32toh (val); -+ -+ p += sizeof (uint32_t); -+ } -+ -+ sid_buf_len = 17 + (num_auths * 11); -+ sid_buf = calloc (1, sid_buf_len); -+ if (sid_buf == NULL) { -+ return NULL; -+ } -+ -+ nc = snprintf (sid_buf, sid_buf_len, "S-%u-%lu", sid_rev_num, -+ (unsigned long) id_auth_val); -+ if (nc < 0 || nc >= sid_buf_len) { -+ free (sid_buf); -+ return NULL; -+ } -+ -+ p = 0; -+ for (c = 0; c < num_auths; c++) { -+ p += nc; -+ sid_buf_len -= nc; -+ -+ nc = snprintf (sid_buf + p, sid_buf_len, "-%lu", -+ (unsigned long) sub_auths[c]); -+ if (nc < 0 || nc >= sid_buf_len) { -+ free (sid_buf); -+ return NULL; -+ } -+ } -+ -+ return sid_buf; -+} -+ - char * - _adcli_str_dupn (void *data, - size_t len) -@@ -508,6 +585,41 @@ test_check_nt_time_string_lifetime (void) - assert (_adcli_check_nt_time_string_lifetime ("130645404000000000", 100000)); - } - -+static void -+test_bin_sid_to_str (void) -+{ -+ uint8_t sid1[] = { 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, -+ 0x15, 0x00, 0x00, 0x00, 0xF8, 0x12, 0x13, 0xDC, -+ 0x47, 0xF3, 0x1C, 0x76, 0x47, 0x2F, 0x2E, 0xD7, -+ 0x51, 0x04, 0x00, 0x00 }; -+ -+ uint8_t sid2[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, -+ 0x15, 0x00, 0x00, 0x00, 0xF8, 0x12, 0x13, 0xDC, -+ 0x47, 0xF3, 0x1C, 0x76, 0x47, 0x2F, 0x2E, 0xD7}; -+ -+ uint8_t sid3[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, -+ 0x15, 0x00, 0x00, 0x00, 0x29, 0xC9, 0x4F, 0xD9, -+ 0xC2, 0x3C, 0xC3, 0x78, 0x36, 0x55, 0x87, 0xF8}; -+ -+ -+ char *str; -+ -+ str = _adcli_bin_sid_to_str (sid1, sizeof (sid1)); -+ assert (str != NULL); -+ assert (strcmp (str, "S-1-5-21-3692237560-1981608775-3610128199-1105") == 0); -+ free (str); -+ -+ str = _adcli_bin_sid_to_str (sid2, sizeof (sid2)); -+ assert (str != NULL); -+ assert (strcmp (str, "S-1-5-21-3692237560-1981608775-3610128199") == 0); -+ free (str); -+ -+ str = _adcli_bin_sid_to_str (sid3, sizeof (sid2)); -+ assert (str != NULL); -+ assert (strcmp (str, "S-1-5-21-3645884713-2026060994-4169618742") == 0); -+ free (str); -+} -+ - int - main (int argc, - char *argv[]) -@@ -516,6 +628,7 @@ main (int argc, - test_func (test_strv_dup, "/util/strv_dup"); - test_func (test_strv_count, "/util/strv_count"); - test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime"); -+ test_func (test_bin_sid_to_str, "/util/bin_sid_to_str"); - return test_run (argc, argv); - } - --- -2.14.4 - diff --git a/SOURCES/0009-library-add-_adcli_call_external_program.patch b/SOURCES/0009-library-add-_adcli_call_external_program.patch deleted file mode 100644 index f215de6..0000000 --- a/SOURCES/0009-library-add-_adcli_call_external_program.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 63576f12524f521c0cf08d42b279654885135a90 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:39:17 +0100 -Subject: [PATCH 09/23] library: add _adcli_call_external_program() - -Allow adcli to call an external program given by an absolute path name -and an array of options. stdin and stdout can be used if needed. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - configure.ac | 28 +++++++ - library/adprivate.h | 6 ++ - library/adutil.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 245 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 221d8ae..fe86638 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -263,6 +263,34 @@ AC_SUBST(LCOV) - AC_SUBST(GCOV) - AC_SUBST(GENHTML) - -+AC_PATH_PROG(BIN_CAT, cat, no) -+if test "$BIN_CAT" = "no" ; then -+ AC_MSG_ERROR([cat is not available]) -+else -+ AC_DEFINE_UNQUOTED(BIN_CAT, "$BIN_CAT", [path to cat, used in unit test]) -+fi -+ -+AC_PATH_PROG(BIN_TAC, tac, no) -+if test "$BIN_TAC" = "no" ; then -+ AC_MSG_ERROR([tac is not available]) -+else -+ AC_DEFINE_UNQUOTED(BIN_TAC, "$BIN_TAC", [path to tac, used in unit test]) -+fi -+ -+AC_PATH_PROG(BIN_REV, rev, no) -+if test "$BIN_REV" = "no" ; then -+ AC_MSG_ERROR([rev is not available]) -+else -+ AC_DEFINE_UNQUOTED(BIN_REV, "$BIN_REV", [path to rev, used in unit test]) -+fi -+ -+AC_PATH_PROG(BIN_ECHO, echo, no) -+if test "$BIN_ECHO" = "no" ; then -+ AC_MSG_ERROR([echo is not available]) -+else -+ AC_DEFINE_UNQUOTED(BIN_ECHO, "$BIN_ECHO", [path to echo, used in unit test]) -+fi -+ - # --------------------------------------------------------------------- - - ADCLI_LT_RELEASE=$ADCLI_CURRENT:$ADCLI_REVISION:$ADCLI_AGE -diff --git a/library/adprivate.h b/library/adprivate.h -index e99f9fc..7257c93 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -285,4 +285,10 @@ struct _adcli_attrs { - - bool _adcli_check_nt_time_string_lifetime (const char *nt_time_string, unsigned int lifetime); - -+adcli_result _adcli_call_external_program (const char *binary, -+ char * const *argv, -+ const char *stdin_data, -+ uint8_t **stdout_data, -+ size_t *stdout_data_len); -+ - #endif /* ADPRIVATE_H_ */ -diff --git a/library/adutil.c b/library/adutil.c -index 829cdd9..a27bd68 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - static adcli_message_func message_func = NULL; - static char last_error[2048] = { 0, }; -@@ -506,6 +507,161 @@ _adcli_check_nt_time_string_lifetime (const char *nt_time_string, - return false; - } - -+adcli_result -+_adcli_call_external_program (const char *binary, char * const *argv, -+ const char *stdin_data, -+ uint8_t **stdout_data, size_t *stdout_data_len) -+{ -+ int ret; -+ int pipefd_to_child[2] = { -1, -1}; -+ int pipefd_from_child[2] = { -1, -1}; -+ pid_t child_pid = 0; -+ int err; -+ size_t len; -+ ssize_t rlen; -+ pid_t wret; -+ int status; -+ uint8_t read_buf[4096]; -+ uint8_t *out; -+ -+ errno = 0; -+ ret = access (binary, X_OK); -+ if (ret != 0) { -+ err = errno; -+ _adcli_err ("Cannot run [%s]: [%d][%s].", binary, err, -+ strerror (err)); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ -+ ret = pipe (pipefd_from_child); -+ if (ret == -1) { -+ err = errno; -+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err)); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ -+ ret = pipe (pipefd_to_child); -+ if (ret == -1) { -+ err = errno; -+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err)); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ -+ child_pid = fork (); -+ -+ if (child_pid == 0) { /* child */ -+ close (pipefd_to_child[1]); -+ ret = dup2 (pipefd_to_child[0], STDIN_FILENO); -+ if (ret == -1) { -+ err = errno; -+ _adcli_err ("dup2 failed [%d][%s].", err, -+ strerror (err)); -+ exit (EXIT_FAILURE); -+ } -+ -+ close (pipefd_from_child[0]); -+ ret = dup2 (pipefd_from_child[1], STDOUT_FILENO); -+ if (ret == -1) { -+ err = errno; -+ _adcli_err ("dup2 failed [%d][%s].", err, -+ strerror (err)); -+ exit (EXIT_FAILURE); -+ } -+ -+ execv (binary, argv); -+ _adcli_err ("Failed to run %s.", binary); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } else if (child_pid > 0) { /* parent */ -+ -+ if (stdin_data != NULL) { -+ len = strlen (stdin_data); -+ ret = write (pipefd_to_child[1], stdin_data, len); -+ if (ret != len) { -+ _adcli_err ("Failed to send computer account password " -+ "to net command."); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ } -+ -+ close (pipefd_to_child[0]); -+ pipefd_to_child[0] = -1; -+ close (pipefd_to_child[1]); -+ pipefd_to_child[0] = -1; -+ -+ if (stdout_data != NULL || stdout_data_len != NULL) { -+ rlen = read (pipefd_from_child[0], read_buf, sizeof (read_buf)); -+ if (rlen < 0) { -+ ret = errno; -+ _adcli_err ("Failed to read from child [%d][%s].\n", -+ ret, strerror (ret)); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ -+ out = malloc (sizeof(uint8_t) * rlen); -+ if (out == NULL) { -+ _adcli_err ("Failed to allocate memory " -+ "for child output."); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } else { -+ memcpy (out, read_buf, rlen); -+ } -+ -+ if (stdout_data != NULL) { -+ *stdout_data = out; -+ } else { -+ free (out); -+ } -+ -+ if (stdout_data_len != NULL) { -+ *stdout_data_len = rlen; -+ } -+ } -+ -+ } else { -+ _adcli_err ("Cannot run net command."); -+ ret = ADCLI_ERR_FAIL; -+ goto done; -+ } -+ -+ ret = ADCLI_SUCCESS; -+ -+done: -+ if (pipefd_from_child[0] != -1) { -+ close (pipefd_from_child[0]); -+ } -+ if (pipefd_from_child[1] != -1) { -+ close (pipefd_from_child[1]); -+ } -+ if (pipefd_to_child[0] != -1) { -+ close (pipefd_to_child[0]); -+ } -+ if (pipefd_to_child[1] != -1) { -+ close (pipefd_to_child[1]); -+ } -+ -+ if (child_pid > 0) { -+ wret = waitpid (child_pid, &status, 0); -+ if (wret == -1) { -+ _adcli_err ("No sure what happend to net command."); -+ } else { -+ if (WIFEXITED (status)) { -+ _adcli_err ("net command failed with %d.", -+ WEXITSTATUS (status)); -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+ - #ifdef UTIL_TESTS - - #include "test.h" -@@ -620,6 +776,60 @@ test_bin_sid_to_str (void) - free (str); - } - -+static void -+test_call_external_program (void) -+{ -+ adcli_result res; -+ char *argv[] = { NULL, NULL, NULL }; -+ uint8_t *stdout_data; -+ size_t stdout_data_len; -+ -+ argv[0] = "/does/not/exists"; -+ res = _adcli_call_external_program (argv[0], argv, NULL, NULL, NULL); -+ assert (res == ADCLI_ERR_FAIL); -+ -+#ifdef BIN_CAT -+ argv[0] = BIN_CAT; -+ res = _adcli_call_external_program (argv[0], argv, "Hello", -+ &stdout_data, &stdout_data_len); -+ assert (res == ADCLI_SUCCESS); -+ assert (strncmp ("Hello", (char *) stdout_data, stdout_data_len) == 0); -+ free (stdout_data); -+ -+ res = _adcli_call_external_program (argv[0], argv, "Hello", -+ NULL, NULL); -+ assert (res == ADCLI_SUCCESS); -+#endif -+ -+#ifdef BIN_REV -+ argv[0] = BIN_REV; -+ res = _adcli_call_external_program (argv[0], argv, "Hello\n", -+ &stdout_data, &stdout_data_len); -+ assert (res == ADCLI_SUCCESS); -+ assert (strncmp ("olleH\n", (char *) stdout_data, stdout_data_len) == 0); -+ free (stdout_data); -+#endif -+ -+#ifdef BIN_TAC -+ argv[0] = BIN_TAC; -+ res = _adcli_call_external_program (argv[0], argv, "Hello\nWorld\n", -+ &stdout_data, &stdout_data_len); -+ assert (res == ADCLI_SUCCESS); -+ assert (strncmp ("World\nHello\n", (char *) stdout_data, stdout_data_len) == 0); -+ free (stdout_data); -+#endif -+ -+#ifdef BIN_ECHO -+ argv[0] = BIN_ECHO; -+ argv[1] = "Hello"; -+ res = _adcli_call_external_program (argv[0], argv, NULL, -+ &stdout_data, &stdout_data_len); -+ assert (res == ADCLI_SUCCESS); -+ assert (strncmp ("Hello\n", (char *) stdout_data, stdout_data_len) == 0); -+ free (stdout_data); -+#endif -+} -+ - int - main (int argc, - char *argv[]) -@@ -629,6 +839,7 @@ main (int argc, - test_func (test_strv_count, "/util/strv_count"); - test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime"); - test_func (test_bin_sid_to_str, "/util/bin_sid_to_str"); -+ test_func (test_call_external_program, "/util/call_external_program"); - return test_run (argc, argv); - } - --- -2.14.4 - diff --git a/SOURCES/0010-library-add-_adcli_ldap_parse_sid.patch b/SOURCES/0010-library-add-_adcli_ldap_parse_sid.patch deleted file mode 100644 index 6e4d719..0000000 --- a/SOURCES/0010-library-add-_adcli_ldap_parse_sid.patch +++ /dev/null @@ -1,69 +0,0 @@ -From bab08d90162c9146c1b4e8373f4b08209b84768c Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:44:45 +0100 -Subject: [PATCH 10/23] library: add _adcli_ldap_parse_sid() - -Get a binary SID from a LDAP message and return it in the string -representation. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - library/adldap.c | 24 ++++++++++++++++++++++++ - library/adprivate.h | 4 ++++ - 2 files changed, 28 insertions(+) - -diff --git a/library/adldap.c b/library/adldap.c -index 7c7a01b..07dc373 100644 ---- a/library/adldap.c -+++ b/library/adldap.c -@@ -67,6 +67,30 @@ _adcli_ldap_handle_failure (LDAP *ldap, - return defres; - } - -+char * -+_adcli_ldap_parse_sid (LDAP *ldap, -+ LDAPMessage *results, -+ const char *attr_name) -+{ -+ LDAPMessage *entry; -+ struct berval **bvs; -+ char *val = NULL; -+ -+ entry = ldap_first_entry (ldap, results); -+ if (entry != NULL) { -+ bvs = ldap_get_values_len (ldap, entry, attr_name); -+ if (bvs != NULL) { -+ if (bvs[0]) { -+ val = _adcli_bin_sid_to_str ( (uint8_t *) bvs[0]->bv_val, -+ bvs[0]->bv_len); -+ return_val_if_fail (val != NULL, NULL); -+ } -+ ldap_value_free_len (bvs); -+ } -+ } -+ -+ return val; -+} - - char * - _adcli_ldap_parse_value (LDAP *ldap, -diff --git a/library/adprivate.h b/library/adprivate.h -index 7257c93..83a88f6 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -174,6 +174,10 @@ adcli_result _adcli_ldap_handle_failure (LDAP *ldap, - const char *desc, - ...) GNUC_PRINTF(3, 4); - -+char * _adcli_ldap_parse_sid (LDAP *ldap, -+ LDAPMessage *results, -+ const char *attr_name); -+ - char * _adcli_ldap_parse_value (LDAP *ldap, - LDAPMessage *results, - const char *attr_name); --- -2.14.4 - diff --git a/SOURCES/0011-library-add-lookup_domain_sid.patch b/SOURCES/0011-library-add-lookup_domain_sid.patch deleted file mode 100644 index 4534269..0000000 --- a/SOURCES/0011-library-add-lookup_domain_sid.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 3fa854b1439c039a2250cb24efadae6a66b0e9da Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:40:46 +0100 -Subject: [PATCH 11/23] library: add lookup_domain_sid() - -Read the domain SID from the default naming context AD object and store -it in adcli_conn. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - library/adconn.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/library/adconn.c b/library/adconn.c -index 67bdfd9..6b84b88 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -72,6 +72,7 @@ struct _adcli_conn_ctx { - char *domain_controller; - char *canonical_host; - char *domain_short; -+ char *domain_sid; - adcli_disco *domain_disco; - char *default_naming_context; - char *configuration_naming_context; -@@ -1068,6 +1069,32 @@ lookup_short_name (adcli_conn *conn) - } - } - -+static void -+lookup_domain_sid (adcli_conn *conn) -+{ -+ char *attrs[] = { "objectSid", NULL, }; -+ LDAPMessage *results; -+ int ret; -+ -+ free (conn->domain_sid); -+ conn->domain_sid = NULL; -+ -+ ret = ldap_search_ext_s (conn->ldap, conn->default_naming_context, LDAP_SCOPE_BASE, -+ NULL, attrs, 0, NULL, NULL, NULL, -1, &results); -+ if (ret == LDAP_SUCCESS) { -+ conn->domain_sid = _adcli_ldap_parse_sid (conn->ldap, results, "objectSid"); -+ ldap_msgfree (results); -+ -+ if (conn->domain_sid) -+ _adcli_info ("Looked up domain SID: %s", conn->domain_sid); -+ else -+ _adcli_err ("No domain SID found"); -+ } else { -+ _adcli_ldap_handle_failure (conn->ldap, ADCLI_ERR_DIRECTORY, -+ "Couldn't lookup domain SID"); -+ } -+} -+ - static void - conn_clear_state (adcli_conn *conn) - { -@@ -1148,6 +1175,7 @@ adcli_conn_connect (adcli_conn *conn) - return res; - - lookup_short_name (conn); -+ lookup_domain_sid (conn); - return ADCLI_SUCCESS; - } - --- -2.14.4 - diff --git a/SOURCES/0012-library-add-adcli_conn_get_domain_sid.patch b/SOURCES/0012-library-add-adcli_conn_get_domain_sid.patch deleted file mode 100644 index c05aaef..0000000 --- a/SOURCES/0012-library-add-adcli_conn_get_domain_sid.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f98c4f92091f6a68f390078f73be3bb6ca6e6550 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 18:23:03 +0100 -Subject: [PATCH 12/23] library: add adcli_conn_get_domain_sid() - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - library/adconn.c | 8 ++++++++ - library/adconn.h | 2 ++ - tools/computer.c | 1 + - 3 files changed, 11 insertions(+) - -diff --git a/library/adconn.c b/library/adconn.c -index 6b84b88..d2fb1d5 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -1355,6 +1355,14 @@ adcli_conn_get_domain_short (adcli_conn *conn) - return conn->domain_short; - } - -+const char * -+adcli_conn_get_domain_sid (adcli_conn *conn) -+{ -+ return_val_if_fail (conn != NULL, NULL); -+ return conn->domain_sid; -+} -+ -+ - LDAP * - adcli_conn_get_ldap_connection (adcli_conn *conn) - { -diff --git a/library/adconn.h b/library/adconn.h -index ed1cc58..13cfd32 100644 ---- a/library/adconn.h -+++ b/library/adconn.h -@@ -91,6 +91,8 @@ void adcli_conn_set_domain_controller (adcli_conn *conn, - - const char * adcli_conn_get_domain_short (adcli_conn *conn); - -+const char * adcli_conn_get_domain_sid (adcli_conn *conn); -+ - LDAP * adcli_conn_get_ldap_connection (adcli_conn *conn); - - krb5_context adcli_conn_get_krb5_context (adcli_conn *conn); -diff --git a/tools/computer.c b/tools/computer.c -index d8a58c9..a3d0f03 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -43,6 +43,7 @@ dump_details (adcli_conn *conn, - printf ("domain-realm = %s\n", adcli_conn_get_domain_realm (conn)); - printf ("domain-controller = %s\n", adcli_conn_get_domain_controller (conn)); - printf ("domain-short = %s\n", adcli_conn_get_domain_short (conn)); -+ printf ("domain-SID = %s\n", adcli_conn_get_domain_sid (conn)); - printf ("naming-context = %s\n", adcli_conn_get_default_naming_context (conn)); - printf ("domain-ou = %s\n", adcli_enroll_get_domain_ou (enroll)); - --- -2.14.4 - diff --git a/SOURCES/0013-tools-add-option-add-samba-data.patch b/SOURCES/0013-tools-add-option-add-samba-data.patch deleted file mode 100644 index 6e5c872..0000000 --- a/SOURCES/0013-tools-add-option-add-samba-data.patch +++ /dev/null @@ -1,142 +0,0 @@ -From d362a0799618b576918f5c5d0625565484670ba2 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 14:46:00 +0100 -Subject: [PATCH 13/23] tools: add option --add-samba-data - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - doc/adcli.xml | 30 ++++++++++++++++++++++++++++++ - library/adenroll.h | 1 + - tools/computer.c | 12 ++++++++++++ - 3 files changed, 43 insertions(+) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index c54cc1b..fbc6c63 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -292,6 +292,21 @@ Password for Administrator: - machine account password. This is output in a format that should - be both human and machine readable. - -+ -+ -+ After a successful join add the domain -+ SID and the machine account password to the Samba -+ specific databases by calling Samba's -+ net utility. -+ -+ Please note that Samba's net -+ requires some settings in smb.conf -+ to create the database entries correctly. Most -+ important here is currently the -+ option, see -+ smb.conf5 -+ for details. -+ - - - -@@ -382,6 +397,21 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - about join operation. This is output in a format that should - be both human and machine readable. - -+ -+ -+ After a successful join add the domain -+ SID and the machine account password to the Samba -+ specific databases by calling Samba's -+ net utility. -+ -+ Please note that Samba's net -+ requires some settings in smb.conf -+ to create the database entries correctly. Most -+ important here is currently the -+ option, see -+ smb.conf5 -+ for details. -+ - - - -diff --git a/library/adenroll.h b/library/adenroll.h -index 9a107ab..32c9764 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -30,6 +30,7 @@ typedef enum { - ADCLI_ENROLL_NO_KEYTAB = 1 << 1, - ADCLI_ENROLL_ALLOW_OVERWRITE = 1 << 2, - ADCLI_ENROLL_PASSWORD_VALID = 1 << 3, -+ ADCLI_ENROLL_ADD_SAMBA_DATA = 1 << 3, - } adcli_enroll_flags; - - typedef struct _adcli_enroll adcli_enroll; -diff --git a/tools/computer.c b/tools/computer.c -index a3d0f03..fc646f2 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -106,6 +106,7 @@ typedef enum { - opt_os_service_pack, - opt_user_principal, - opt_computer_password_lifetime, -+ opt_add_samba_data, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -142,6 +143,8 @@ static adcli_tool_desc common_usages[] = { - "a successful join" }, - { opt_show_password, "show computer account password after after a\n" - "successful join" }, -+ { opt_add_samba_data, "add domain SID and computer account password\n" -+ "to the Samba specific configuration database" }, - { opt_verbose, "show verbose progress and failure messages", }, - { 0 }, - }; -@@ -269,6 +272,7 @@ parse_option (Option opt, - case opt_show_details: - case opt_show_password: - case opt_one_time_password: -+ case opt_add_samba_data: - assert (0 && "not reached"); - break; - } -@@ -326,6 +330,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "user-principal", optional_argument, NULL, opt_user_principal }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, -+ { "add-samba-data", no_argument, NULL, opt_add_samba_data }, - { "verbose", no_argument, NULL, opt_verbose }, - { "help", no_argument, NULL, 'h' }, - { 0 }, -@@ -352,6 +357,9 @@ adcli_tool_computer_join (adcli_conn *conn, - case opt_show_password: - show_password = 1; - break; -+ case opt_add_samba_data: -+ flags |= ADCLI_ENROLL_ADD_SAMBA_DATA; -+ break; - case 'h': - case '?': - case ':': -@@ -425,6 +433,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "computer-password-lifetime", optional_argument, NULL, opt_computer_password_lifetime }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, -+ { "add-samba-data", no_argument, NULL, opt_add_samba_data }, - { "verbose", no_argument, NULL, opt_verbose }, - { "help", no_argument, NULL, 'h' }, - { 0 }, -@@ -447,6 +456,9 @@ adcli_tool_computer_update (adcli_conn *conn, - case opt_show_password: - show_password = 1; - break; -+ case opt_add_samba_data: -+ flags |= ADCLI_ENROLL_ADD_SAMBA_DATA; -+ break; - case 'h': - case '?': - case ':': --- -2.14.4 - diff --git a/SOURCES/0014-tools-store-Samba-data-if-requested.patch b/SOURCES/0014-tools-store-Samba-data-if-requested.patch deleted file mode 100644 index 33f8bff..0000000 --- a/SOURCES/0014-tools-store-Samba-data-if-requested.patch +++ /dev/null @@ -1,75 +0,0 @@ -From c090131e4f912f6f6c4f79eb40fbe500eb31c171 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 30 Jan 2018 18:24:15 +0100 -Subject: [PATCH 14/23] tools: store Samba data if requested - -Use Samba's net utility to add the machine account password and the -domain SID to the Samba configuration. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - library/adenroll.c | 39 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - -diff --git a/library/adenroll.c b/library/adenroll.c -index bb970d1..20731cd 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -1533,6 +1533,36 @@ update_keytab_for_principals (adcli_enroll *enroll) - return ADCLI_SUCCESS; - } - -+static adcli_result -+update_samba_data (adcli_enroll *enroll) -+{ -+ int ret; -+ char *argv_pw[] = { "/usr/bin/net", "changesecretpw", "-i", "-f", NULL }; -+ char *argv_sid[] = { "/usr/bin/net", "setdomainsid", NULL, NULL }; -+ -+ _adcli_info ("Trying to set Samba secret.\n"); -+ ret = _adcli_call_external_program (argv_pw[0], argv_pw, -+ enroll->computer_password, NULL, NULL); -+ if (ret != ADCLI_SUCCESS) { -+ _adcli_err ("Failed to set Samba computer account password.\n"); -+ } -+ -+ argv_sid[2] = (char *) adcli_conn_get_domain_sid (enroll->conn); -+ if (argv_sid[2] == NULL) { -+ _adcli_err ("Domain SID not available.\n"); -+ } else { -+ _adcli_info ("Trying to set domain SID %s for Samba.\n", -+ argv_sid[2]); -+ ret = _adcli_call_external_program (argv_sid[0], argv_sid, -+ NULL, NULL, NULL); -+ if (ret != ADCLI_SUCCESS) { -+ _adcli_err ("Failed to set Samba domain SID.\n"); -+ } -+ } -+ -+ return ret; -+} -+ - static void - enroll_clear_state (adcli_enroll *enroll) - { -@@ -1687,6 +1717,15 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - update_computer_account (enroll); - update_service_principals (enroll); - -+ if ( (flags & ADCLI_ENROLL_ADD_SAMBA_DATA) && ! (flags & ADCLI_ENROLL_PASSWORD_VALID)) { -+ res = update_samba_data (enroll); -+ if (res != ADCLI_SUCCESS) { -+ _adcli_info ("Failed to add Samba specific data, smbd " -+ "or winbindd might not work as " -+ "expected.\n"); -+ } -+ } -+ - if (flags & ADCLI_ENROLL_NO_KEYTAB) - return ADCLI_SUCCESS; - --- -2.14.4 - diff --git a/SOURCES/0015-make-Samba-data-tool-configurable.patch b/SOURCES/0015-make-Samba-data-tool-configurable.patch deleted file mode 100644 index 714cae5..0000000 --- a/SOURCES/0015-make-Samba-data-tool-configurable.patch +++ /dev/null @@ -1,292 +0,0 @@ -From 9b73f79a2436760b8278377014bf78a144a427ae Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 1 Feb 2018 14:26:22 +0100 -Subject: [PATCH 15/23] make Samba data tool configurable - -Allow to specify an alternative path to Samba's net utility at configure -time and at run time. - -https://bugs.freedesktop.org/show_bug.cgi?id=100118 - -Reviewed-by: Jakub Hrozek ---- - configure.ac | 13 ++++++++++++ - doc/adcli.xml | 21 ++++++++++++++++++- - doc/samba_data_tool_path.xml.in | 1 + - library/adenroll.c | 46 ++++++++++++++++++++++++++++++++++------- - library/adenroll.h | 5 +++++ - tools/computer.c | 16 ++++++++++++++ - 7 files changed, 95 insertions(+), 8 deletions(-) - create mode 100644 doc/samba_data_tool_path.xml.in - -diff --git a/configure.ac b/configure.ac -index fe86638..68877c7 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -291,6 +291,18 @@ else - AC_DEFINE_UNQUOTED(BIN_ECHO, "$BIN_ECHO", [path to echo, used in unit test]) - fi - -+AC_MSG_CHECKING([where is Samba's net utility]) -+AC_ARG_WITH([samba_data_tool], -+ AC_HELP_STRING([--with-samba-data-tool=/path], -+ [Path to Samba's net utility]), -+ [], -+ [with_samba_data_tool=/usr/bin/net]) -+AC_MSG_RESULT([$with_samba_data_tool]) -+ -+AC_DEFINE_UNQUOTED(SAMBA_DATA_TOOL, "$with_samba_data_tool", -+ [Path to Samba's net utility]) -+ -+AC_SUBST(SAMBA_DATA_TOOL, [$with_samba_data_tool]) - # --------------------------------------------------------------------- - - ADCLI_LT_RELEASE=$ADCLI_CURRENT:$ADCLI_REVISION:$ADCLI_AGE -@@ -300,6 +312,7 @@ AC_CONFIG_FILES([Makefile - build/Makefile - doc/Makefile - doc/version.xml -+ doc/samba_data_tool_path.xml - library/Makefile - tools/Makefile - ]) -diff --git a/doc/adcli.xml b/doc/adcli.xml -index fbc6c63..c2b7760 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -1,6 +1,9 @@ - - -+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" -+[ -+ -+]> - - - -@@ -307,6 +310,14 @@ Password for Administrator: - smb.conf5 - for details. - -+ -+ -+ If Samba's net -+ cannot be found at -+ &samba_data_tool; this option can -+ be used to specific an alternative location with the -+ help of an absolute path. -+ - - - -@@ -412,6 +423,14 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - smb.conf5 - for details. - -+ -+ -+ If Samba's net -+ cannot be found at -+ &samba_data_tool; this option can -+ be used to specific an alternative location with the -+ help of an absolute path. -+ - - - -diff --git a/doc/samba_data_tool_path.xml.in b/doc/samba_data_tool_path.xml.in -new file mode 100644 -index 0000000..a667c57 ---- /dev/null -+++ b/doc/samba_data_tool_path.xml.in -@@ -0,0 +1 @@ -+@SAMBA_DATA_TOOL@ -diff --git a/library/adenroll.c b/library/adenroll.c -index 20731cd..a693049 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -42,6 +42,10 @@ - #include - #include - -+#ifndef SAMBA_DATA_TOOL -+#define SAMBA_DATA_TOOL "/usr/bin/net" -+#endif -+ - static krb5_enctype v60_later_enctypes[] = { - ENCTYPE_AES256_CTS_HMAC_SHA1_96, - ENCTYPE_AES128_CTS_HMAC_SHA1_96, -@@ -100,6 +104,7 @@ struct _adcli_enroll { - int keytab_enctypes_explicit; - unsigned int computer_password_lifetime; - int computer_password_lifetime_explicit; -+ char *samba_data_tool; - }; - - static adcli_result -@@ -1537,26 +1542,33 @@ static adcli_result - update_samba_data (adcli_enroll *enroll) - { - int ret; -- char *argv_pw[] = { "/usr/bin/net", "changesecretpw", "-i", "-f", NULL }; -- char *argv_sid[] = { "/usr/bin/net", "setdomainsid", NULL, NULL }; -+ char *argv_pw[] = { NULL, "changesecretpw", "-i", "-f", NULL }; -+ char *argv_sid[] = { NULL, "setdomainsid", NULL, NULL }; -+ -+ argv_pw[0] = (char *) adcli_enroll_get_samba_data_tool (enroll); -+ if (argv_pw[0] ==NULL) { -+ _adcli_err ("Samba data tool not available."); -+ return ADCLI_ERR_FAIL; -+ } -+ argv_sid[0] = argv_pw[0]; - -- _adcli_info ("Trying to set Samba secret.\n"); -+ _adcli_info ("Trying to set Samba secret."); - ret = _adcli_call_external_program (argv_pw[0], argv_pw, - enroll->computer_password, NULL, NULL); - if (ret != ADCLI_SUCCESS) { -- _adcli_err ("Failed to set Samba computer account password.\n"); -+ _adcli_err ("Failed to set Samba computer account password."); - } - - argv_sid[2] = (char *) adcli_conn_get_domain_sid (enroll->conn); - if (argv_sid[2] == NULL) { -- _adcli_err ("Domain SID not available.\n"); -+ _adcli_err ("Domain SID not available."); - } else { -- _adcli_info ("Trying to set domain SID %s for Samba.\n", -+ _adcli_info ("Trying to set domain SID %s for Samba.", - argv_sid[2]); - ret = _adcli_call_external_program (argv_sid[0], argv_sid, - NULL, NULL, NULL); - if (ret != ADCLI_SUCCESS) { -- _adcli_err ("Failed to set Samba domain SID.\n"); -+ _adcli_err ("Failed to set Samba domain SID."); - } - } - -@@ -1951,6 +1963,9 @@ adcli_enroll_new (adcli_conn *conn) - enroll->os_name = strdup (value); - return_val_if_fail (enroll->os_name != NULL, NULL); - -+ enroll->samba_data_tool = strdup (SAMBA_DATA_TOOL); -+ return_val_if_fail (enroll->samba_data_tool != NULL, NULL); -+ - return enroll; - } - -@@ -1978,6 +1993,7 @@ enroll_free (adcli_enroll *enroll) - free (enroll->os_name); - free (enroll->os_version); - free (enroll->os_service_pack); -+ free (enroll->samba_data_tool); - - free (enroll->user_principal); - _adcli_strv_free (enroll->service_names); -@@ -2343,3 +2359,19 @@ adcli_enroll_set_computer_password_lifetime (adcli_enroll *enroll, - - enroll->computer_password_lifetime_explicit = 1; - } -+ -+void -+adcli_enroll_set_samba_data_tool (adcli_enroll *enroll, const char *value) -+{ -+ return_if_fail (enroll != NULL); -+ if (value != NULL && value[0] != '\0') { -+ _adcli_str_set (&enroll->samba_data_tool, value); -+ } -+} -+ -+const char * -+adcli_enroll_get_samba_data_tool (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ return enroll->samba_data_tool; -+} -diff --git a/library/adenroll.h b/library/adenroll.h -index 32c9764..31ca0bc 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -141,4 +141,9 @@ const char * adcli_enroll_get_os_service_pack (adcli_enroll *enroll); - void adcli_enroll_set_os_service_pack (adcli_enroll *enroll, - const char *value); - -+void adcli_enroll_set_samba_data_tool (adcli_enroll *enroll, -+ const char *value); -+ -+const char * adcli_enroll_get_samba_data_tool (adcli_enroll *enroll); -+ - #endif /* ADENROLL_H_ */ -diff --git a/tools/computer.c b/tools/computer.c -index fc646f2..f86548b 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - static void - dump_details (adcli_conn *conn, -@@ -107,6 +108,7 @@ typedef enum { - opt_user_principal, - opt_computer_password_lifetime, - opt_add_samba_data, -+ opt_samba_data_tool, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -145,6 +147,7 @@ static adcli_tool_desc common_usages[] = { - "successful join" }, - { opt_add_samba_data, "add domain SID and computer account password\n" - "to the Samba specific configuration database" }, -+ { opt_samba_data_tool, "Absolute path to the tool used for add-samba-data" }, - { opt_verbose, "show verbose progress and failure messages", }, - { 0 }, - }; -@@ -160,6 +163,7 @@ parse_option (Option opt, - static int stdin_password = 0; - char *endptr; - unsigned int lifetime; -+ int ret; - - switch (opt) { - case opt_login_ccache: -@@ -265,6 +269,16 @@ parse_option (Option opt, - - adcli_enroll_set_computer_password_lifetime (enroll, lifetime); - return; -+ case opt_samba_data_tool: -+ errno = 0; -+ ret = access (optarg, X_OK); -+ if (ret != 0) { -+ ret = errno; -+ errx (EUSAGE, "Failed to access tool to add Samba data: %s", strerror (ret)); -+ } else { -+ adcli_enroll_set_samba_data_tool (enroll, optarg); -+ } -+ return; - case opt_verbose: - return; - -@@ -331,6 +345,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, -+ { "samba-data-tool", no_argument, NULL, opt_samba_data_tool }, - { "verbose", no_argument, NULL, opt_verbose }, - { "help", no_argument, NULL, 'h' }, - { 0 }, -@@ -434,6 +449,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, -+ { "samba-data-tool", no_argument, NULL, opt_samba_data_tool }, - { "verbose", no_argument, NULL, opt_verbose }, - { "help", no_argument, NULL, 'h' }, - { 0 }, --- -2.14.4 - diff --git a/SOURCES/0016-Add-trusted-for-delegation-option.patch b/SOURCES/0016-Add-trusted-for-delegation-option.patch deleted file mode 100644 index 122f5a2..0000000 --- a/SOURCES/0016-Add-trusted-for-delegation-option.patch +++ /dev/null @@ -1,247 +0,0 @@ -From f306f2f20c1d35fac63d27147824f039f7ef2d67 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 31 May 2018 18:27:37 +0200 -Subject: [PATCH 16/23] Add trusted-for-delegation option - -Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1538730 ---- - doc/adcli.xml | 14 ++++++++++ - library/adenroll.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- - library/adenroll.h | 4 +++ - tools/computer.c | 12 ++++++++ - 4 files changed, 108 insertions(+), 2 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index c2b7760..b246190 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -283,6 +283,13 @@ Password for Administrator: - and providing a - password as input. - -+ -+ -+ Set or unset the TRUSTED_FOR_DELEGATION -+ flag in the userAccountControl attribute to allow or -+ not allow that Kerberos tickets can be forwarded to the -+ host. -+ - - - After a successful join print out information -@@ -402,6 +409,13 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - in days. By default the password is updated if it is - older than 30 days. - -+ -+ -+ Set or unset the TRUSTED_FOR_DELEGATION -+ flag in the userAccountControl attribute to allow or -+ not allow that Kerberos tickets can be forwarded to the -+ host. -+ - - - After a successful join print out information -diff --git a/library/adenroll.c b/library/adenroll.c -index a693049..eca3c37 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -63,6 +63,13 @@ static krb5_enctype v51_earlier_enctypes[] = { - 0 - }; - -+/* 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. */ -+#define UAC_WORKSTATION_TRUST_ACCOUNT 0x1000 -+#define UAC_DONT_EXPIRE_PASSWORD 0x10000 -+#define UAC_TRUSTED_FOR_DELEGATION 0x80000 -+ - struct _adcli_enroll { - int refs; - adcli_conn *conn; -@@ -105,6 +112,7 @@ struct _adcli_enroll { - unsigned int computer_password_lifetime; - int computer_password_lifetime_explicit; - char *samba_data_tool; -+ bool trusted_for_delegation; - }; - - static adcli_result -@@ -538,6 +546,10 @@ create_computer_account (adcli_enroll *enroll, - NULL, - }; - -+ if (adcli_enroll_get_trusted_for_delegation (enroll)) { -+ vals_userAccountControl[0] = "593920"; /* WORKSTATION_TRUST_ACCOUNT | DONT_EXPIRE_PASSWD | TRUSTED_FOR_DELEGATION */ -+ } -+ - ret = ldap_add_ext_s (ldap, enroll->computer_dn, mods, NULL, NULL); - - /* -@@ -971,6 +983,7 @@ retrieve_computer_account (adcli_enroll *enroll) - "operatingSystemVersion", - "operatingSystemServicePack", - "pwdLastSet", -+ "userAccountControl", - NULL, - }; - -@@ -1149,6 +1162,47 @@ update_computer_attribute (adcli_enroll *enroll, - return res; - } - -+static char *get_user_account_control (adcli_enroll *enroll) -+{ -+ uint32_t uac = 0; -+ unsigned long attr_val; -+ char *uac_str; -+ LDAP *ldap; -+ char *end; -+ -+ ldap = adcli_conn_get_ldap_connection (enroll->conn); -+ return_val_if_fail (ldap != NULL, NULL); -+ -+ uac_str = _adcli_ldap_parse_value (ldap, enroll->computer_attributes, "userAccountControl"); -+ if (uac_str != NULL) { -+ -+ 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); -+ } else { -+ uac = attr_val; -+ } -+ free (uac_str); -+ } -+ -+ if (uac == 0) { -+ uac = UAC_WORKSTATION_TRUST_ACCOUNT | UAC_DONT_EXPIRE_PASSWORD; -+ } -+ -+ if (adcli_enroll_get_trusted_for_delegation (enroll)) { -+ uac |= UAC_TRUSTED_FOR_DELEGATION; -+ } else { -+ uac &= ~(UAC_TRUSTED_FOR_DELEGATION); -+ } -+ -+ if (asprintf (&uac_str, "%d", uac) < 0) { -+ return_val_if_reached (NULL); -+ } -+ -+ return uac_str; -+} -+ - static void - update_computer_account (adcli_enroll *enroll) - { -@@ -1167,11 +1221,16 @@ update_computer_account (adcli_enroll *enroll) - } - - if (res == ADCLI_SUCCESS) { -- char *vals_userAccountControl[] = { "69632", NULL }; /* WORKSTATION_TRUST_ACCOUNT | DONT_EXPIRE_PASSWD */ -+ char *vals_userAccountControl[] = { NULL , NULL }; - LDAPMod userAccountControl = { LDAP_MOD_REPLACE, "userAccountControl", { vals_userAccountControl, } }; - LDAPMod *mods[] = { &userAccountControl, NULL }; - -- res |= update_computer_attribute (enroll, ldap, mods); -+ vals_userAccountControl[0] = get_user_account_control (enroll); -+ if (vals_userAccountControl[0] != NULL) { -+ res |= update_computer_attribute (enroll, ldap, mods); -+ } else { -+ _adcli_warn ("Cannot update userAccountControl"); -+ } - } - - if (res == ADCLI_SUCCESS) { -@@ -2375,3 +2434,20 @@ adcli_enroll_get_samba_data_tool (adcli_enroll *enroll) - return_val_if_fail (enroll != NULL, NULL); - return enroll->samba_data_tool; - } -+ -+bool -+adcli_enroll_get_trusted_for_delegation (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, false); -+ -+ return enroll->trusted_for_delegation; -+} -+ -+void -+adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, -+ bool value) -+{ -+ return_if_fail (enroll != NULL); -+ -+ enroll->trusted_for_delegation = value; -+} -diff --git a/library/adenroll.h b/library/adenroll.h -index 31ca0bc..be2ca18 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -109,6 +109,10 @@ unsigned int adcli_enroll_get_computer_password_lifetime (adcli_enroll *en - void adcli_enroll_set_computer_password_lifetime (adcli_enroll *enroll, - unsigned int lifetime); - -+bool adcli_enroll_get_trusted_for_delegation (adcli_enroll *enroll); -+void adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, -+ bool 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 f86548b..b905fd1 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -109,6 +109,7 @@ typedef enum { - opt_computer_password_lifetime, - opt_add_samba_data, - opt_samba_data_tool, -+ opt_trusted_for_delegation, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -135,6 +136,8 @@ static adcli_tool_desc common_usages[] = { - { opt_os_service_pack, "the computer operating system service pack", }, - { opt_user_principal, "add an authentication principal to the account", }, - { opt_computer_password_lifetime, "lifetime of the host accounts password in days", }, -+ { opt_trusted_for_delegation, "set/unset the TRUSTED_FOR_DELEGATION flag\n" -+ "in the userAccountControl attribute", }, - { 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" -@@ -279,6 +282,13 @@ parse_option (Option opt, - adcli_enroll_set_samba_data_tool (enroll, optarg); - } - return; -+ case opt_trusted_for_delegation: -+ if (strcasecmp (optarg, "true") == 0 || strcasecmp (optarg, "yes") == 0) { -+ adcli_enroll_set_trusted_for_delegation (enroll, true); -+ } else { -+ adcli_enroll_set_trusted_for_delegation (enroll, false); -+ } -+ return; - case opt_verbose: - return; - -@@ -342,6 +352,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "os-version", required_argument, NULL, opt_os_version }, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "user-principal", optional_argument, NULL, opt_user_principal }, -+ { "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, -@@ -446,6 +457,7 @@ adcli_tool_computer_update (adcli_conn *conn, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "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 }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, --- -2.14.4 - diff --git a/SOURCES/0017-Only-update-attributes-given-on-the-command-line.patch b/SOURCES/0017-Only-update-attributes-given-on-the-command-line.patch deleted file mode 100644 index 2ee6a6f..0000000 --- a/SOURCES/0017-Only-update-attributes-given-on-the-command-line.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 27c7dde2c0e84c3bb610d1aadb0fd8faff70d3fa Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 1 Jun 2018 21:26:47 +0200 -Subject: [PATCH 17/23] Only update attributes given on the command line - -When updating attributes of the LDAP computer object we only want to -update attributes which are related to options given on the command -line. Otherwise a simple call of 'adcli update' to check if the machine -account password needs an update might unexpectedly reset other -attributes as well. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547013 - https://bugzilla.redhat.com/show_bug.cgi?id=1545568 - https://bugzilla.redhat.com/show_bug.cgi?id=1538730 ---- - library/adenroll.c | 35 ++++++++++++++++++++++++++++++----- - 1 file changed, 30 insertions(+), 5 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index eca3c37..ee845ef 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -99,8 +99,11 @@ struct _adcli_enroll { - int user_princpal_generate; - - char *os_name; -+ int os_name_explicit; - char *os_version; -+ int os_version_explicit; - char *os_service_pack; -+ int os_service_pack_explicit; - - krb5_kvno kvno; - char *keytab_name; -@@ -113,6 +116,7 @@ struct _adcli_enroll { - int computer_password_lifetime_explicit; - char *samba_data_tool; - bool trusted_for_delegation; -+ int trusted_for_delegation_explicit; - }; - - static adcli_result -@@ -1212,7 +1216,11 @@ update_computer_account (adcli_enroll *enroll) - 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) { - char *vals_dNSHostName[] = { enroll->host_fqdn, NULL }; - LDAPMod dNSHostName = { LDAP_MOD_REPLACE, "dNSHostName", { vals_dNSHostName, } }; - LDAPMod *mods[] = { &dNSHostName, NULL }; -@@ -1220,7 +1228,7 @@ update_computer_account (adcli_enroll *enroll) - res |= update_computer_attribute (enroll, ldap, mods); - } - -- if (res == ADCLI_SUCCESS) { -+ if (res == ADCLI_SUCCESS && enroll->trusted_for_delegation_explicit) { - char *vals_userAccountControl[] = { NULL , NULL }; - LDAPMod userAccountControl = { LDAP_MOD_REPLACE, "userAccountControl", { vals_userAccountControl, } }; - LDAPMod *mods[] = { &userAccountControl, NULL }; -@@ -1240,12 +1248,25 @@ update_computer_account (adcli_enroll *enroll) - LDAPMod operatingSystemVersion = { LDAP_MOD_REPLACE, "operatingSystemVersion", { vals_operatingSystemVersion, } }; - char *vals_operatingSystemServicePack[] = { enroll->os_service_pack, NULL }; - LDAPMod operatingSystemServicePack = { LDAP_MOD_REPLACE, "operatingSystemServicePack", { vals_operatingSystemServicePack, } }; -- LDAPMod *mods[] = { &operatingSystem, &operatingSystemVersion, &operatingSystemServicePack, NULL }; -+ LDAPMod *mods[] = { NULL, NULL, NULL, NULL }; -+ size_t c = 0; - -- res |= update_computer_attribute (enroll, ldap, mods); -+ if (enroll->os_name_explicit) { -+ mods[c++] = &operatingSystem; -+ } -+ if (enroll->os_version_explicit) { -+ mods[c++] = &operatingSystemVersion; -+ } -+ if (enroll->os_service_pack_explicit) { -+ mods[c++] = &operatingSystemServicePack; -+ } -+ -+ if (c != 0) { -+ res |= update_computer_attribute (enroll, ldap, mods); -+ } - } - -- if (res == ADCLI_SUCCESS) { -+ if (res == ADCLI_SUCCESS && !enroll->user_princpal_generate) { - char *vals_userPrincipalName[] = { enroll->user_principal, NULL }; - LDAPMod userPrincipalName = { LDAP_MOD_REPLACE, "userPrincipalName", { vals_userPrincipalName, }, }; - LDAPMod *mods[] = { &userPrincipalName, NULL, }; -@@ -2337,6 +2358,7 @@ adcli_enroll_set_os_name (adcli_enroll *enroll, - if (value && value[0] == '\0') - value = NULL; - _adcli_str_set (&enroll->os_name, value); -+ enroll->os_name_explicit = 1; - } - - const char * -@@ -2354,6 +2376,7 @@ adcli_enroll_set_os_version (adcli_enroll *enroll, - if (value && value[0] == '\0') - value = NULL; - _adcli_str_set (&enroll->os_version, value); -+ enroll->os_version_explicit = 1; - } - - const char * -@@ -2371,6 +2394,7 @@ adcli_enroll_set_os_service_pack (adcli_enroll *enroll, - if (value && value[0] == '\0') - value = NULL; - _adcli_str_set (&enroll->os_service_pack, value); -+ enroll->os_service_pack_explicit = 1; - } - - const char * -@@ -2450,4 +2474,5 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, - return_if_fail (enroll != NULL); - - enroll->trusted_for_delegation = value; -+ enroll->trusted_for_delegation_explicit = 1; - } --- -2.14.4 - diff --git a/SOURCES/0018-update-allow-to-add-service-names.patch b/SOURCES/0018-update-allow-to-add-service-names.patch deleted file mode 100644 index 2387ef2..0000000 --- a/SOURCES/0018-update-allow-to-add-service-names.patch +++ /dev/null @@ -1,387 +0,0 @@ -From 54c3d176326f719ffefded17bb797bc9e6c7f3c0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 4 Jun 2018 10:49:33 +0200 -Subject: [PATCH 18/23] update: allow to add service names - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547013 - https://bugzilla.redhat.com/show_bug.cgi?id=1545568 ---- - library/adenroll.c | 136 +++++++++++++++++++++++++++++++++------------------- - library/adkrb5.c | 113 +++++++++++++++++++++++++++++++++++++++++++ - library/adprivate.h | 6 +++ - 3 files changed, 206 insertions(+), 49 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index ee845ef..6fdc773 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -305,13 +305,37 @@ ensure_service_names (adcli_result res, - } - - static adcli_result --ensure_service_principals (adcli_result res, -- adcli_enroll *enroll) -+add_service_names_to_service_principals (adcli_enroll *enroll) - { - char *name; - int length = 0; - int i; - -+ if (enroll->service_principals != NULL) { -+ length = seq_count (enroll->service_principals); -+ } -+ -+ for (i = 0; enroll->service_names[i] != NULL; i++) { -+ if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0) -+ return_unexpected_if_reached (); -+ enroll->service_principals = _adcli_strv_add (enroll->service_principals, -+ name, &length); -+ -+ if (enroll->host_fqdn) { -+ if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0) -+ return_unexpected_if_reached (); -+ enroll->service_principals = _adcli_strv_add (enroll->service_principals, -+ name, &length); -+ } -+ } -+ -+ return ADCLI_SUCCESS; -+} -+ -+static adcli_result -+ensure_service_principals (adcli_result res, -+ adcli_enroll *enroll) -+{ - if (res != ADCLI_SUCCESS) - return res; - -@@ -319,20 +343,7 @@ ensure_service_principals (adcli_result res, - - if (!enroll->service_principals) { - assert (enroll->service_names != NULL); -- -- for (i = 0; enroll->service_names[i] != NULL; i++) { -- if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->computer_name) < 0) -- return_unexpected_if_reached (); -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -- -- if (enroll->host_fqdn) { -- if (asprintf (&name, "%s/%s", enroll->service_names[i], enroll->host_fqdn) < 0) -- return_unexpected_if_reached (); -- enroll->service_principals = _adcli_strv_add (enroll->service_principals, -- name, &length); -- } -- } -+ return add_service_names_to_service_principals (enroll); - } - - return ADCLI_SUCCESS; -@@ -356,6 +367,7 @@ ensure_keytab_principals (adcli_result res, - return_unexpected_if_fail (k5 != NULL); - - enroll->keytab_principals = calloc (count + 3, sizeof (krb5_principal)); -+ return_unexpected_if_fail (enroll->keytab_principals != NULL); - at = 0; - - /* First add the principal for the computer account name */ -@@ -1266,7 +1278,7 @@ update_computer_account (adcli_enroll *enroll) - } - } - -- if (res == ADCLI_SUCCESS && !enroll->user_princpal_generate) { -+ if (res == ADCLI_SUCCESS && enroll->user_principal != NULL && !enroll->user_princpal_generate) { - char *vals_userPrincipalName[] = { enroll->user_principal, NULL }; - LDAPMod userPrincipalName = { LDAP_MOD_REPLACE, "userPrincipalName", { vals_userPrincipalName, }, }; - LDAPMod *mods[] = { &userPrincipalName, NULL, }; -@@ -1519,7 +1531,8 @@ add_principal_to_keytab (adcli_enroll *enroll, - krb5_context k5, - krb5_principal principal, - const char *principal_name, -- int *which_salt) -+ int *which_salt, -+ adcli_enroll_flags flags) - { - match_principal_kvno closure; - krb5_data password; -@@ -1547,41 +1560,47 @@ add_principal_to_keytab (adcli_enroll *enroll, - enroll->keytab_name); - } - -- password.data = enroll->computer_password; -- password.length = strlen (enroll->computer_password); -- - enctypes = adcli_enroll_get_keytab_enctypes (enroll); - -- /* -- * So we need to discover which salt to use. As a side effect we are -- * also testing that our account works. -- */ -+ if (flags & ADCLI_ENROLL_PASSWORD_VALID) { -+ code = _adcli_krb5_keytab_copy_entries (k5, enroll->keytab, principal, -+ enroll->kvno, enctypes); -+ } else { - -- salts = build_principal_salts (enroll, k5, principal); -- return_unexpected_if_fail (salts != NULL); -+ password.data = enroll->computer_password; -+ password.length = strlen (enroll->computer_password); - -- if (*which_salt < 0) { -- code = _adcli_krb5_keytab_discover_salt (k5, principal, enroll->kvno, &password, -- enctypes, salts, which_salt); -- if (code != 0) { -- _adcli_warn ("Couldn't authenticate with keytab while discovering which salt to use: %s: %s", -- principal_name, krb5_get_error_message (k5, code)); -- *which_salt = DEFAULT_SALT; -- } else { -- assert (*which_salt >= 0); -- _adcli_info ("Discovered which keytab salt to use"); -+ /* -+ * So we need to discover which salt to use. As a side effect we are -+ * also testing that our account works. -+ */ -+ -+ salts = build_principal_salts (enroll, k5, principal); -+ return_unexpected_if_fail (salts != NULL); -+ -+ if (*which_salt < 0) { -+ code = _adcli_krb5_keytab_discover_salt (k5, principal, enroll->kvno, &password, -+ enctypes, salts, which_salt); -+ if (code != 0) { -+ _adcli_warn ("Couldn't authenticate with keytab while discovering which salt to use: %s: %s", -+ principal_name, krb5_get_error_message (k5, code)); -+ *which_salt = DEFAULT_SALT; -+ } else { -+ assert (*which_salt >= 0); -+ _adcli_info ("Discovered which keytab salt to use"); -+ } - } -- } - -- code = _adcli_krb5_keytab_add_entries (k5, enroll->keytab, principal, -- enroll->kvno, &password, enctypes, &salts[*which_salt]); -+ code = _adcli_krb5_keytab_add_entries (k5, enroll->keytab, principal, -+ enroll->kvno, &password, enctypes, &salts[*which_salt]); - -- free_principal_salts (k5, salts); -+ free_principal_salts (k5, salts); - -- if (code != 0) { -- _adcli_err ("Couldn't add keytab entries: %s: %s", -- enroll->keytab_name, krb5_get_error_message (k5, code)); -- return ADCLI_ERR_FAIL; -+ if (code != 0) { -+ _adcli_err ("Couldn't add keytab entries: %s: %s", -+ enroll->keytab_name, krb5_get_error_message (k5, code)); -+ return ADCLI_ERR_FAIL; -+ } - } - - -@@ -1591,7 +1610,8 @@ add_principal_to_keytab (adcli_enroll *enroll, - } - - static adcli_result --update_keytab_for_principals (adcli_enroll *enroll) -+update_keytab_for_principals (adcli_enroll *enroll, -+ adcli_enroll_flags flags) - { - krb5_context k5; - adcli_result res; -@@ -1608,7 +1628,7 @@ update_keytab_for_principals (adcli_enroll *enroll) - if (krb5_unparse_name (k5, enroll->keytab_principals[i], &name) != 0) - name = ""; - res = add_principal_to_keytab (enroll, k5, enroll->keytab_principals[i], -- name, &which_salt); -+ name, &which_salt, flags); - krb5_free_unparsed_name (k5, name); - - if (res != ADCLI_SUCCESS) -@@ -1807,6 +1827,20 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - /* We ignore failures of setting these fields */ - update_and_calculate_enctypes (enroll); - update_computer_account (enroll); -+ -+ /* service_names is only set from input on the command line, so no -+ * additional check for explicit is needed here */ -+ if (enroll->service_names != NULL) { -+ res = add_service_names_to_service_principals (enroll); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ res = ensure_keytab_principals (res, enroll); -+ if (res != ADCLI_SUCCESS) { -+ return res; -+ } -+ } -+ - update_service_principals (enroll); - - if ( (flags & ADCLI_ENROLL_ADD_SAMBA_DATA) && ! (flags & ADCLI_ENROLL_PASSWORD_VALID)) { -@@ -1826,7 +1860,7 @@ enroll_join_or_update_tasks (adcli_enroll *enroll, - * that we use for salting. - */ - -- return update_keytab_for_principals (enroll); -+ return update_keytab_for_principals (enroll, flags); - } - - adcli_result -@@ -1927,7 +1961,11 @@ adcli_enroll_update (adcli_enroll *enroll, - - if (_adcli_check_nt_time_string_lifetime (value, - adcli_enroll_get_computer_password_lifetime (enroll))) { -- flags |= ADCLI_ENROLL_NO_KEYTAB; -+ /* Do not update keytab if neither new service principals have -+ * to be added nor the user principal has to be changed. */ -+ if (enroll->service_names == NULL && (enroll->user_principal == NULL || enroll->user_princpal_generate)) { -+ flags |= ADCLI_ENROLL_NO_KEYTAB; -+ } - flags |= ADCLI_ENROLL_PASSWORD_VALID; - } - free (value); -diff --git a/library/adkrb5.c b/library/adkrb5.c -index b0e903e..033c181 100644 ---- a/library/adkrb5.c -+++ b/library/adkrb5.c -@@ -204,6 +204,119 @@ _adcli_krb5_open_keytab (krb5_context k5, - return ADCLI_SUCCESS; - } - -+typedef struct { -+ krb5_kvno kvno; -+ krb5_enctype enctype; -+ int matched; -+} match_enctype_kvno; -+ -+static krb5_boolean -+match_enctype_and_kvno (krb5_context k5, -+ krb5_keytab_entry *entry, -+ void *data) -+{ -+ krb5_boolean similar = FALSE; -+ match_enctype_kvno *closure = data; -+ krb5_error_code code; -+ -+ assert (closure->enctype); -+ -+ code = krb5_c_enctype_compare (k5, closure->enctype, entry->key.enctype, -+ &similar); -+ -+ if (code == 0 && entry->vno == closure->kvno && similar) { -+ closure->matched = 1; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static krb5_error_code -+_adcli_krb5_get_keyblock (krb5_context k5, -+ krb5_keytab keytab, -+ krb5_keyblock *keyblock, -+ krb5_boolean (* match_func) (krb5_context, -+ krb5_keytab_entry *, -+ void *), -+ void *match_data) -+{ -+ krb5_kt_cursor cursor; -+ krb5_keytab_entry entry; -+ krb5_error_code code; -+ -+ code = krb5_kt_start_seq_get (k5, keytab, &cursor); -+ if (code == KRB5_KT_END || code == ENOENT) -+ return 0; -+ else if (code != 0) -+ return code; -+ -+ for (;;) { -+ code = krb5_kt_next_entry (k5, keytab, &entry, &cursor); -+ if (code != 0) -+ break; -+ -+ /* See if we should remove this entry */ -+ if (!match_func (k5, &entry, match_data)) { -+ krb5_free_keytab_entry_contents (k5, &entry); -+ continue; -+ } -+ -+ code = krb5_copy_keyblock_contents (k5, &entry.key, keyblock); -+ krb5_free_keytab_entry_contents (k5, &entry); -+ break; -+ -+ -+ } -+ -+ if (code == KRB5_KT_END) -+ code = 0; -+ -+ krb5_kt_end_seq_get (k5, keytab, &cursor); -+ return code; -+} -+ -+krb5_error_code -+_adcli_krb5_keytab_copy_entries (krb5_context k5, -+ krb5_keytab keytab, -+ krb5_principal principal, -+ krb5_kvno kvno, -+ krb5_enctype *enctypes) -+{ -+ krb5_keytab_entry entry; -+ krb5_error_code code; -+ int i; -+ match_enctype_kvno closure; -+ -+ for (i = 0; enctypes[i] != 0; i++) { -+ -+ closure.kvno = kvno; -+ closure.enctype = enctypes[i]; -+ closure.matched = 0; -+ -+ memset (&entry, 0, sizeof (entry)); -+ -+ code = _adcli_krb5_get_keyblock (k5, keytab, &entry.key, -+ match_enctype_and_kvno, &closure); -+ if (code != 0) { -+ return code; -+ } -+ -+ -+ entry.principal = principal; -+ entry.vno = kvno; -+ -+ code = krb5_kt_add_entry (k5, keytab, &entry); -+ -+ entry.principal = NULL; -+ krb5_free_keytab_entry_contents (k5, &entry); -+ -+ if (code != 0) -+ return code; -+ } -+ -+ return 0; -+} - - krb5_error_code - _adcli_krb5_keytab_add_entries (krb5_context k5, -diff --git a/library/adprivate.h b/library/adprivate.h -index 83a88f6..7485249 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -282,6 +282,12 @@ krb5_enctype * _adcli_krb5_parse_enctypes (const char *value); - - char * _adcli_krb5_format_enctypes (krb5_enctype *enctypes); - -+krb5_error_code _adcli_krb5_keytab_copy_entries (krb5_context k5, -+ krb5_keytab keytab, -+ krb5_principal principal, -+ krb5_kvno kvno, -+ krb5_enctype *enctypes); -+ - struct _adcli_attrs { - LDAPMod **mods; - int len; --- -2.14.4 - diff --git a/SOURCES/0019-Calculate-enctypes-in-a-separate-function.patch b/SOURCES/0019-Calculate-enctypes-in-a-separate-function.patch deleted file mode 100644 index 4a09f33..0000000 --- a/SOURCES/0019-Calculate-enctypes-in-a-separate-function.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 9ad1164405e7b4decb7c4ad96fe5ab27d6e53366 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 6 Jun 2018 16:31:32 +0200 -Subject: [PATCH 19/23] Calculate enctypes in a separate function - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1542354 ---- - library/adenroll.c | 137 +++++++++++++++++++++++++++++++---------------------- - 1 file changed, 81 insertions(+), 56 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 6fdc773..75ac1e4 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -542,6 +542,83 @@ calculate_computer_account (adcli_enroll *enroll, - return ADCLI_SUCCESS; - } - -+static adcli_result -+calculate_enctypes (adcli_enroll *enroll, char **enctype) -+{ -+ char *value = NULL; -+ krb5_enctype *read_enctypes; -+ char *new_value = NULL; -+ int is_2008_or_later; -+ LDAP *ldap; -+ -+ *enctype = NULL; -+ /* -+ * Because we're using a keytab we want the server to be aware of the -+ * encryption types supported on the client, because we can't dynamically -+ * use a new one that's thrown at us. -+ * -+ * If the encryption types are not explicitly set by the caller of this -+ * library, then see if the account already has some encryption types -+ * marked on it. -+ * -+ * If not, write our default set to the account. -+ * -+ * Note that Windows 2003 and earlier have a standard set of encryption -+ * types, and no msDS-supportedEncryptionTypes attribute. -+ */ -+ -+ ldap = adcli_conn_get_ldap_connection (enroll->conn); -+ return_unexpected_if_fail (ldap != NULL); -+ -+ is_2008_or_later = adcli_conn_server_has_capability (enroll->conn, ADCLI_CAP_V60_OID); -+ -+ /* In 2008 or later, use the msDS-supportedEncryptionTypes attribute */ -+ if (is_2008_or_later) { -+ value = _adcli_ldap_parse_value (ldap, enroll->computer_attributes, -+ "msDS-supportedEncryptionTypes"); -+ -+ if (!enroll->keytab_enctypes_explicit && value != NULL) { -+ read_enctypes = _adcli_krb5_parse_enctypes (value); -+ if (read_enctypes == NULL) { -+ _adcli_warn ("Invalid or unsupported encryption types are set on " -+ "the computer account (%s).", value); -+ } else { -+ free (enroll->keytab_enctypes); -+ enroll->keytab_enctypes = read_enctypes; -+ } -+ } -+ -+ /* In 2003 or earlier, standard set of enc types */ -+ } else { -+ value = _adcli_krb5_format_enctypes (v51_earlier_enctypes); -+ } -+ -+ new_value = _adcli_krb5_format_enctypes (adcli_enroll_get_keytab_enctypes (enroll)); -+ if (new_value == NULL) { -+ free (value); -+ _adcli_warn ("The encryption types desired are not available in active directory"); -+ return ADCLI_ERR_CONFIG; -+ } -+ -+ /* If we already have this value, then don't need to update */ -+ if (value && strcmp (new_value, value) == 0) { -+ free (value); -+ free (new_value); -+ return ADCLI_SUCCESS; -+ } -+ free (value); -+ -+ if (!is_2008_or_later) { -+ free (new_value); -+ _adcli_warn ("Server does not support setting encryption types"); -+ return ADCLI_SUCCESS; -+ } -+ -+ *enctype = new_value; -+ return ADCLI_SUCCESS; -+} -+ -+ - static adcli_result - create_computer_account (adcli_enroll *enroll, - LDAP *ldap) -@@ -1053,75 +1130,23 @@ retrieve_computer_account (adcli_enroll *enroll) - static adcli_result - update_and_calculate_enctypes (adcli_enroll *enroll) - { -- char *value = NULL; -- krb5_enctype *read_enctypes; - char *vals_supportedEncryptionTypes[] = { NULL, NULL }; - LDAPMod mod = { LDAP_MOD_REPLACE, "msDS-supportedEncryptionTypes", { vals_supportedEncryptionTypes, } }; - LDAPMod *mods[2] = { &mod, NULL }; -- int is_2008_or_later; - char *new_value; - LDAP *ldap; - int ret; - -- /* -- * Because we're using a keytab we want the server to be aware of the -- * encryption types supported on the client, because we can't dynamically -- * use a new one that's thrown at us. -- * -- * If the encryption types are not explicitly set by the caller of this -- * library, then see if the account already has some encryption types -- * marked on it. -- * -- * If not, write our default set to the account. -- * -- * Note that Windows 2003 and earlier have a standard set of encryption -- * types, and no msDS-supportedEncryptionTypes attribute. -- */ -- - ldap = adcli_conn_get_ldap_connection (enroll->conn); - return_unexpected_if_fail (ldap != NULL); - -- is_2008_or_later = adcli_conn_server_has_capability (enroll->conn, ADCLI_CAP_V60_OID); -- -- /* In 2008 or later, use the msDS-supportedEncryptionTypes attribute */ -- if (is_2008_or_later) { -- value = _adcli_ldap_parse_value (ldap, enroll->computer_attributes, -- "msDS-supportedEncryptionTypes"); -- -- if (!enroll->keytab_enctypes_explicit && value != NULL) { -- read_enctypes = _adcli_krb5_parse_enctypes (value); -- if (read_enctypes == NULL) { -- _adcli_warn ("Invalid or unsupported encryption types are set on " -- "the computer account (%s).", value); -- } else { -- free (enroll->keytab_enctypes); -- enroll->keytab_enctypes = read_enctypes; -- } -- } -- -- /* In 2003 or earlier, standard set of enc types */ -- } else { -- value = _adcli_krb5_format_enctypes (v51_earlier_enctypes); -- } -- -- new_value = _adcli_krb5_format_enctypes (adcli_enroll_get_keytab_enctypes (enroll)); -- if (new_value == NULL) { -- free (value); -- _adcli_warn ("The encryption types desired are not available in active directory"); -- return ADCLI_ERR_CONFIG; -- } -- -- /* If we already have this value, then don't need to update */ -- if (value && strcmp (new_value, value) == 0) { -- free (value); -+ ret = calculate_enctypes (enroll, &new_value); -+ if (ret != ADCLI_SUCCESS) { - free (new_value); -- return ADCLI_SUCCESS; -+ return ret; - } -- free (value); - -- if (!is_2008_or_later) { -- free (new_value); -- _adcli_warn ("Server does not support setting encryption types"); -+ if (new_value == NULL) { - return ADCLI_SUCCESS; - } - --- -2.14.4 - diff --git a/SOURCES/0020-join-add-all-attributes-while-creating-computer-obje.patch b/SOURCES/0020-join-add-all-attributes-while-creating-computer-obje.patch deleted file mode 100644 index 7c76b1c..0000000 --- a/SOURCES/0020-join-add-all-attributes-while-creating-computer-obje.patch +++ /dev/null @@ -1,110 +0,0 @@ -From cbe33b3e6d0d3415e4642d71942380d1793311f1 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 11 Jun 2018 09:44:49 +0200 -Subject: [PATCH 20/23] join: add all attributes while creating computer object - -It is possible to create special accounts which can only join a computer -to a domain but is not allowed to do any further operations which the -computer object. As a result if such an account is used during the join -only the ldapadd operation is permitted but not any later ldapmodify -operation. To create the computer object correctly in this case all -attributes must be added while the object is created and not later. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1542354 ---- - library/adenroll.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 47 insertions(+), 5 deletions(-) - -diff --git a/library/adenroll.c b/library/adenroll.c -index 75ac1e4..b508caf 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -573,7 +573,7 @@ calculate_enctypes (adcli_enroll *enroll, char **enctype) - is_2008_or_later = adcli_conn_server_has_capability (enroll->conn, ADCLI_CAP_V60_OID); - - /* In 2008 or later, use the msDS-supportedEncryptionTypes attribute */ -- if (is_2008_or_later) { -+ if (is_2008_or_later && enroll->computer_attributes != NULL) { - value = _adcli_ldap_parse_value (ldap, enroll->computer_attributes, - "msDS-supportedEncryptionTypes"); - -@@ -618,7 +618,6 @@ calculate_enctypes (adcli_enroll *enroll, char **enctype) - return ADCLI_SUCCESS; - } - -- - static adcli_result - create_computer_account (adcli_enroll *enroll, - LDAP *ldap) -@@ -628,22 +627,65 @@ create_computer_account (adcli_enroll *enroll, - char *vals_sAMAccountName[] = { enroll->computer_sam, NULL }; - LDAPMod sAMAccountName = { LDAP_MOD_ADD, "sAMAccountName", { vals_sAMAccountName, } }; - char *vals_userAccountControl[] = { "69632", NULL }; /* WORKSTATION_TRUST_ACCOUNT | DONT_EXPIRE_PASSWD */ -- LDAPMod userAccountControl = { LDAP_MOD_REPLACE, "userAccountControl", { vals_userAccountControl, } }; -+ LDAPMod userAccountControl = { LDAP_MOD_ADD, "userAccountControl", { vals_userAccountControl, } }; -+ char *vals_supportedEncryptionTypes[] = { NULL, NULL }; -+ LDAPMod encTypes = { LDAP_MOD_ADD, "msDS-supportedEncryptionTypes", { vals_supportedEncryptionTypes, } }; -+ char *vals_dNSHostName[] = { enroll->host_fqdn, NULL }; -+ LDAPMod dNSHostName = { LDAP_MOD_ADD, "dNSHostName", { vals_dNSHostName, } }; -+ char *vals_operatingSystem[] = { enroll->os_name, NULL }; -+ LDAPMod operatingSystem = { LDAP_MOD_ADD, "operatingSystem", { vals_operatingSystem, } }; -+ char *vals_operatingSystemVersion[] = { enroll->os_version, NULL }; -+ LDAPMod operatingSystemVersion = { LDAP_MOD_ADD, "operatingSystemVersion", { vals_operatingSystemVersion, } }; -+ char *vals_operatingSystemServicePack[] = { enroll->os_service_pack, NULL }; -+ LDAPMod operatingSystemServicePack = { LDAP_MOD_ADD, "operatingSystemServicePack", { vals_operatingSystemServicePack, } }; -+ 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 *val = NULL; - - int ret; -+ size_t c; -+ size_t m; - -- LDAPMod *mods[] = { -+ LDAPMod *all_mods[] = { - &objectClass, - &sAMAccountName, - &userAccountControl, -- NULL, -+ &encTypes, -+ &dNSHostName, -+ &operatingSystem, -+ &operatingSystemVersion, -+ &operatingSystemServicePack, -+ &userPrincipalName, -+ &servicePrincipalName, -+ NULL - }; - -+ size_t mods_count = sizeof (all_mods) / sizeof (LDAPMod *); -+ LDAPMod *mods[mods_count]; -+ - if (adcli_enroll_get_trusted_for_delegation (enroll)) { - vals_userAccountControl[0] = "593920"; /* WORKSTATION_TRUST_ACCOUNT | DONT_EXPIRE_PASSWD | TRUSTED_FOR_DELEGATION */ - } - -+ ret = calculate_enctypes (enroll, &val); -+ if (ret != ADCLI_SUCCESS) { -+ return ret; -+ } -+ vals_supportedEncryptionTypes[0] = val; -+ -+ m = 0; -+ for (c = 0; c < mods_count - 1; c++) { -+ /* Skip empty LDAP sttributes */ -+ if (all_mods[c]->mod_vals.modv_strvals[0] != NULL) { -+ mods[m++] = all_mods[c]; -+ } -+ } -+ mods[m] = NULL; -+ - ret = ldap_add_ext_s (ldap, enroll->computer_dn, mods, NULL, NULL); -+ free (val); - - /* - * Hand to head. This is really dumb... AD returns --- -2.14.4 - diff --git a/SOURCES/0021-util-add-_adcli_strv_remove_unsorted.patch b/SOURCES/0021-util-add-_adcli_strv_remove_unsorted.patch deleted file mode 100644 index f9dea0f..0000000 --- a/SOURCES/0021-util-add-_adcli_strv_remove_unsorted.patch +++ /dev/null @@ -1,288 +0,0 @@ -From 4208646609da9b25b70c21f5f39c92fabbd59dfc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 14 Jun 2018 16:48:22 +0200 -Subject: [PATCH 21/23] util: add _adcli_strv_remove_unsorted - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014 ---- - library/adprivate.h | 4 ++ - library/adutil.c | 21 ++++++++ - library/seq.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++--- - library/seq.h | 12 +++++ - 4 files changed, 179 insertions(+), 7 deletions(-) - -diff --git a/library/adprivate.h b/library/adprivate.h -index 7485249..bc9df6d 100644 ---- a/library/adprivate.h -+++ b/library/adprivate.h -@@ -111,6 +111,10 @@ char ** _adcli_strv_add (char **strv, - char *string, - int *length) GNUC_WARN_UNUSED; - -+void _adcli_strv_remove_unsorted (char **strv, -+ const char *string, -+ int *length); -+ - void _adcli_strv_free (char **strv); - - int _adcli_strv_has (char **strv, -diff --git a/library/adutil.c b/library/adutil.c -index a27bd68..6334b52 100644 ---- a/library/adutil.c -+++ b/library/adutil.c -@@ -221,6 +221,27 @@ _adcli_strv_add (char **strv, - return seq_push (strv, length, string); - } - -+#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) -+ -+void -+_adcli_strv_remove_unsorted (char **strv, -+ const char *string, -+ int *length) -+{ -+ int len; -+ -+ return_if_fail (string != NULL); -+ -+ if (!length) { -+ len = seq_count (strv); -+ length = &len; -+ } -+ -+ return seq_remove_unsorted (strv, length, discard_const (string), -+ (seq_compar)strcasecmp, free); -+} -+ -+ - int - _adcli_strv_has (char **strv, - const char *str) -diff --git a/library/seq.c b/library/seq.c -index 627dcaf..8e7475d 100644 ---- a/library/seq.c -+++ b/library/seq.c -@@ -111,6 +111,24 @@ seq_push (seq_voidp sequence, - return seq; - } - -+static int -+linear_search (void **seq, -+ int low, -+ int high, -+ void *match, -+ seq_compar compar) -+{ -+ int at; -+ -+ for (at = low; at < high; at++) { -+ if (compar (match, seq[at]) == 0) { -+ break; -+ } -+ } -+ -+ return at; -+} -+ - static int - binary_search (void **seq, - int low, -@@ -171,12 +189,13 @@ seq_insert (seq_voidp sequence, - return seq; - } - --void --seq_remove (seq_voidp sequence, -- int *length, -- void *match, -- seq_compar compar, -- seq_destroy destroy) -+static void -+seq_remove_int (seq_voidp sequence, -+ int *length, -+ void *match, -+ seq_search search, -+ seq_compar compar, -+ seq_destroy destroy) - { - void **seq = sequence; - int at; -@@ -187,7 +206,7 @@ seq_remove (seq_voidp sequence, - assert (match != NULL); - - len = *length; -- at = binary_search (seq, 0, len, match, compar); -+ at = search (seq, 0, len, match, compar); - - /* We have a matching value */ - if (at < len && compar (match, seq[at]) == 0) { -@@ -201,6 +220,26 @@ seq_remove (seq_voidp sequence, - *length = len; - } - -+void -+seq_remove (seq_voidp sequence, -+ int *length, -+ void *match, -+ seq_compar compar, -+ seq_destroy destroy) -+{ -+ return seq_remove_int (sequence, length, match, binary_search, compar, destroy); -+} -+ -+void -+seq_remove_unsorted (seq_voidp sequence, -+ int *length, -+ void *match, -+ seq_compar compar, -+ seq_destroy destroy) -+{ -+ return seq_remove_int (sequence, length, match, linear_search, compar, destroy); -+} -+ - void - seq_filter (seq_voidp sequence, - int *length, -@@ -430,6 +469,99 @@ test_remove (void) - seq_free (seq, NULL); - } - -+static void -+test_remove_unsorted (void) -+{ -+ void **seq = NULL; -+ int len = 0; -+ -+ seq = seq_push (seq, &len, "3"); -+ seq = seq_push (seq, &len, "5"); -+ seq = seq_push (seq, &len, "1"); -+ seq = seq_push (seq, &len, "4"); -+ seq = seq_push (seq, &len, "2"); -+ -+ assert_str_eq (seq[0], "3"); -+ assert_str_eq (seq[1], "5"); -+ assert_str_eq (seq[2], "1"); -+ assert_str_eq (seq[3], "4"); -+ assert_str_eq (seq[4], "2"); -+ assert (seq[5] == NULL); -+ assert_num_eq (len, 5); -+ -+ seq_remove_unsorted (seq, &len, "3", (seq_compar)strcmp, NULL); -+ seq_remove_unsorted (seq, &len, "2", (seq_compar)strcmp, NULL); -+ -+ assert_str_eq (seq[0], "5"); -+ assert_str_eq (seq[1], "1"); -+ assert_str_eq (seq[2], "4"); -+ assert (seq[3] == NULL); -+ assert_num_eq (len, 3); -+ -+ seq_free (seq, NULL); -+} -+ -+static void -+test_remove_first (void) -+{ -+ void **seq = NULL; -+ int len = 0; -+ -+ seq = seq_insert (seq, &len, "3", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "5", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "1", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "4", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "2", (seq_compar)strcmp, NULL); -+ -+ assert_str_eq (seq[0], "1"); -+ assert_str_eq (seq[1], "2"); -+ assert_str_eq (seq[2], "3"); -+ assert_str_eq (seq[3], "4"); -+ assert_str_eq (seq[4], "5"); -+ assert (seq[5] == NULL); -+ assert_num_eq (len, 5); -+ -+ seq_remove (seq, &len, "1", (seq_compar)strcmp, NULL); -+ -+ assert_str_eq (seq[0], "2"); -+ assert_str_eq (seq[1], "3"); -+ assert_str_eq (seq[2], "4"); -+ assert_str_eq (seq[3], "5"); -+ assert (seq[4] == NULL); -+ assert_num_eq (len, 4); -+ -+ seq_free (seq, NULL); -+} -+ -+static void -+test_remove_last (void) -+{ -+ void **seq = NULL; -+ int len = 0; -+ -+ seq = seq_insert (seq, &len, "3", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "1", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "4", (seq_compar)strcmp, NULL); -+ seq = seq_insert (seq, &len, "2", (seq_compar)strcmp, NULL); -+ -+ assert_str_eq (seq[0], "1"); -+ assert_str_eq (seq[1], "2"); -+ assert_str_eq (seq[2], "3"); -+ assert_str_eq (seq[3], "4"); -+ assert (seq[4] == NULL); -+ assert_num_eq (len, 4); -+ -+ seq_remove (seq, &len, "4", (seq_compar)strcmp, NULL); -+ -+ assert_str_eq (seq[0], "1"); -+ assert_str_eq (seq[1], "2"); -+ assert_str_eq (seq[2], "3"); -+ assert (seq[3] == NULL); -+ assert_num_eq (len, 3); -+ -+ seq_free (seq, NULL); -+} -+ - static int - compar_even (void *match, - void *value) -@@ -631,6 +763,9 @@ main (int argc, - test_func (test_insert, "/seq/insert"); - test_func (test_insert_destroys, "/seq/insert_destroys"); - test_func (test_remove, "/seq/remove"); -+ test_func (test_remove_unsorted, "/seq/remove_unsorted"); -+ test_func (test_remove_first, "/seq/remove_first"); -+ test_func (test_remove_last, "/seq/remove_last"); - test_func (test_remove_destroys, "/seq/remove_destroys"); - test_func (test_filter, "/seq/filter"); - test_func (test_filter_null, "/seq/filter_null"); -diff --git a/library/seq.h b/library/seq.h -index 694965b..5d48848 100644 ---- a/library/seq.h -+++ b/library/seq.h -@@ -44,6 +44,12 @@ typedef void * (* seq_copy) (void *value); - - typedef void (* seq_destroy) (void *value); - -+typedef int (* seq_search) (void **seq, -+ int low, -+ int high, -+ void *match, -+ seq_compar compar); -+ - seq_voidp seq_push (seq_voidp seq, - int *length, - void *value) WARN_UNUSED; -@@ -62,6 +68,12 @@ void seq_remove (seq_voidp seq, - seq_compar compar, - seq_destroy destroy); - -+void seq_remove_unsorted (seq_voidp seq, -+ int *length, -+ void *match, -+ seq_compar compar, -+ seq_destroy destroy); -+ - seq_voidp seq_lookup (seq_voidp seq, - int *length, - void *match, --- -2.14.4 - diff --git a/SOURCES/0022-Add-add-service-principal-and-remove-service-princip.patch b/SOURCES/0022-Add-add-service-principal-and-remove-service-princip.patch deleted file mode 100644 index a92414a..0000000 --- a/SOURCES/0022-Add-add-service-principal-and-remove-service-princip.patch +++ /dev/null @@ -1,360 +0,0 @@ -From ee71c4c0614a504b4472bf64a24fc3c18c6b9987 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 14 Jun 2018 16:49:26 +0200 -Subject: [PATCH 22/23] Add add-service-principal and remove-service-principal - options - -Currently it is only possible to specific a service name for service -principals but not to set the full service principal. This is e.g. -needed if there is a service running on a host which should be reachable -by a different DNS name as well. - -With this patch service principal can be added and removed by specifying -the full name. - -Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014 ---- - doc/adcli.xml | 21 ++++++++ - library/adenroll.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++-- - library/adenroll.h | 8 +++ - library/adldap.c | 16 ++++-- - tools/computer.c | 13 +++++ - 5 files changed, 189 insertions(+), 8 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index b246190..83b6981 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -290,6 +290,14 @@ Password for Administrator: - not allow that Kerberos tickets can be forwarded to the - host. - -+ -+ -+ Add a service principal name. In -+ contrast to the the -+ hostname part can be specified as well in case the -+ service should be accessible with a different host -+ name as well. -+ - - - After a successful join print out information -@@ -416,6 +424,19 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - not allow that Kerberos tickets can be forwarded to the - host. - -+ -+ -+ Add a service principal name. In -+ contrast to the the -+ hostname part can be specified as well in case the -+ service should be accessible with a different host -+ name as well. -+ -+ -+ -+ Remove a service principal name from -+ the keytab and the AD host object. -+ - - - After a successful join print out information -diff --git a/library/adenroll.c b/library/adenroll.c -index b508caf..c4ba537 100644 ---- a/library/adenroll.c -+++ b/library/adenroll.c -@@ -95,6 +95,9 @@ struct _adcli_enroll { - char **service_principals; - int service_principals_explicit; - -+ char **service_principals_to_add; -+ char **service_principals_to_remove; -+ - char *user_principal; - int user_princpal_generate; - -@@ -332,6 +335,43 @@ add_service_names_to_service_principals (adcli_enroll *enroll) - return ADCLI_SUCCESS; - } - -+static adcli_result -+add_and_remove_service_principals (adcli_enroll *enroll) -+{ -+ int length = 0; -+ size_t c; -+ const char **list; -+ -+ if (enroll->service_principals != NULL) { -+ length = seq_count (enroll->service_principals); -+ } -+ -+ list = adcli_enroll_get_service_principals_to_add (enroll); -+ if (list != NULL) { -+ for (c = 0; list[c] != NULL; c++) { -+ enroll->service_principals = _adcli_strv_add (enroll->service_principals, -+ strdup (list[c]), -+ &length); -+ if (enroll->service_principals == NULL) { -+ return ADCLI_ERR_UNEXPECTED; -+ } -+ } -+ } -+ -+ list = adcli_enroll_get_service_principals_to_remove (enroll); -+ if (list != NULL) { -+ for (c = 0; list[c] != NULL; c++) { -+ /* enroll->service_principals typically refects the -+ * order of the principal in the keytabm so it is not -+ * ordered. */ -+ _adcli_strv_remove_unsorted (enroll->service_principals, -+ list[c], &length); -+ } -+ } -+ -+ return ADCLI_SUCCESS; -+} -+ - static adcli_result - ensure_service_principals (adcli_result res, - adcli_enroll *enroll) -@@ -343,10 +383,14 @@ ensure_service_principals (adcli_result res, - - if (!enroll->service_principals) { - assert (enroll->service_names != NULL); -- return add_service_names_to_service_principals (enroll); -+ res = add_service_names_to_service_principals (enroll); - } - -- return ADCLI_SUCCESS; -+ if (res == ADCLI_SUCCESS) { -+ res = add_and_remove_service_principals (enroll); -+ } -+ -+ return res; - } - - static adcli_result -@@ -1593,6 +1637,39 @@ free_principal_salts (krb5_context k5, - free (salts); - } - -+static adcli_result -+remove_principal_from_keytab (adcli_enroll *enroll, -+ krb5_context k5, -+ const char *principal_name) -+{ -+ krb5_error_code code; -+ krb5_principal principal; -+ match_principal_kvno closure; -+ -+ code = krb5_parse_name (k5, principal_name, &principal); -+ if (code != 0) { -+ _adcli_err ("Couldn't parse principal: %s: %s", -+ principal_name, krb5_get_error_message (k5, code)); -+ return ADCLI_ERR_FAIL; -+ } -+ -+ closure.kvno = enroll->kvno; -+ closure.principal = principal; -+ closure.matched = 0; -+ -+ code = _adcli_krb5_keytab_clear (k5, enroll->keytab, -+ match_principal_and_kvno, &closure); -+ krb5_free_principal (k5, principal); -+ -+ if (code != 0) { -+ _adcli_err ("Couldn't update keytab: %s: %s", -+ enroll->keytab_name, krb5_get_error_message (k5, code)); -+ return ADCLI_ERR_FAIL; -+ } -+ -+ return ADCLI_SUCCESS; -+} -+ - static adcli_result - add_principal_to_keytab (adcli_enroll *enroll, - krb5_context k5, -@@ -1702,6 +1779,17 @@ update_keytab_for_principals (adcli_enroll *enroll, - return res; - } - -+ if (enroll->service_principals_to_remove != NULL) { -+ for (i = 0; enroll->service_principals_to_remove[i] != NULL; i++) { -+ res = remove_principal_from_keytab (enroll, k5, -+ enroll->service_principals_to_remove[i]); -+ if (res != ADCLI_SUCCESS) { -+ _adcli_warn ("Failed to remove %s from keytab.", -+ enroll->service_principals_to_remove[i]); -+ } -+ } -+ } -+ - return ADCLI_SUCCESS; - } - -@@ -2029,8 +2117,11 @@ adcli_enroll_update (adcli_enroll *enroll, - if (_adcli_check_nt_time_string_lifetime (value, - adcli_enroll_get_computer_password_lifetime (enroll))) { - /* Do not update keytab if neither new service principals have -- * to be added nor the user principal has to be changed. */ -- if (enroll->service_names == NULL && (enroll->user_principal == NULL || enroll->user_princpal_generate)) { -+ * to be added or deleted nor the user principal has to be changed. */ -+ if (enroll->service_names == NULL -+ && (enroll->user_principal == NULL || enroll->user_princpal_generate) -+ && enroll->service_principals_to_add == NULL -+ && enroll->service_principals_to_remove == NULL) { - flags |= ADCLI_ENROLL_NO_KEYTAB; - } - flags |= ADCLI_ENROLL_PASSWORD_VALID; -@@ -2581,3 +2672,43 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll, - enroll->trusted_for_delegation = value; - enroll->trusted_for_delegation_explicit = 1; - } -+ -+const char ** -+adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ -+ return (const char **)enroll->service_principals_to_add; -+} -+ -+void -+adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll, -+ const char *value) -+{ -+ return_if_fail (enroll != NULL); -+ return_if_fail (value != NULL); -+ -+ enroll->service_principals_to_add = _adcli_strv_add (enroll->service_principals_to_add, -+ strdup (value), NULL); -+ return_if_fail (enroll->service_principals_to_add != NULL); -+} -+ -+const char ** -+adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll) -+{ -+ return_val_if_fail (enroll != NULL, NULL); -+ -+ return (const char **)enroll->service_principals_to_remove; -+} -+ -+void -+adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll, -+ const char *value) -+{ -+ return_if_fail (enroll != NULL); -+ return_if_fail (value != NULL); -+ -+ enroll->service_principals_to_remove = _adcli_strv_add (enroll->service_principals_to_remove, -+ strdup (value), NULL); -+ return_if_fail (enroll->service_principals_to_remove != NULL); -+} -diff --git a/library/adenroll.h b/library/adenroll.h -index be2ca18..f87dffa 100644 ---- a/library/adenroll.h -+++ b/library/adenroll.h -@@ -98,6 +98,14 @@ const char ** adcli_enroll_get_service_principals (adcli_enroll *enroll); - void adcli_enroll_set_service_principals (adcli_enroll *enroll, - const char **value); - -+const char ** adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll); -+void adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll, -+ const char *value); -+ -+const char ** adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll); -+void adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll, -+ const char *value); -+ - const char * adcli_enroll_get_user_principal (adcli_enroll *enroll); - - void adcli_enroll_set_user_principal (adcli_enroll *enroll, -diff --git a/library/adldap.c b/library/adldap.c -index 07dc373..d93efb7 100644 ---- a/library/adldap.c -+++ b/library/adldap.c -@@ -210,16 +210,24 @@ _adcli_ldap_have_in_mod (LDAPMod *mod, - struct berval *vals; - struct berval **pvals; - int count = 0; -+ int count_have = 0; - int i; - int ret; - -- /* Already in berval format, just compare */ -- if (mod->mod_op & LDAP_MOD_BVALUES) -- return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have); -- - /* Count number of values */ - for (i = 0; mod->mod_vals.modv_strvals[i] != 0; i++) - count++; -+ for (i = 0; have[i] != 0; i++) -+ count_have++; -+ -+ /* If numbers different something has to be added or removed */ -+ if (count != count_have) { -+ return 0; -+ } -+ -+ /* Already in berval format, just compare */ -+ if (mod->mod_op & LDAP_MOD_BVALUES) -+ return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have); - - vals = malloc (sizeof (struct berval) * (count + 1)); - pvals = malloc (sizeof (struct berval *) * (count + 1)); -diff --git a/tools/computer.c b/tools/computer.c -index b905fd1..377d449 100644 ---- a/tools/computer.c -+++ b/tools/computer.c -@@ -110,6 +110,8 @@ typedef enum { - opt_add_samba_data, - opt_samba_data_tool, - opt_trusted_for_delegation, -+ opt_add_service_principal, -+ opt_remove_service_principal, - } Option; - - static adcli_tool_desc common_usages[] = { -@@ -138,6 +140,8 @@ static adcli_tool_desc common_usages[] = { - { opt_computer_password_lifetime, "lifetime of the host accounts password in days", }, - { opt_trusted_for_delegation, "set/unset the TRUSTED_FOR_DELEGATION flag\n" - "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_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" -@@ -289,6 +293,12 @@ parse_option (Option opt, - adcli_enroll_set_trusted_for_delegation (enroll, false); - } - return; -+ case opt_add_service_principal: -+ adcli_enroll_add_service_principal_to_add (enroll, optarg); -+ return; -+ case opt_remove_service_principal: -+ adcli_enroll_add_service_principal_to_remove (enroll, optarg); -+ return; - case opt_verbose: - return; - -@@ -353,6 +363,7 @@ adcli_tool_computer_join (adcli_conn *conn, - { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, - { "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 }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, -@@ -458,6 +469,8 @@ adcli_tool_computer_update (adcli_conn *conn, - { "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 }, -+ { "add-service-principal", required_argument, NULL, opt_add_service_principal }, -+ { "remove-service-principal", required_argument, NULL, opt_remove_service_principal }, - { "show-details", no_argument, NULL, opt_show_details }, - { "show-password", no_argument, NULL, opt_show_password }, - { "add-samba-data", no_argument, NULL, opt_add_samba_data }, --- -2.14.4 - diff --git a/SOURCES/0023-adcli_conn_is_writeable-do-not-crash-id-domain_disco.patch b/SOURCES/0023-adcli_conn_is_writeable-do-not-crash-id-domain_disco.patch deleted file mode 100644 index 7b775c3..0000000 --- a/SOURCES/0023-adcli_conn_is_writeable-do-not-crash-id-domain_disco.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 026cfacabfad58ae2cebcdf6cd82d905023ea289 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 31 May 2018 17:01:36 +0200 -Subject: [PATCH 23/23] adcli_conn_is_writeable: do not crash id domain_disco - is missing - -Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1575554 ---- - library/adconn.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/library/adconn.c b/library/adconn.c -index d2fb1d5..e2250e3 100644 ---- a/library/adconn.c -+++ b/library/adconn.c -@@ -1567,6 +1567,11 @@ adcli_conn_server_has_capability (adcli_conn *conn, - - bool adcli_conn_is_writeable (adcli_conn *conn) - { -- disco_dance_if_necessary (conn); -- return ( (conn->domain_disco->flags & ADCLI_DISCO_WRITABLE) != 0); -+ disco_dance_if_necessary (conn); -+ -+ if (conn->domain_disco == NULL) { -+ return false; -+ } -+ -+ return ( (conn->domain_disco->flags & ADCLI_DISCO_WRITABLE) != 0); - } --- -2.14.4 - diff --git a/SOURCES/0024-doc-fix-typos-in-the-adcli-man-page.patch b/SOURCES/0024-doc-fix-typos-in-the-adcli-man-page.patch deleted file mode 100644 index 1827c95..0000000 --- a/SOURCES/0024-doc-fix-typos-in-the-adcli-man-page.patch +++ /dev/null @@ -1,203 +0,0 @@ -From 1e57862cf5d8f4f774868b3599e4a34c525ae348 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 5 Jul 2018 13:06:26 +0200 -Subject: [PATCH 24/24] doc: fix typos in the adcli man page - -Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1440533 ---- - doc/adcli.xml | 44 ++++++++++++++++++++++---------------------- - 1 file changed, 22 insertions(+), 22 deletions(-) - -diff --git a/doc/adcli.xml b/doc/adcli.xml -index 83b6981..97dec08 100644 ---- a/doc/adcli.xml -+++ b/doc/adcli.xml -@@ -105,19 +105,19 @@ - - - The domain to connect to. If a domain is -- not specified then the domain part of the local computer's -+ not specified, then the domain part of the local computer's - host name is used. - - - - Kerberos realm for the domain. If not -- specified then the upper cased domain name is -+ specified, then the upper cased domain name is - used. - - - - Connect to a specific domain controller. -- If not specified then an appropriate domain controller -+ If not specified, then an appropriate domain controller - is automatically discovered. - - -@@ -134,7 +134,7 @@ - - - Use the specified user account to -- authenticate with the domain. If not specified then -+ authenticate with the domain. If not specified, then - the name 'Administrator' will be used. - - -@@ -181,7 +181,7 @@ $ adcli info --domain-controller=dc.domain.example.com - adcli info will output as much information as - it can about the domain. The information is designed to be both machine - and human readable. The command will exit with a non-zero exit code -- if the domain does note exist or cannot be reached. -+ if the domain does not exist or cannot be reached. - - To show domain info for a specific domain controller use the - option to specify which domain -@@ -213,35 +213,35 @@ Password for Administrator: - - - The short non-dotted name of the computer -- account that will be created in the domain. If not specified -+ account that will be created in the domain. If not specified, - then the first portion of the - is used. - - - - The full distinguished name of the OU in -- which to create the computer account. If not specified -+ which to create the computer account. If not specified, - then the computer account will be created in a default - location. - - - - Override the local machine's fully qualified -- domain name. If not specified the local machine's hostname -+ domain name. If not specified, the local machine's hostname - will be retrieved via gethostname(). - - - - Specify the path to the host keytab where - host credentials will be written after a successful join -- operation. If not specified the default location will be -+ operation. If not specified, the default location will be - used, usually /etc/krb5.keytab. - - - - Specify the type of authentication that - will be performed before creating the machine account in -- the domain. If set to 'computer' then the computer must -+ the domain. If set to 'computer', then the computer must - already have a preset account in the domain. If not - specified and none of the other - arguments have been specified, then will try both -@@ -329,7 +329,7 @@ Password for Administrator: - - If Samba's net - cannot be found at -- &samba_data_tool; this option can -+ &samba_data_tool;, this option can - be used to specific an alternative location with the - help of an absolute path. - -@@ -351,7 +351,7 @@ Password for Administrator: - $ adcli update - - -- If used with a credential cache other attributes of the computer -+ If used with a credential cache, other attributes of the computer - account can be changed as well if the principal has sufficient - privileges. - -@@ -367,20 +367,20 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - - - The short non-dotted name of the computer -- account that will be created in the domain. If not specified -+ account that will be created in the domain. If not specified, - it will be retrieved from the keytab entries. - - - - The local machine's fully qualified -- domain name. If not specified the local machine's hostname -+ domain name. If not specified, the local machine's hostname - will be retrieved from the keytab entries. - - - - Specify the path to the host keytab where - current host credentials are stored and the new ones -- will be written to. If not specified the default -+ will be written to. If not specified, the default - location will be used, usually - /etc/krb5.keytab. - -@@ -462,7 +462,7 @@ $ adcli update --login-ccache=/tmp/krbcc_123 - - If Samba's net - cannot be found at -- &samba_data_tool; this option can -+ &samba_data_tool;, this option can - be used to specific an alternative location with the - help of an absolute path. - -@@ -493,7 +493,7 @@ $ adcli create-user Fry --domain=domain.example.com \ - - - The full distinguished name of the OU in -- which to create the user account. If not specified -+ which to create the user account. If not specified, - then the computer account will be created in a default - location. - -@@ -569,7 +569,7 @@ $ adcli create-group Pilots --domain=domain.example.com \ - - - The full distinguished name of the OU in -- which to create the group. If not specified -+ which to create the group. If not specified, - then the group will be created in a default - location. - -@@ -649,14 +649,14 @@ Password for Administrator: - - - The full distinguished name of the OU in -- which to create the computer accounts. If not specified -+ which to create the computer accounts. If not specified, - then the computer account will be created in a default - location. - - - - Specify a one time password to use when -- presetting the computer accounts. If not specified then -+ presetting the computer accounts. If not specified, then - a default password will be used, which allows for later - automatic joins. - -@@ -696,7 +696,7 @@ Password for Administrator: - Reset Computer Account - - adcli reset-computer resets a computer account -- in the domain. If a the appropriate machine is currently joined to the -+ in the domain. If the appropriate machine is currently joined to the - domain, then its membership will be broken. The account must already - exist. - -@@ -716,7 +716,7 @@ $ adcli reset-computer --domain=domain.example.com host2 - - Specify the type of authentication that - will be performed before creating the machine account in -- the domain. If set to 'computer' then the computer must -+ the domain. If set to 'computer', then the computer must - already have a preset account in the domain. If not - specified and none of the other - arguments have been specified, then will try both --- -2.14.4 - diff --git a/SPECS/adcli.spec b/SPECS/adcli.spec index 3fc795c..a67807e 100644 --- a/SPECS/adcli.spec +++ b/SPECS/adcli.spec @@ -1,187 +1,27 @@ -Name: adcli -Version: 0.8.2 -Release: 12%{?dist} -Summary: Active Directory enrollment -License: LGPLv2+ -URL: http://cgit.freedesktop.org/realmd/adcli -Source0: http://www.freedesktop.org/software/realmd/releases/adcli-%{version}.tar.gz - -Patch1: 0001-Remove-upper-case-only-check-when-looking-for-the-Ne.patch -Patch2: 0002-Use-strdup-if-offset-are-used.patch -Patch3: 0003-correct-spelling-of-adcli_tool_computer_delete-descr.patch -Patch4: 0004-doc-explain-that-all-credential-cache-types-are-supp.patch -Patch5: 0005-library-add-adcli_conn_is_writeable.patch -Patch6: 0006-Handle-kvno-increment-for-RODCs.patch -Patch7: 0007-Fix-memory-leak-in-test_check_nt_time_string_lifetim.patch -Patch8: 0008-library-add-_adcli_bin_sid_to_str.patch -Patch9: 0009-library-add-_adcli_call_external_program.patch -Patch10: 0010-library-add-_adcli_ldap_parse_sid.patch -Patch11: 0011-library-add-lookup_domain_sid.patch -Patch12: 0012-library-add-adcli_conn_get_domain_sid.patch -Patch13: 0013-tools-add-option-add-samba-data.patch -Patch14: 0014-tools-store-Samba-data-if-requested.patch -Patch15: 0015-make-Samba-data-tool-configurable.patch -Patch16: 0016-Add-trusted-for-delegation-option.patch -Patch17: 0017-Only-update-attributes-given-on-the-command-line.patch -Patch18: 0018-update-allow-to-add-service-names.patch -Patch19: 0019-Calculate-enctypes-in-a-separate-function.patch -Patch20: 0020-join-add-all-attributes-while-creating-computer-obje.patch -Patch21: 0021-util-add-_adcli_strv_remove_unsorted.patch -Patch22: 0022-Add-add-service-principal-and-remove-service-princip.patch -Patch23: 0023-adcli_conn_is_writeable-do-not-crash-id-domain_disco.patch -Patch24: 0024-doc-fix-typos-in-the-adcli-man-page.patch - -Patch25: 0001-fix-typo-in-flag-value.patch -Patch26: 0002-_adcli_call_external_program-silence-noisy-debug-mes.patch -Patch27: 0003-Do-not-add-service-principals-twice.patch -Patch28: 0004-Do-not-depend-on-default_realm-in-krb5.conf.patch - -# rhbz#1677194 - Realm cannot join domain when hostname is not FQDN -Patch29: 0001-adutil-add-_adcli_strv_add_unique.patch -Patch30: 0002-adenroll-use-_adcli_strv_add_unique-for-service-prin.patch - -# Forward port of RHEL-7.7 ticket rhbz#1642546 - adcli exports kerberos ticket -# with old kvno -Patch31: 0001-Increment-kvno-after-password-change-with-user-creds.patch - -# Forward port of RHEL-7.7 ticket rhbz#1595911 - [RFE] Have `adcli join` work -# without FQDN in `hostname` output -Patch32: 0001-library-use-getaddrinfo-with-AI_CANONNAME-to-find-a-.patch - -# Forward port of RHEL-7.7 ticket rhbz#1644311 - Improve handling of service -# principals -Patch33: 0001-join-always-add-service-principals.patch -Patch34: 0002-library-return-error-if-no-matching-key-was-found.patch - -# Forward port of RHEL-7.7 ticket rhbz#1337489 - [RFE] adcli command with -# --unix-* options doesn't update values in UnixAttributes Tab for user -Patch35: 0001-create-user-add-nis-domain-option.patch -Patch36: 0002-create-user-try-to-find-NIS-domain-if-needed.patch - -# Forward port of RHEL-7.7 ticket rhbz#1630187 - [RFE] adcli join should -# preserve SPN added by adcli preset-computer -Patch37: 0001-ensure_keytab_principals-do-not-leak-memory-when-cal.patch -Patch38: 0002-library-make-_adcli_strv_has_ex-public.patch -Patch39: 0003-library-_adcli_krb5_build_principal-allow-principals.patch -Patch40: 0004-library-make-sure-server-side-SPNs-are-preserved.patch - -# Forward port of RHEL-7.7 ticket rhbz#1622583 - [RFE] Need an option for adcli -# command which will show domain join status. -Patch41: 0001-Implement-adcli-testjoin.patch - -# Forward port of RHEL-7.7 ticket rhbz#1630187 - [RFE] adcli join should -# preserve SPN added by adcli preset-computer - additional patch -Patch42: 0001-library-add-missing-strdup.patch - -# Forward port of RHEL-7.7 ticket rhbz#1588596 - many adcli-krb5-????? -# directories are created /tmp -Patch43: 0001-tools-remove-errx-from-computer-commands.patch -Patch44: 0002-tools-remove-errx-from-user-and-group-commands.patch -Patch45: 0003-tools-remove-errx-from-info-commands.patch -Patch46: 0004-tools-remove-errx-from-adcli_read_password_func.patch -Patch47: 0005-tools-remove-errx-from-setup_krb5_conf_directory.patch -Patch48: 0006-tools-entry-remove-errx-from-parse_option.patch -Patch49: 0007-tools-computer-remove-errx-from-parse_option.patch - -# rhbz#1717355 - `adcli join` fails in FIPS enabled environment -Patch50: 0001-Fix-for-issues-found-by-Coverity.patch -Patch51: 0001-adenroll-make-sure-only-allowed-enctypes-are-used-in.patch -Patch52: 0002-adconn-add-adcli_conn_set_krb5_context.patch -Patch53: 0003-adenroll-add-adcli_enroll_get_permitted_keytab_encty.patch -Patch54: 0004-adenroll-use-only-enctypes-permitted-by-Kerberos-con.patch - -# rhbz#1745931 - adcli update --add-samba-data does not work as expected -Patch55: 0001-doc-explain-how-to-force-password-reset.patch -Patch56: 0001-man-move-note-to-the-right-section.patch - -# rhbz#1745932 - Issue is that with arcfour-hmac as first encryption type -Patch57: 0001-Do-not-use-arcfour-hmac-md5-when-discovering-the-sal.patch - -Patch58: 0001-Fix-for-issue-found-by-Coverity.patch - -# rhbz#1737342 - [RFE] enhancement adcli to set description attribute and to -# show all AD attributes -Patch59: 0001-tools-add-show-computer-command.patch -Patch60: 0002-add-description-option-to-join-and-update.patch - -Patch61: 0001-Use-GSS-SPNEGO-if-available.patch -Patch62: 0002-add-option-use-ldaps.patch - -# rhbz#1806260 - [abrt] [faf] adcli: raise(): /usr/sbin/adcli killed by 6 -Patch63: 0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch -Patch64: 0001-discovery-fix.patch - -# rhbz#1846882 - No longer able to delete computer from AD using adcli -Patch65: 0001-delete-do-not-exit-if-keytab-cannot-be-read.patch - -# rhbz#1846878 - adcli: presetting $computer in $domain domain failed: Cannot -# set computer password: Authentication error -Patch66: 0001-tools-disable-SSSD-s-locator-plugin.patch - -# rhbz#1791611 - Typo in adcli update --help option -Patch67: 0001-tools-fix-typo-in-show-password-help-output.patch - -# rhbz#1791545 - Manpage and help does not explain the use of "-C" option -Patch68: 0001-man-explain-optional-parameter-of-login-ccache-bette.patch -Patch69: 0001-man-make-handling-of-optional-credential-cache-more-.patch - -# rhbz#1883467 - Add --use-ldaps option to adcli update as well -Patch70: 0001-tools-add-missing-use-ldaps-option-to-update-and-tes.patch - -# rhbz#1734764 - Cannot join a pre-staged Computer Account on AD in Custom OU -# using Delegated user -Patch71: 0001-join-update-set-dNSHostName-if-not-set.patch - -# rhbz#1852080 - missing documentation for required AD rights for adcli join -# and net join -Patch72: 0001-doc-add-missing-samba_data_tool_path.xml-.in-to-EXTR.patch -Patch73: 0001-doc-explain-required-AD-permissions.patch - -# rhbz#1854112 - [RFE] Add new mode to just create an AD account to be able to -# connect to LDAP -Patch74: 0001-enroll-add-is_service-member.patch -Patch75: 0002-computer-add-create-msa-sub-command.patch -Patch76: 0003-enroll-use-computer-or-service-in-debug-messages.patch -Patch77: 0004-enroll-more-filters-for-random-characters.patch -Patch78: 0005-enroll-make-adcli_enroll_add_keytab_for_service_acco.patch -Patch79: 0006-enroll-allow-fqdn-for-locate_computer_account.patch -Patch80: 0007-service-account-add-random-suffix-to-account-name.patch - -# rhbz#1906303 - Typo in CREATE A SERVICE ACCOUNT section of man page of adcli -Patch81: 0001-service-account-fix-typo-in-the-man-page-entry.patch - -# rhbz#1889386 - [RFE] Adcli and Realm Error Code Optimization Request -Patch82: 0001-build-add-with-vendor-error-message-configure-option.patch - -# rhbz#1769644 - [RFE] adcli should allow to modify DONT_EXPIRE_PASSWORD attribute -Patch83: 0001-coverity-add-missing-NULL-checks.patch -Patch84: 0002-Add-dont-expire-password-option.patch -Patch85: 0001-Fix-for-dont-expire-password-option-and-join.patch - -# rhbz#1952828 - [RFE] Allow adcli to create AD user with password as well as -# set or reset existing user password -Patch86: 0001-library-move-UAC-flags-to-a-more-common-header-file.patch -Patch87: 0002-adcli_entry-add-entry_attrs-with-userAccountControl-.patch -Patch88: 0003-entry-add-passwd-user-sub-command.patch - -# rhbz#1690920 - [RFE] add option to populate "managed by" computer attribute -Patch89: 0001-Add-setattr-option.patch -Patch90: 0002-Add-delattr-option.patch - -BuildRequires: gcc -BuildRequires: intltool pkgconfig -BuildRequires: libtool -BuildRequires: gettext-devel -BuildRequires: krb5-devel -BuildRequires: openldap-devel -BuildRequires: libxslt -BuildRequires: xmlto - -Requires: cyrus-sasl-gssapi +Name: adcli +Version: 0.9.2 +Release: 1%{?dist} +Summary: Active Directory enrollment +License: LGPLv2+ +URL: https://gitlab.freedesktop.org/realmd/adcli +Source0: https://gitlab.freedesktop.org/realmd/adcli/uploads/ea560656ac921b3fe0d455976aaae9be/adcli-%{version}.tar.gz + +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 +Conflicts: adcli-doc < %{version}-%{release} # 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 @@ -208,11 +48,7 @@ make check make install DESTDIR=%{buildroot} find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' -%post -p /sbin/ldconfig - -%postun -p /sbin/ldconfig - -%clean +%ldconfig_scriptlets %files %{_sbindir}/adcli @@ -222,6 +58,7 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %package doc Summary: adcli documentation BuildArch: noarch +Conflicts: adcli < %{version}-%{release} %description doc adcli is a tool for joining an Active Directory domain using @@ -232,6 +69,10 @@ documentation. %doc %{_datadir}/doc/adcli/* %changelog +* Fri Oct 21 2022 Sumit Bose - 0.9.2-1 +- Update to upstream release 0.9.2 + Resolves: rhbz#1991619, rhbz#2111348, rhbz#2133838 + * Mon Jun 14 2021 Sumit Bose - 0.8.2-12 - [RFE] Allow adcli to create AD user with password as well as set or reset existing user password [#1952828]