Update smbrun to allow for settings environment variables.
[samba.git] / source3 / libnet / libnet_join.c
index ef6c99506f6fd3127d61a7d396391e157c2b3fa9..3ac7f3980e5b5418a42bacad5abee22d8d8dae0d 100644 (file)
 /****************************************************************
 ****************************************************************/
 
+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, ...)
@@ -94,6 +99,11 @@ static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx,
 /****************************************************************
 ****************************************************************/
 
+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, ...)
@@ -463,6 +473,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 +535,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) {
@@ -1343,11 +1413,11 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        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,
@@ -1389,7 +1459,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
        status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
                                          &user_pol,
-                                         26,
+                                         UserInternal5InformationNew,
                                          &user_info,
                                          &result);
 
@@ -1406,7 +1476,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
                status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
                                                  &user_pol,
-                                                 24,
+                                                 UserInternal5Information,
                                                  &user_info,
                                                  &result);
        }
@@ -1618,7 +1688,7 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx,
                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;
@@ -1838,7 +1908,7 @@ static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
 
        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;
        }
 
@@ -1846,14 +1916,14 @@ static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
 
                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;
                }
 
@@ -1863,28 +1933,28 @@ static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
 
        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;
                }
        }
@@ -1905,7 +1975,7 @@ static WERROR do_unjoin_modify_vals_config(struct libnet_UnjoinCtx *r)
 
        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;
        }
 
@@ -1913,13 +1983,13 @@ static WERROR do_unjoin_modify_vals_config(struct libnet_UnjoinCtx *r)
 
                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;
                }
 
@@ -2038,7 +2108,7 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
        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) {
@@ -2047,7 +2117,7 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
                          "\"%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,
@@ -2055,17 +2125,27 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
                                    &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;
        }
 
@@ -2142,7 +2222,7 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
 
                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 */
@@ -2186,7 +2266,7 @@ WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
 
        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);
@@ -2221,7 +2301,7 @@ WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
 
        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);
@@ -2243,6 +2323,7 @@ static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx,
        bool valid_security = false;
        bool valid_workgroup = false;
        bool valid_realm = false;
+       bool ignored_realm = false;
 
        /* check if configuration is already set correctly */
 
@@ -2262,11 +2343,27 @@ static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx,
                        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;
                        }
@@ -2371,10 +2468,10 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                                     &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);
@@ -2385,7 +2482,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                    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;
@@ -2403,14 +2500,14 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                                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;
                        }
                }
 
@@ -2438,9 +2535,11 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 
 #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)) {
@@ -2456,7 +2555,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 
                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);
@@ -2476,7 +2575,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                                "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",
@@ -2496,14 +2595,14 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                        "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;
        }
 
@@ -2607,7 +2706,7 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                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);
@@ -2633,10 +2732,10 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                                     &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);
@@ -2682,7 +2781,7 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                                "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);
                }
@@ -2707,7 +2806,7 @@ static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx,
        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,
@@ -2715,21 +2814,31 @@ static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx,
                                    &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;
        }