summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2019-08-08 14:40:04 +0200
committerStefan Metzmacher <metze@samba.org>2019-10-16 12:15:54 +0000
commitf65a755bdd16527dd84708fa77199f6162b19584 (patch)
tree072eea681b9a7b3f6d3f3aca1aab2669df692a83
parent9d984cebde3516a42173b77664c5d79b96ad3bbc (diff)
downloadsamba-f65a755bdd16527dd84708fa77199f6162b19584.tar.gz
s3:libads: Just change the machine password if account already exists
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13884 Pair-Programmed-With: Guenther Deschner <gd@samba.org> Signed-off-by: Guenther Deschner <gd@samba.org> Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Alexander Bokovoy <ab@samba.org> (cherry picked from commit 14f320fa1e40ecc3a43dabb0cecd57430270a521)
-rw-r--r--source3/libads/ldap.c167
-rw-r--r--source3/libnet/libnet_join.c1
2 files changed, 146 insertions, 22 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 81efda0cf30..afae46d2e79 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -2098,6 +2098,127 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads,
return ret;
}
+static uint32_t ads_get_acct_ctrl(ADS_STRUCT *ads,
+ LDAPMessage *msg)
+{
+ uint32_t acct_ctrl = 0;
+ bool ok;
+
+ ok = ads_pull_uint32(ads, msg, "userAccountControl", &acct_ctrl);
+ if (!ok) {
+ return 0;
+ }
+
+ return acct_ctrl;
+}
+
+static ADS_STATUS ads_change_machine_acct(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ const struct berval *machine_pw_val)
+{
+ ADS_MODLIST mods;
+ ADS_STATUS ret;
+ TALLOC_CTX *frame = talloc_stackframe();
+ uint32_t acct_control;
+ char *control_str = NULL;
+ const char *attrs[] = {
+ "objectSid",
+ NULL
+ };
+ LDAPMessage *res = NULL;
+ char *dn = NULL;
+
+ dn = ads_get_dn(ads, frame, msg);
+ if (dn == NULL) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ acct_control = ads_get_acct_ctrl(ads, msg);
+ if (acct_control == 0) {
+ ret = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ goto done;
+ }
+
+ /*
+ * Changing the password, disables the account. So we need to change the
+ * userAccountControl flags to enable it again.
+ */
+ mods = ads_init_mods(frame);
+ if (mods == NULL) {
+ ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ ads_mod_ber(frame, &mods, "unicodePwd", machine_pw_val);
+
+ ret = ads_gen_mod(ads, dn, mods);
+ if (!ADS_ERR_OK(ret)) {
+ goto done;
+ }
+ TALLOC_FREE(mods);
+
+ /*
+ * To activate the account, we need to disable and enable it.
+ */
+ acct_control |= UF_ACCOUNTDISABLE;
+
+ control_str = talloc_asprintf(frame, "%u", acct_control);
+ if (control_str == NULL) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ mods = ads_init_mods(frame);
+ if (mods == NULL) {
+ ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ ads_mod_str(frame, &mods, "userAccountControl", control_str);
+
+ ret = ads_gen_mod(ads, dn, mods);
+ if (!ADS_ERR_OK(ret)) {
+ goto done;
+ }
+ TALLOC_FREE(mods);
+ TALLOC_FREE(control_str);
+
+ /*
+ * Enable the account again.
+ */
+ acct_control &= ~UF_ACCOUNTDISABLE;
+
+ control_str = talloc_asprintf(frame, "%u", acct_control);
+ if (control_str == NULL) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ mods = ads_init_mods(frame);
+ if (mods == NULL) {
+ ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ ads_mod_str(frame, &mods, "userAccountControl", control_str);
+
+ ret = ads_gen_mod(ads, dn, mods);
+ if (!ADS_ERR_OK(ret)) {
+ goto done;
+ }
+ TALLOC_FREE(mods);
+ TALLOC_FREE(control_str);
+
+ ret = ads_search_dn(ads, &res, dn, attrs);
+ ads_msgfree(ads, res);
+
+done:
+ talloc_free(frame);
+
+ return ret;
+}
+
/**
* adds a machine account to the ADS server
* @param ads An intialized ADS_STRUCT
@@ -2149,11 +2270,34 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
goto done;
}
+ utf8_pw = talloc_asprintf(ctx, "\"%s\"", machine_password);
+ if (utf8_pw == NULL) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+ utf8_pw_len = strlen(utf8_pw);
+
+ ok = convert_string_talloc(ctx,
+ CH_UTF8, CH_UTF16MUNGED,
+ utf8_pw, utf8_pw_len,
+ (void *)&utf16_pw, &utf16_pw_len);
+ if (!ok) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ machine_pw_val = (struct berval) {
+ .bv_val = utf16_pw,
+ .bv_len = utf16_pw_len,
+ };
+
/* Check if the machine account already exists. */
ret = ads_find_machine_acct(ads, &res, machine_escaped);
if (ADS_ERR_OK(ret)) {
- ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS);
+ /* Change the machine account password */
+ ret = ads_change_machine_acct(ads, res, &machine_pw_val);
ads_msgfree(ads, res);
+
goto done;
}
ads_msgfree(ads, res);
@@ -2236,27 +2380,6 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
goto done;
}
- utf8_pw = talloc_asprintf(ctx, "\"%s\"", machine_password);
- if (utf8_pw == NULL) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto done;
- }
- utf8_pw_len = strlen(utf8_pw);
-
- ok = convert_string_talloc(ctx,
- CH_UTF8, CH_UTF16MUNGED,
- utf8_pw, utf8_pw_len,
- (void *)&utf16_pw, &utf16_pw_len);
- if (!ok) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto done;
- }
-
- machine_pw_val = (struct berval) {
- .bv_val = utf16_pw,
- .bv_len = utf16_pw_len,
- };
-
mods = ads_init_mods(ctx);
if (mods == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 31d1d221ed3..1052afde641 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -968,6 +968,7 @@ static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx,
if (r->in.ads->auth.ccache_name != NULL) {
ads_kdestroy(r->in.ads->auth.ccache_name);
+ r->in.ads->auth.ccache_name = NULL;
}
ads_destroy(&r->in.ads);