/****************************************************************
****************************************************************/
+static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r,
+ const char *format, ...)
+ PRINTF_ATTRIBUTE(3,4);
+
static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx,
struct libnet_JoinCtx *r,
const char *format, ...)
/****************************************************************
****************************************************************/
+static void libnet_unjoin_set_error_string(TALLOC_CTX *mem_ctx,
+ struct libnet_UnjoinCtx *r,
+ const char *format, ...)
+ PRINTF_ATTRIBUTE(3,4);
+
static void libnet_unjoin_set_error_string(TALLOC_CTX *mem_ctx,
struct libnet_UnjoinCtx *r,
const char *format, ...)
/****************************************************************
****************************************************************/
-#if 0
+
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);
}
-#endif
+
/****************************************************************
****************************************************************/
size_t num_spns = 0;
char *spn = NULL;
bool ok;
+ const char **netbios_aliases = NULL;
/* Find our DN */
}
}
+ 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) {
/****************************************************************
****************************************************************/
-#if 0
+
static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
struct libnet_JoinCtx *r)
{
return ADS_SUCCESS;
}
-#endif
+
/****************************************************************
****************************************************************/
struct libnet_JoinCtx *r)
{
ADS_STATUS status;
+ bool need_etype_update = false;
if (!r->in.ads) {
status = libnet_join_connect_ads_user(mem_ctx, r);
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);
}
/****************************************************************
ZERO_STRUCT(user_info.info16);
user_info.info16.acct_flags = acct_flags;
- status = dcerpc_samr_SetUserInfo(b, mem_ctx,
- &user_pol,
- 16,
- &user_info,
- &result);
+ status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
+ &user_pol,
+ UserControlInformation,
+ &user_info,
+ &result);
if (!NT_STATUS_IS_OK(status)) {
dcerpc_samr_DeleteUser(b, mem_ctx,
&user_pol,
status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
&user_pol,
- 26,
+ UserInternal5InformationNew,
&user_info,
&result);
status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
&user_pol,
- 24,
+ UserInternal5Information,
&user_info,
&result);
}
machine_domain,
machine_password,
flags,
- SMB_SIGNING_DEFAULT);
+ 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)) {
libnet_join_set_error_string(mem_ctx, r,
"failed to verify domain membership after joining: %s",
get_friendly_nt_error_msg(status));
- return WERR_SETUP_NOT_JOINED;
+ return WERR_NERR_SETUPNOTJOINED;
}
return WERR_OK;
err = smbconf_init_reg(r, &ctx, NULL);
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "security", "user");
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "workgroup",
r->in.domain_name);
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "security", "domain");
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "workgroup",
r->out.netbios_domain_name);
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
if (r->out.domain_is_ad) {
err = smbconf_set_global_parameter(ctx, "security", "ads");
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "realm",
r->out.dns_domain_name);
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
}
err = smbconf_init_reg(r, &ctx, NULL);
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_set_global_parameter(ctx, "security", "user");
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
err = smbconf_delete_global_parameter(ctx, "workgroup");
if (!SBC_ERROR_IS_OK(err)) {
- werr = WERR_NO_SUCH_SERVICE;
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
goto done;
}
if (!r->in.domain_name) {
libnet_join_set_error_string(mem_ctx, r,
"No domain name defined");
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (strlen(r->in.machine_name) > 15) {
"\"%s\" is %u chars long\n",
r->in.machine_name,
(unsigned int)strlen(r->in.machine_name));
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name,
&r->in.dc_name)) {
libnet_join_set_error_string(mem_ctx, r,
"Failed to parse domain name");
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (!r->in.admin_domain) {
char *admin_domain = NULL;
char *admin_account = NULL;
- split_domain_user(mem_ctx,
- r->in.admin_account,
- &admin_domain,
- &admin_account);
- r->in.admin_domain = admin_domain;
+ bool ok;
+
+ ok = split_domain_user(mem_ctx,
+ r->in.admin_account,
+ &admin_domain,
+ &admin_account);
+ if (!ok) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ if (admin_domain != NULL) {
+ r->in.admin_domain = admin_domain;
+ } else {
+ r->in.admin_domain = r->in.domain_name;
+ }
r->in.admin_account = admin_account;
}
ads_status = libnet_join_post_processing_ads(mem_ctx, r);
if (!ADS_ERR_OK(ads_status)) {
- return WERR_GENERAL_FAILURE;
+ return WERR_GEN_FAILURE;
}
}
#endif /* HAVE_ADS */
ctx = talloc_zero(mem_ctx, struct libnet_JoinCtx);
if (!ctx) {
- return WERR_NOMEM;
+ return WERR_NOT_ENOUGH_MEMORY;
}
talloc_set_destructor(ctx, libnet_destroy_JoinCtx);
ctx = talloc_zero(mem_ctx, struct libnet_UnjoinCtx);
if (!ctx) {
- return WERR_NOMEM;
+ return WERR_NOT_ENOUGH_MEMORY;
}
talloc_set_destructor(ctx, libnet_destroy_UnjoinCtx);
bool valid_security = false;
bool valid_workgroup = false;
bool valid_realm = false;
+ bool ignored_realm = false;
/* check if configuration is already set correctly */
valid_realm = strequal(lp_realm(), r->out.dns_domain_name);
switch (lp_security()) {
case SEC_DOMAIN:
+ if (!valid_realm && lp_winbind_rpc_only()) {
+ valid_realm = true;
+ ignored_realm = true;
+ }
+ /* FALL THROUGH */
case SEC_ADS:
valid_security = true;
}
if (valid_workgroup && valid_realm && valid_security) {
+ if (ignored_realm && !r->in.modify_config)
+ {
+ libnet_join_set_error_string(mem_ctx, r,
+ "Warning: ignoring realm when "
+ "joining AD domain with "
+ "'security=domain' and "
+ "'winbind rpc only = yes'. "
+ "(realm set to '%s', "
+ "should be '%s').", lp_realm(),
+ r->out.dns_domain_name);
+ }
/* nothing to be done */
return WERR_OK;
}
&info);
if (!NT_STATUS_IS_OK(status)) {
libnet_join_set_error_string(mem_ctx, r,
- "failed to find DC for domain %s",
+ "failed to find DC for domain %s - %s",
r->in.domain_name,
get_friendly_nt_error_msg(status));
- return WERR_DCNOTFOUND;
+ return WERR_NERR_DCNOTFOUND;
}
dc = strip_hostname(info->dc_unc);
info->dc_address[1] != '\\') {
DBG_ERR("ill-formed DC address '%s'\n",
info->dc_address);
- return WERR_DCNOTFOUND;
+ return WERR_NERR_DCNOTFOUND;
}
numeric_dcip = info->dc_address + 2;
DBG_ERR(
"cannot parse IP address '%s' of DC '%s'\n",
numeric_dcip, r->in.dc_name);
- return WERR_DCNOTFOUND;
+ return WERR_NERR_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;
+ return WERR_NERR_DCNOTFOUND;
}
}
#ifdef HAVE_ADS
- create_local_private_krb5_conf_for_domain(
- r->out.dns_domain_name, r->out.netbios_domain_name,
- NULL, smbXcli_conn_remote_sockaddr(cli->conn));
+ if (r->out.domain_is_ad) {
+ create_local_private_krb5_conf_for_domain(
+ r->out.dns_domain_name, r->out.netbios_domain_name,
+ sitename, smbXcli_conn_remote_sockaddr(cli->conn));
+ }
if (r->out.domain_is_ad &&
!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
ads_status = libnet_join_connect_ads_user(mem_ctx, r);
if (!ADS_ERR_OK(ads_status)) {
- return WERR_DEFAULT_JOIN_REQUIRED;
+ return WERR_NERR_DEFAULTJOINREQUIRED;
}
ads_status = libnet_join_precreate_machine_acct(mem_ctx, r);
"failed to precreate account in ou %s: %s",
r->in.account_ou,
ads_errstr(ads_status));
- return WERR_DEFAULT_JOIN_REQUIRED;
+ return WERR_NERR_DEFAULTJOINREQUIRED;
}
DEBUG(5, ("failed to precreate account in ou %s: %s",
"failed to join domain '%s' over rpc: %s",
r->in.domain_name, get_friendly_nt_error_msg(status));
if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
- return WERR_SETUP_ALREADY_JOINED;
+ return WERR_NERR_SETUPALREADYJOINED;
}
werr = ntstatus_to_werror(status);
goto done;
}
if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) {
- werr = WERR_SETUP_NOT_JOINED;
+ werr = WERR_NERR_SETUPNOTJOINED;
goto done;
}
if (!secrets_fetch_domain_sid(lp_workgroup(), &sid)) {
libnet_unjoin_set_error_string(mem_ctx, r,
"Unable to fetch domain sid: are we joined?");
- return WERR_SETUP_NOT_JOINED;
+ return WERR_NERR_SETUPNOTJOINED;
}
r->in.domain_sid = dom_sid_dup(mem_ctx, &sid);
W_ERROR_HAVE_NO_MEMORY(r->in.domain_sid);
&info);
if (!NT_STATUS_IS_OK(status)) {
libnet_unjoin_set_error_string(mem_ctx, r,
- "failed to find DC for domain %s",
+ "failed to find DC for domain %s - %s",
r->in.domain_name,
get_friendly_nt_error_msg(status));
- return WERR_DCNOTFOUND;
+ return WERR_NERR_DCNOTFOUND;
}
dc = strip_hostname(info->dc_unc);
"failed to disable machine account via rpc: %s",
get_friendly_nt_error_msg(status));
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
- return WERR_SETUP_NOT_JOINED;
+ return WERR_NERR_SETUPNOTJOINED;
}
return ntstatus_to_werror(status);
}
if (!r->in.domain_name) {
libnet_unjoin_set_error_string(mem_ctx, r,
"No domain name defined");
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name,
&r->in.dc_name)) {
libnet_unjoin_set_error_string(mem_ctx, r,
"Failed to parse domain name");
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (IS_DC) {
- return WERR_SETUP_DOMAIN_CONTROLLER;
+ return WERR_NERR_SETUPDOMAINCONTROLLER;
}
if (!r->in.admin_domain) {
char *admin_domain = NULL;
char *admin_account = NULL;
- split_domain_user(mem_ctx,
- r->in.admin_account,
- &admin_domain,
- &admin_account);
- r->in.admin_domain = admin_domain;
+ bool ok;
+
+ ok = split_domain_user(mem_ctx,
+ r->in.admin_account,
+ &admin_domain,
+ &admin_account);
+ if (!ok) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ if (admin_domain != NULL) {
+ r->in.admin_domain = admin_domain;
+ } else {
+ r->in.admin_domain = r->in.domain_name;
+ }
r->in.admin_account = admin_account;
}