s3:libnet: accept empty realm for AD domains when only security=domain is set.
[samba.git] / source3 / libnet / libnet_join.c
index ac7e3efdbde62e875ef90d0b96d6e623d02f4ab6..abb9cff1a5bf76c1e058a3587bb2262d320a33ed 100644 (file)
@@ -253,13 +253,13 @@ static ADS_STATUS libnet_join_connect_ads_user(TALLOC_CTX *mem_ctx,
 
 /****************************************************************
 ****************************************************************/
-#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
+
 /****************************************************************
 ****************************************************************/
 
@@ -463,6 +463,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
        size_t num_spns = 0;
        char *spn = NULL;
        bool ok;
+       const char **netbios_aliases = NULL;
 
        /* Find our DN */
 
@@ -524,6 +525,65 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
                }
        }
 
+       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) {
@@ -684,7 +744,7 @@ static ADS_STATUS libnet_join_set_os_attributes(TALLOC_CTX *mem_ctx,
 
 /****************************************************************
 ****************************************************************/
-#if 0
+
 static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
                                         struct libnet_JoinCtx *r)
 {
@@ -731,7 +791,7 @@ static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
 
        return ADS_SUCCESS;
 }
-#endif
+
 /****************************************************************
 ****************************************************************/
 
@@ -809,6 +869,7 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx,
                                                  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);
@@ -843,6 +904,56 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx,
                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);
        }
@@ -911,7 +1022,7 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
                                   domain,
                                   pass,
                                   flags,
-                                  SMB_SIGNING_DEFAULT);
+                                  SMB_SIGNING_IPC_DEFAULT);
 }
 
 /****************************************************************
@@ -1466,7 +1577,7 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
                                     machine_domain,
                                     machine_password,
                                     flags,
-                                    SMB_SIGNING_DEFAULT);
+                                    SMB_SIGNING_IPC_DEFAULT);
 
        if (!NT_STATUS_IS_OK(status)) {
                status = cli_full_connection(&cli, NULL,
@@ -1477,7 +1588,7 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
                                             NULL,
                                             "",
                                             0,
-                                            SMB_SIGNING_DEFAULT);
+                                            SMB_SIGNING_IPC_DEFAULT);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -2256,9 +2367,26 @@ static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx,
                        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;
        }
 
@@ -2389,7 +2517,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 
        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.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {