#include "lib/param/loadparm.h"
#include "libcli/auth/netlogon_creds_cli.h"
#include "auth/credentials/credentials.h"
+#include "krb5_env.h"
/****************************************************************
****************************************************************/
const char *dc_name,
const char *user_name,
const char *password,
+ const char *ccname,
ADS_STRUCT **ads)
{
ADS_STATUS status;
my_ads->auth.password = SMB_STRDUP(password);
}
+ if (ccname != NULL) {
+ SAFE_FREE(my_ads->auth.ccache_name);
+ my_ads->auth.ccache_name = SMB_STRDUP(ccname);
+ setenv(KRB5_ENV_CCNAME, my_ads->auth.ccache_name, 1);
+ }
+
status = ads_connect_user_creds(my_ads);
if (!ADS_ERR_OK(status)) {
ads_destroy(&my_ads);
****************************************************************/
static ADS_STATUS libnet_join_connect_ads(TALLOC_CTX *mem_ctx,
- struct libnet_JoinCtx *r)
+ struct libnet_JoinCtx *r,
+ bool use_machine_creds)
{
ADS_STATUS status;
+ const char *username;
+ const char *password;
+ const char *ccname = NULL;
+
+ if (use_machine_creds) {
+ if (r->in.machine_name == NULL ||
+ r->in.machine_password == NULL) {
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ username = talloc_strdup(mem_ctx, r->in.machine_name);
+ if (username == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+ if (username[strlen(username)] != '$') {
+ username = talloc_asprintf(username, "%s$", username);
+ if (username == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+ }
+ password = r->in.machine_password;
+ ccname = "MEMORY:libnet_join_machine_creds";
+ } else {
+ username = r->in.admin_account;
+ password = r->in.admin_password;
+
+ /*
+ * when r->in.use_kerberos is set to allow "net ads join -k" we
+ * may not override the provided credential cache - gd
+ */
+
+ if (!r->in.use_kerberos) {
+ ccname = "MEMORY:libnet_join_user_creds";
+ }
+ }
status = libnet_connect_ads(r->out.dns_domain_name,
r->out.netbios_domain_name,
r->in.dc_name,
- r->in.admin_account,
- r->in.admin_password,
+ username,
+ password,
+ ccname,
&r->in.ads);
if (!ADS_ERR_OK(status)) {
libnet_join_set_error_string(mem_ctx, r,
/****************************************************************
****************************************************************/
+static ADS_STATUS libnet_join_connect_ads_user(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
+{
+ return libnet_join_connect_ads(mem_ctx, r, false);
+}
+
+/****************************************************************
+****************************************************************/
+
+static ADS_STATUS libnet_join_connect_ads_machine(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
+{
+ return libnet_join_connect_ads(mem_ctx, r, true);
+}
+
+/****************************************************************
+****************************************************************/
+
static ADS_STATUS libnet_unjoin_connect_ads(TALLOC_CTX *mem_ctx,
struct libnet_UnjoinCtx *r)
{
r->in.dc_name,
r->in.admin_account,
r->in.admin_password,
+ NULL,
&r->in.ads);
if (!ADS_ERR_OK(status)) {
libnet_unjoin_set_error_string(mem_ctx, r,
status = ads_create_machine_acct(r->in.ads,
r->in.machine_name,
- r->in.account_ou);
+ r->in.account_ou,
+ r->in.desired_encryption_types);
if (ADS_ERR_OK(status)) {
DEBUG(1,("machine account creation created\n"));
goto done;
}
+ if (!ads_pull_uint32(r->in.ads, res, "msDS-SupportedEncryptionTypes",
+ &r->out.set_encryption_types)) {
+ r->out.set_encryption_types = 0;
+ }
+
done:
ads_msgfree(r->in.ads, res);
TALLOC_FREE(dn);
return status;
}
+static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r,
+ char ***spn_array,
+ size_t *num_spns)
+{
+ ADS_STATUS status;
+
+ if (r->in.machine_name == NULL) {
+ return ADS_ERROR_SYSTEM(EINVAL);
+ }
+
+ status = ads_get_service_principal_names(mem_ctx,
+ r->in.ads,
+ r->in.machine_name,
+ spn_array,
+ num_spns);
+
+ return status;
+}
+
/****************************************************************
Set a machines dNSHostName and servicePrincipalName attributes
****************************************************************/
ADS_STATUS status;
ADS_MODLIST mods;
fstring my_fqdn;
- const char *spn_array[3] = {NULL, NULL, NULL};
+ const char **spn_array = NULL;
+ size_t num_spns = 0;
char *spn = NULL;
+ bool ok;
+ const char **netbios_aliases = NULL;
/* Find our DN */
return status;
}
+ status = libnet_join_get_machine_spns(mem_ctx,
+ r,
+ discard_const_p(char **, &spn_array),
+ &num_spns);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(5, ("Retrieving the servicePrincipalNames failed.\n"));
+ }
+
/* Windows only creates HOST/shortname & HOST/fqdn. */
spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name);
if (!strupper_m(spn)) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
- spn_array[0] = spn;
+
+ ok = ads_element_in_array(spn_array, num_spns, spn);
+ if (!ok) {
+ ok = add_string_to_array(spn_array, spn,
+ &spn_array, &num_spns);
+ if (!ok) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ }
if (!name_to_fqdn(my_fqdn, r->in.machine_name)
|| (strchr(my_fqdn, '.') == NULL)) {
if (!spn) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
- spn_array[1] = spn;
+
+ ok = ads_element_in_array(spn_array, num_spns, spn);
+ if (!ok) {
+ ok = add_string_to_array(spn_array, spn,
+ &spn_array, &num_spns);
+ if (!ok) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ }
+ }
+
+ netbios_aliases = lp_netbios_aliases();
+ if (netbios_aliases != NULL) {
+ for (; *netbios_aliases != NULL; netbios_aliases++) {
+ /*
+ * Add HOST/NETBIOSNAME
+ */
+ spn = talloc_asprintf(mem_ctx, "HOST/%s", *netbios_aliases);
+ if (spn == NULL) {
+ TALLOC_FREE(spn);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ if (!strupper_m(spn)) {
+ TALLOC_FREE(spn);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ ok = ads_element_in_array(spn_array, num_spns, spn);
+ if (ok) {
+ TALLOC_FREE(spn);
+ continue;
+ }
+ ok = add_string_to_array(spn_array, spn,
+ &spn_array, &num_spns);
+ if (!ok) {
+ TALLOC_FREE(spn);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ TALLOC_FREE(spn);
+
+ /*
+ * Add HOST/netbiosname.domainname
+ */
+ if (r->out.dns_domain_name == NULL) {
+ continue;
+ }
+ fstr_sprintf(my_fqdn, "%s.%s",
+ *netbios_aliases,
+ r->out.dns_domain_name);
+
+ spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn);
+ if (spn == NULL) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ ok = ads_element_in_array(spn_array, num_spns, spn);
+ if (ok) {
+ TALLOC_FREE(spn);
+ continue;
+ }
+ ok = add_string_to_array(spn_array, spn,
+ &spn_array, &num_spns);
+ if (!ok) {
+ TALLOC_FREE(spn);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ TALLOC_FREE(spn);
+ }
+ }
+
+ /* make sure to NULL terminate the array */
+ spn_array = talloc_realloc(mem_ctx, spn_array, const char *, num_spns + 1);
+ if (spn_array == NULL) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
+ spn_array[num_spns] = NULL;
mods = ads_init_mods(mem_ctx);
if (!mods) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- os_sp = talloc_asprintf(mem_ctx, "Samba %s", samba_version_string());
- if (!os_sp) {
+ if (r->in.os_servicepack) {
+ /*
+ * if blank string then leave os_sp equal to NULL to force
+ * attribute delete (LDAP_MOD_DELETE)
+ */
+ if (!strequal(r->in.os_servicepack,"")) {
+ os_sp = talloc_strdup(mem_ctx, r->in.os_servicepack);
+ }
+ } else {
+ os_sp = talloc_asprintf(mem_ctx, "Samba %s",
+ samba_version_string());
+ }
+ if (!os_sp && !strequal(r->in.os_servicepack,"")) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
/****************************************************************
****************************************************************/
+static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
+{
+ ADS_STATUS status;
+ ADS_MODLIST mods;
+ const char *etype_list_str;
+
+ etype_list_str = talloc_asprintf(mem_ctx, "%d",
+ r->in.desired_encryption_types);
+ if (!etype_list_str) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = libnet_join_find_machine_acct(mem_ctx, r);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if (r->in.desired_encryption_types == r->out.set_encryption_types) {
+ return ADS_SUCCESS;
+ }
+
+ /* now do the mods */
+
+ mods = ads_init_mods(mem_ctx);
+ if (!mods) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_mod_str(mem_ctx, &mods, "msDS-SupportedEncryptionTypes",
+ etype_list_str);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ status = ads_gen_mod(r->in.ads, r->out.dn, mods);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ r->out.set_encryption_types = r->in.desired_encryption_types;
+
+ return ADS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx,
struct libnet_JoinCtx *r)
{
struct libnet_JoinCtx *r)
{
ADS_STATUS status;
+ bool need_etype_update = false;
if (!r->in.ads) {
- status = libnet_join_connect_ads(mem_ctx, r);
+ status = libnet_join_connect_ads_user(mem_ctx, r);
if (!ADS_ERR_OK(status)) {
return status;
}
return status;
}
+ status = libnet_join_find_machine_acct(mem_ctx, r);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if (r->in.desired_encryption_types != r->out.set_encryption_types) {
+ uint32_t func_level = 0;
+
+ status = ads_domain_func_level(r->in.ads, &func_level);
+ if (!ADS_ERR_OK(status)) {
+ libnet_join_set_error_string(mem_ctx, r,
+ "failed to query domain controller functional level: %s",
+ ads_errstr(status));
+ return status;
+ }
+
+ if (func_level >= DS_DOMAIN_FUNCTION_2008) {
+ need_etype_update = true;
+ }
+ }
+
+ if (need_etype_update) {
+ /*
+ * We need to reconnect as machine account in order
+ * to update msDS-SupportedEncryptionTypes reliable
+ */
+
+ if (r->in.ads->auth.ccache_name != NULL) {
+ ads_kdestroy(r->in.ads->auth.ccache_name);
+ }
+
+ ads_destroy(&r->in.ads);
+
+ status = libnet_join_connect_ads_machine(mem_ctx, r);
+ if (!ADS_ERR_OK(status)) {
+ libnet_join_set_error_string(mem_ctx, r,
+ "Failed to connect as machine account: %s",
+ ads_errstr(status));
+ return status;
+ }
+
+ status = libnet_join_set_etypes(mem_ctx, r);
+ if (!ADS_ERR_OK(status)) {
+ libnet_join_set_error_string(mem_ctx, r,
+ "failed to set machine kerberos encryption types: %s",
+ ads_errstr(status));
+ return status;
+ }
+ }
+
if (!libnet_join_derive_salting_principal(mem_ctx, r)) {
return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
domain,
pass,
flags,
- SMB_SIGNING_DEFAULT);
+ SMB_SIGNING_IPC_DEFAULT);
}
/****************************************************************
return status;
}
- status = rpccli_setup_netlogon_creds(cli,
+ status = rpccli_setup_netlogon_creds(cli, NCACN_NP,
netlogon_creds,
true, /* force_reauth */
current_nt_hash,
TALLOC_CTX *frame = talloc_stackframe();
struct cli_state *cli = NULL;
struct rpc_pipe_client *netlogon_pipe = NULL;
+ struct cli_credentials *cli_creds = NULL;
struct netlogon_creds_cli_context *netlogon_creds = NULL;
struct netlogon_creds_CredentialState *creds = NULL;
uint32_t netlogon_flags = 0;
- enum netr_SchannelType sec_chan_type = 0;
NTSTATUS status;
- char *machine_password = NULL;
- const char *machine_name = NULL;
const char *machine_account = NULL;
+ const char *machine_domain = NULL;
+ const char *machine_password = NULL;
int flags = 0;
- struct samr_Password current_nt_hash;
- struct samr_Password *previous_nt_hash = NULL;
- bool ok;
if (!dc_name) {
TALLOC_FREE(frame);
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- ok = get_trust_pw_clear(netbios_domain_name,
- &machine_password,
- &machine_name,
- &sec_chan_type);
- if (!ok) {
+ status = pdb_get_trust_credentials(netbios_domain_name, NULL,
+ frame, &cli_creds);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ return status;
}
- machine_account = talloc_asprintf(frame, "%s$", machine_name);
- if (machine_account == NULL) {
- SAFE_FREE(machine_password);
- SAFE_FREE(previous_nt_hash);
- TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
+ /* we don't want any old password */
+ cli_credentials_set_old_password(cli_creds, NULL, CRED_SPECIFIED);
if (use_kerberos) {
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
}
+ machine_account = cli_credentials_get_username(cli_creds);
+ machine_domain = cli_credentials_get_domain(cli_creds);
+ machine_password = cli_credentials_get_password(cli_creds);
+
status = cli_full_connection(&cli, NULL,
dc_name,
NULL, 0,
"IPC$", "IPC",
machine_account,
- netbios_domain_name,
+ machine_domain,
machine_password,
flags,
- SMB_SIGNING_DEFAULT);
-
- E_md4hash(machine_password, current_nt_hash.hash);
- SAFE_FREE(machine_password);
+ SMB_SIGNING_IPC_DEFAULT);
if (!NT_STATUS_IS_OK(status)) {
status = cli_full_connection(&cli, NULL,
NULL,
"",
0,
- SMB_SIGNING_DEFAULT);
+ SMB_SIGNING_IPC_DEFAULT);
}
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(previous_nt_hash);
TALLOC_FREE(frame);
return status;
}
- status = rpccli_create_netlogon_creds(dc_name,
- netbios_domain_name,
- machine_account,
- sec_chan_type,
- msg_ctx,
- frame,
- &netlogon_creds);
+ status = rpccli_create_netlogon_creds_with_creds(cli_creds,
+ dc_name,
+ msg_ctx,
+ frame,
+ &netlogon_creds);
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(previous_nt_hash);
cli_shutdown(cli);
TALLOC_FREE(frame);
return status;
}
- status = rpccli_setup_netlogon_creds(cli,
- netlogon_creds,
- true, /* force_reauth */
- current_nt_hash,
- previous_nt_hash);
- SAFE_FREE(previous_nt_hash);
+ status = rpccli_setup_netlogon_creds_with_creds(cli, NCACN_NP,
+ netlogon_creds,
+ true, /* force_reauth */
+ cli_creds);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("connect_to_domain_password_server: "
"unable to open the domain client session to "
return NT_STATUS_OK;
}
- status = cli_rpc_pipe_open_schannel_with_key(
+ status = cli_rpc_pipe_open_schannel_with_creds(
cli, &ndr_table_netlogon, NCACN_NP,
- netbios_domain_name,
+ cli_creds,
netlogon_creds, &netlogon_pipe);
TALLOC_FREE(netlogon_pipe);
return WERR_INVALID_PARAM;
}
- if (IS_DC) {
- return WERR_SETUP_DOMAIN_CONTROLLER;
- }
-
if (!r->in.admin_domain) {
char *admin_domain = NULL;
char *admin_account = NULL;
ctx->in.secure_channel_type = SEC_CHAN_WKSTA;
+ ctx->in.desired_encryption_types = ENC_CRC32 |
+ ENC_RSA_MD5 |
+ ENC_RC4_HMAC_MD5;
+#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+ ctx->in.desired_encryption_types |= ENC_HMAC_SHA1_96_AES128;
+#endif
+#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
+ ctx->in.desired_encryption_types |= ENC_HMAC_SHA1_96_AES256;
+#endif
+
*r = ctx;
return WERR_OK;
switch (r->out.domain_is_ad) {
case false:
- valid_security = (lp_security() == SEC_DOMAIN);
+ valid_security = (lp_security() == SEC_DOMAIN)
+ || (lp_server_role() == ROLE_DOMAIN_PDC)
+ || (lp_server_role() == ROLE_DOMAIN_BDC);
if (valid_workgroup && valid_security) {
/* nothing to be done */
return WERR_OK;
W_ERROR_HAVE_NO_MEMORY(wrong_conf);
}
+ /*
+ * We should generate the warning for the special case when
+ * domain is AD, "security = domain" and the realm parameter is
+ * not set.
+ */
+ if (lp_security() == SEC_DOMAIN &&
+ r->out.domain_is_ad &&
+ !valid_realm) {
+ libnet_join_set_error_string(mem_ctx, r,
+ "Warning: when joining AD domains with security=domain, "
+ "\"realm\" should be defined in the configuration (%s) "
+ "and configuration modification was not requested",
+ wrong_conf);
+ return WERR_OK;
+ }
+
libnet_join_set_error_string(mem_ctx, r,
"Invalid configuration (%s) and configuration modification "
"was not requested", wrong_conf);
+
return WERR_CAN_NOT_COMPLETE;
}
#ifdef HAVE_ADS
ADS_STATUS ads_status;
#endif /* HAVE_ADS */
+ const char *pre_connect_realm = NULL;
+ const char *numeric_dcip = NULL;
+ const char *sitename = NULL;
+
+ /* Before contacting a DC, we can securely know
+ * the realm only if the user specifies it.
+ */
+ if (r->in.use_kerberos &&
+ r->in.domain_name_type == JoinDomNameTypeDNS) {
+ pre_connect_realm = r->in.domain_name;
+ }
if (!r->in.dc_name) {
struct netr_DsRGetDCNameInfo *info;
const char *dc;
+ uint32_t name_type_flags = 0;
+ if (r->in.domain_name_type == JoinDomNameTypeDNS) {
+ name_type_flags = DS_IS_DNS_NAME;
+ } else if (r->in.domain_name_type == JoinDomNameTypeNBT) {
+ name_type_flags = DS_IS_FLAT_NAME;
+ }
status = dsgetdcname(mem_ctx,
r->in.msg_ctx,
r->in.domain_name,
DS_FORCE_REDISCOVERY |
DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
- DS_RETURN_DNS_NAME,
+ DS_RETURN_DNS_NAME |
+ name_type_flags,
&info);
if (!NT_STATUS_IS_OK(status)) {
libnet_join_set_error_string(mem_ctx, r,
dc = strip_hostname(info->dc_unc);
r->in.dc_name = talloc_strdup(mem_ctx, dc);
W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
+
+ if (info->dc_address == NULL || info->dc_address[0] != '\\' ||
+ info->dc_address[1] != '\\') {
+ DBG_ERR("ill-formed DC address '%s'\n",
+ info->dc_address);
+ return WERR_DCNOTFOUND;
+ }
+
+ numeric_dcip = info->dc_address + 2;
+ sitename = info->dc_site_name;
+ /* info goes out of scope but the memory stays
+ allocated on the talloc context */
+ }
+
+ if (pre_connect_realm != NULL) {
+ struct sockaddr_storage ss = {0};
+
+ if (numeric_dcip != NULL) {
+ if (!interpret_string_addr(&ss, numeric_dcip,
+ AI_NUMERICHOST)) {
+ DBG_ERR(
+ "cannot parse IP address '%s' of DC '%s'\n",
+ numeric_dcip, r->in.dc_name);
+ return WERR_DCNOTFOUND;
+ }
+ } else {
+ if (!interpret_string_addr(&ss, r->in.dc_name, 0)) {
+ DBG_WARNING(
+ "cannot resolve IP address of DC '%s'\n",
+ r->in.dc_name);
+ return WERR_DCNOTFOUND;
+ }
+ }
+
+ /* The domain parameter is only used as modifier
+ * to krb5.conf file name. .JOIN is is not a valid
+ * NetBIOS name so it cannot clash with another domain
+ * -- Uri.
+ */
+ create_local_private_krb5_conf_for_domain(
+ pre_connect_realm, ".JOIN", sitename, &ss);
}
status = libnet_join_lookup_dc_rpc(mem_ctx, r, &cli);
create_local_private_krb5_conf_for_domain(
r->out.dns_domain_name, r->out.netbios_domain_name,
- NULL, smbXcli_conn_remote_sockaddr(cli->conn));
+ sitename, smbXcli_conn_remote_sockaddr(cli->conn));
- if (r->out.domain_is_ad && r->in.account_ou &&
+ if (r->out.domain_is_ad &&
!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
- ads_status = libnet_join_connect_ads(mem_ctx, r);
+ const char *initial_account_ou = r->in.account_ou;
+
+ /*
+ * we want to create the msDS-SupportedEncryptionTypes attribute
+ * as early as possible so always try an LDAP create as the user
+ * first. We copy r->in.account_ou because it may be changed
+ * during the machine pre-creation.
+ */
+
+ ads_status = libnet_join_connect_ads_user(mem_ctx, r);
if (!ADS_ERR_OK(ads_status)) {
return WERR_DEFAULT_JOIN_REQUIRED;
}
ads_status = libnet_join_precreate_machine_acct(mem_ctx, r);
- if (!ADS_ERR_OK(ads_status)) {
+ if (ADS_ERR_OK(ads_status)) {
+
+ /*
+ * LDAP object create succeeded, now go to the rpc
+ * password set routines
+ */
+
+ r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
+ goto rpc_join;
+ }
+
+ if (initial_account_ou != NULL) {
libnet_join_set_error_string(mem_ctx, r,
"failed to precreate account in ou %s: %s",
r->in.account_ou,
return WERR_DEFAULT_JOIN_REQUIRED;
}
- r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
+ DEBUG(5, ("failed to precreate account in ou %s: %s",
+ r->in.account_ou, ads_errstr(ads_status)));
}
#endif /* HAVE_ADS */
+ rpc_join:
if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) &&
(r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED)) {
status = libnet_join_joindomain_rpc_unsecure(mem_ctx, r, cli);