1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-08 05:57:51 +03:00

s3:libads: Fix creating machine account using LDAP

This implements the same behaviour as Windows.

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 ce7762935051c862ecdd3e82d93096aac61dd292)
This commit is contained in:
Andreas Schneider 2019-08-13 16:34:34 +02:00 committed by Stefan Metzmacher
parent ac8c51fbb5
commit 1e38443496
3 changed files with 124 additions and 21 deletions

View File

@ -114,8 +114,10 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads, const char *machine_
const char **spns);
ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
const char *machine_name,
const char *machine_password,
const char *org_unit,
uint32_t etype_list);
uint32_t etype_list,
const char *dns_domain_name);
ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name,
const char *org_unit, bool *moved);
int ads_count_replies(ADS_STRUCT *ads, void *res);

View File

@ -1516,7 +1516,6 @@ ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
name, (const void **) vals);
}
#if 0
/**
* Add a single ber-encoded value to a mod list
* @param ctx An initialized TALLOC_CTX
@ -1537,7 +1536,6 @@ static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods,
return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES,
name, (const void **) values);
}
#endif
static void ads_print_error(int ret, LDAP *ld)
{
@ -2111,8 +2109,10 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads,
ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
const char *machine_name,
const char *machine_password,
const char *org_unit,
uint32_t etype_list)
uint32_t etype_list,
const char *dns_domain_name)
{
ADS_STATUS ret;
char *samAccountName = NULL;
@ -2120,13 +2120,23 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
TALLOC_CTX *ctx = NULL;
ADS_MODLIST mods;
char *machine_escaped = NULL;
char *dns_hostname = NULL;
char *new_dn = NULL;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
char *utf8_pw = NULL;
size_t utf8_pw_len = 0;
char *utf16_pw = NULL;
size_t utf16_pw_len = 0;
struct berval machine_pw_val;
bool ok;
const char **spn_array = NULL;
size_t num_spns = 0;
const char *spn_prefix[] = {
"HOST",
"RestrictedKrbHost",
};
size_t i;
LDAPMessage *res = NULL;
uint32_t acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\
UF_DONT_EXPIRE_PASSWD |\
UF_ACCOUNTDISABLE );
uint32_t acct_control = UF_WORKSTATION_TRUST_ACCOUNT;
ctx = talloc_init("ads_add_machine_acct");
if (ctx == NULL) {
@ -2139,10 +2149,9 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
goto done;
}
/* Check if the machine account already exists. */
ret = ads_find_machine_acct(ads, &res, machine_escaped);
if (ADS_ERR_OK(ret)) {
DBG_DEBUG("Host account for %s already exists.\n",
machine_escaped);
ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS);
ads_msgfree(ads, res);
goto done;
@ -2155,28 +2164,111 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
goto done;
}
/* Create machine account */
samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
if (samAccountName == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
dns_hostname = talloc_asprintf(ctx,
"%s.%s",
machine_name,
dns_domain_name);
if (dns_hostname == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
/* Add dns_hostname SPNs */
for (i = 0; i < ARRAY_SIZE(spn_prefix); i++) {
char *spn = talloc_asprintf(ctx,
"%s/%s",
spn_prefix[i],
dns_hostname);
if (spn == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
ok = add_string_to_array(spn_array,
spn,
&spn_array,
&num_spns);
if (!ok) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
}
/* Add machine_name SPNs */
for (i = 0; i < ARRAY_SIZE(spn_prefix); i++) {
char *spn = talloc_asprintf(ctx,
"%s/%s",
spn_prefix[i],
machine_name);
if (spn == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
ok = add_string_to_array(spn_array,
spn,
&spn_array,
&num_spns);
if (!ok) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
}
}
/* Make sure to NULL terminate the array */
spn_array = talloc_realloc(ctx, spn_array, const char *, num_spns + 1);
if (spn_array == NULL) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
spn_array[num_spns] = NULL;
controlstr = talloc_asprintf(ctx, "%u", acct_control);
if (controlstr == NULL) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
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);
goto done;
}
ads_mod_str(ctx, &mods, "cn", machine_name);
ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
ads_mod_str(ctx, &mods, "objectClass", "Computer");
ads_mod_str(ctx, &mods, "SamAccountName", samAccountName);
ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
ads_mod_str(ctx, &mods, "DnsHostName", dns_hostname);
ads_mod_strlist(ctx, &mods, "ServicePrincipalName", spn_array);
ads_mod_ber(ctx, &mods, "unicodePwd", &machine_pw_val);
ret = ads_gen_add(ads, new_dn, mods);

View File

@ -338,10 +338,22 @@ static ADS_STATUS libnet_join_precreate_machine_acct(TALLOC_CTX *mem_ctx,
/* Attempt to create the machine account and bail if this fails.
Assume that the admin wants exactly what they requested */
if (r->in.machine_password == NULL) {
r->in.machine_password =
trust_pw_new_value(mem_ctx,
r->in.secure_channel_type,
SEC_ADS);
if (r->in.machine_password == NULL) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
}
status = ads_create_machine_acct(r->in.ads,
r->in.machine_name,
r->in.machine_password,
r->in.account_ou,
r->in.desired_encryption_types);
r->in.desired_encryption_types,
r->out.dns_domain_name);
if (ADS_ERR_OK(status)) {
DEBUG(1,("machine account creation created\n"));
@ -2668,12 +2680,11 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
if (ADS_ERR_OK(ads_status)) {
/*
* LDAP object create succeeded, now go to the rpc
* password set routines
* LDAP object creation succeeded.
*/
r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
goto rpc_join;
return WERR_OK;
}
if (initial_account_ou != NULL) {
@ -2687,8 +2698,6 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
DBG_INFO("Failed to pre-create account in OU %s: %s\n",
r->in.account_ou, ads_errstr(ads_status));
}
rpc_join:
#endif /* HAVE_ADS */
if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) &&