s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_schannel_with_key().
[samba.git] / source3 / libnet / libnet_join.c
index 16c068c66eee5ff9165b9659dd1eee4646cc6945..c77149a33b0605fac0b01c4d20e3bb81c31da35f 100644 (file)
 #include "secrets.h"
 #include "rpc_client/init_lsa.h"
 #include "rpc_client/cli_pipe.h"
-#include "krb5_env.h"
 #include "../libcli/security/security.h"
 #include "passdb.h"
 #include "libsmb/libsmb.h"
+#include "../libcli/smb/smbXcli_base.h"
+#include "lib/param/loadparm.h"
 
 /****************************************************************
 ****************************************************************/
@@ -135,7 +136,10 @@ static ADS_STATUS libnet_connect_ads(const char *dns_domain_name,
                        *cp++ = '\0';
                        SAFE_FREE(my_ads->auth.realm);
                        my_ads->auth.realm = smb_xstrdup(cp);
-                       strupper_m(my_ads->auth.realm);
+                       if (!strupper_m(my_ads->auth.realm)) {
+                               ads_destroy(&my_ads);
+                               return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+                       }
                }
        }
 
@@ -380,7 +384,9 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
        if (!spn) {
                return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
        }
-       strupper_m(spn);
+       if (!strupper_m(spn)) {
+               return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+       }
        spn_array[0] = spn;
 
        if (!name_to_fqdn(my_fqdn, r->in.machine_name)
@@ -389,7 +395,9 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
                             r->out.dns_domain_name);
        }
 
-       strlower_m(my_fqdn);
+       if (!strlower_m(my_fqdn)) {
+               return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+       }
 
        if (!strequal(my_fqdn, r->in.machine_name)) {
                spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn);
@@ -700,7 +708,7 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
                                   NULL,
                                   pass,
                                   flags,
-                                  Undefined);
+                                  SMB_SIGNING_DEFAULT);
 }
 
 /****************************************************************
@@ -803,7 +811,9 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx,
        }
 
        if (!r->in.machine_password) {
-               r->in.machine_password = generate_random_str(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+               r->in.machine_password = generate_random_password(mem_ctx,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
                NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
        }
 
@@ -811,7 +821,9 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx,
 
        /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */
        fstrcpy(trust_passwd, r->in.admin_password);
-       strlower_m(trust_passwd);
+       if (!strlower_m(trust_passwd)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        /*
         * Machine names can be 15 characters, but the max length on
@@ -851,7 +863,9 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        struct samr_Ids name_types;
        union samr_UserInfo user_info;
        struct dcerpc_binding_handle *b = NULL;
+       unsigned int old_timeout = 0;
 
+       DATA_BLOB session_key = data_blob_null;
        struct samr_CryptPassword crypt_pwd;
        struct samr_CryptPasswordEx crypt_pwd_ex;
 
@@ -871,7 +885,9 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        }
 
        if (!r->in.machine_password) {
-               r->in.machine_password = generate_random_str(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+               r->in.machine_password = generate_random_password(mem_ctx,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
                NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
        }
 
@@ -887,6 +903,13 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
        b = pipe_hnd->binding_handle;
 
+       status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
+                       nt_errstr(status)));
+               goto done;
+       }
+
        status = dcerpc_samr_Connect2(b, mem_ctx,
                                      pipe_hnd->desthost,
                                      SAMR_ACCESS_ENUM_DOMAINS
@@ -920,7 +943,10 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        /* Create domain user */
 
        acct_name = talloc_asprintf(mem_ctx, "%s$", r->in.machine_name);
-       strlower_m(acct_name);
+       if (!strlower_m(acct_name)) {
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
 
        init_lsa_String(&lsa_acct_name, acct_name);
 
@@ -1062,8 +1088,14 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
        /* Set password on machine account - first try level 26 */
 
+       /*
+        * increase the timeout as password filter modules on the DC
+        * might delay the operation for a significant amount of time
+        */
+       old_timeout = rpccli_set_timeout(pipe_hnd, 600000);
+
        init_samr_CryptPasswordEx(r->in.machine_password,
-                                 &cli->user_session_key,
+                                 &session_key,
                                  &crypt_pwd_ex);
 
        user_info.info26.password = crypt_pwd_ex;
@@ -1080,7 +1112,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                /* retry with level 24 */
 
                init_samr_CryptPassword(r->in.machine_password,
-                                       &cli->user_session_key,
+                                       &session_key,
                                        &crypt_pwd);
 
                user_info.info24.password = crypt_pwd;
@@ -1093,6 +1125,8 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                                                  &result);
        }
 
+       old_timeout = rpccli_set_timeout(pipe_hnd, old_timeout);
+
        if (!NT_STATUS_IS_OK(status)) {
 
                dcerpc_samr_DeleteUser(b, mem_ctx,
@@ -1124,6 +1158,8 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                return status;
        }
 
+       data_blob_clear_free(&session_key);
+
        if (is_valid_policy_hnd(&sam_pol)) {
                dcerpc_samr_Close(b, mem_ctx, &sam_pol, &result);
        }
@@ -1143,7 +1179,8 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
 NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                        const char *machine_name,
-                       const char *dc_name)
+                       const char *dc_name,
+                       const bool use_kerberos)
 {
        uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
        struct cli_state *cli = NULL;
@@ -1152,6 +1189,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
        NTSTATUS status;
        char *machine_password = NULL;
        char *machine_account = NULL;
+       int flags = 0;
 
        if (!dc_name) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -1172,6 +1210,10 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                return NT_STATUS_NO_MEMORY;
        }
 
+       if (use_kerberos) {
+               flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
+       }
+
        status = cli_full_connection(&cli, NULL,
                                     dc_name,
                                     NULL, 0,
@@ -1179,8 +1221,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                                     machine_account,
                                     NULL,
                                     machine_password,
-                                    0,
-                                    Undefined);
+                                    flags,
+                                    SMB_SIGNING_DEFAULT);
        free(machine_account);
        free(machine_password);
 
@@ -1193,7 +1235,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                                             NULL,
                                             "",
                                             0,
-                                            Undefined);
+                                            SMB_SIGNING_DEFAULT);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -1210,7 +1252,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
 
                DEBUG(0,("libnet_join_ok: failed to get schannel session "
                        "key from server %s for domain %s. Error was %s\n",
-               cli->desthost, netbios_domain_name, nt_errstr(status)));
+                       smbXcli_conn_remote_name(cli->conn),
+                       netbios_domain_name, nt_errstr(status)));
                cli_shutdown(cli);
                return status;
        }
@@ -1221,7 +1264,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
        }
 
        status = cli_rpc_pipe_open_schannel_with_key(
-               cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
+               cli, &ndr_table_netlogon, NCACN_NP,
                DCERPC_AUTH_LEVEL_PRIVACY,
                netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd);
 
@@ -1231,7 +1274,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                DEBUG(0,("libnet_join_ok: failed to open schannel session "
                        "on netlogon pipe to server %s for domain %s. "
                        "Error was %s\n",
-                       cli->desthost, netbios_domain_name, nt_errstr(status)));
+                       smbXcli_conn_remote_name(cli->conn),
+                       netbios_domain_name, nt_errstr(status)));
                return status;
        }
 
@@ -1248,7 +1292,8 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx,
 
        status = libnet_join_ok(r->out.netbios_domain_name,
                                r->in.machine_name,
-                               r->in.dc_name);
+                               r->in.dc_name,
+                               r->in.use_kerberos);
        if (!NT_STATUS_IS_OK(status)) {
                libnet_join_set_error_string(mem_ctx, r,
                        "failed to verify domain membership after joining: %s",
@@ -1349,7 +1394,10 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
        /* Create domain user */
 
        acct_name = talloc_asprintf(mem_ctx, "%s$", r->in.machine_name);
-       strlower_m(acct_name);
+       if (!strlower_m(acct_name)) {
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
 
        init_lsa_String(&lsa_acct_name, acct_name);
 
@@ -1574,7 +1622,7 @@ static WERROR do_JoinConfig(struct libnet_JoinCtx *r)
                return werr;
        }
 
-       lp_load(get_dyn_CONFIGFILE(),true,false,false,true);
+       lp_load_global(get_dyn_CONFIGFILE());
 
        r->out.modified_config = true;
        r->out.result = werr;
@@ -1602,7 +1650,7 @@ static WERROR libnet_unjoin_config(struct libnet_UnjoinCtx *r)
                return werr;
        }
 
-       lp_load(get_dyn_CONFIGFILE(),true,false,false,true);
+       lp_load_global(get_dyn_CONFIGFILE());
 
        r->out.modified_config = true;
        r->out.result = werr;
@@ -1697,7 +1745,7 @@ static void libnet_join_add_dom_rids_to_builtins(struct dom_sid *domain_sid)
        if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
                DEBUG(10,("Unable to auto-add domain administrators to "
                          "BUILTIN\\Administrators during join because "
-                         "winbindd must be running."));
+                         "winbindd must be running.\n"));
        } else if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("Failed to auto-add domain administrators to "
                          "BUILTIN\\Administrators during join: %s\n",
@@ -1708,7 +1756,7 @@ static void libnet_join_add_dom_rids_to_builtins(struct dom_sid *domain_sid)
        status = create_builtin_users(domain_sid);
        if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
                DEBUG(10,("Unable to auto-add domain users to BUILTIN\\users "
-                         "during join because winbindd must be running."));
+                         "during join because winbindd must be running.\n"));
        } else if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("Failed to auto-add domain administrators to "
                          "BUILTIN\\Administrators during join: %s\n",
@@ -1764,17 +1812,10 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
 
 static int libnet_destroy_JoinCtx(struct libnet_JoinCtx *r)
 {
-       const char *krb5_cc_env = NULL;
-
        if (r->in.ads) {
                ads_destroy(&r->in.ads);
        }
 
-       krb5_cc_env = getenv(KRB5_ENV_CCNAME);
-       if (krb5_cc_env && strcasecmp_m(krb5_cc_env, "MEMORY:libnetjoin")) {
-               unsetenv(KRB5_ENV_CCNAME);
-       }
-
        return 0;
 }
 
@@ -1783,17 +1824,10 @@ static int libnet_destroy_JoinCtx(struct libnet_JoinCtx *r)
 
 static int libnet_destroy_UnjoinCtx(struct libnet_UnjoinCtx *r)
 {
-       const char *krb5_cc_env = NULL;
-
        if (r->in.ads) {
                ads_destroy(&r->in.ads);
        }
 
-       krb5_cc_env = getenv(KRB5_ENV_CCNAME);
-       if (krb5_cc_env && strcasecmp_m(krb5_cc_env, "MEMORY:libnetjoin")) {
-               unsetenv(KRB5_ENV_CCNAME);
-       }
-
        return 0;
 }
 
@@ -1804,7 +1838,6 @@ WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
                           struct libnet_JoinCtx **r)
 {
        struct libnet_JoinCtx *ctx;
-       const char *krb5_cc_env = NULL;
 
        ctx = talloc_zero(mem_ctx, struct libnet_JoinCtx);
        if (!ctx) {
@@ -1816,13 +1849,6 @@ WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
        ctx->in.machine_name = talloc_strdup(mem_ctx, lp_netbios_name());
        W_ERROR_HAVE_NO_MEMORY(ctx->in.machine_name);
 
-       krb5_cc_env = getenv(KRB5_ENV_CCNAME);
-       if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
-               krb5_cc_env = talloc_strdup(mem_ctx, "MEMORY:libnetjoin");
-               W_ERROR_HAVE_NO_MEMORY(krb5_cc_env);
-               setenv(KRB5_ENV_CCNAME, krb5_cc_env, 1);
-       }
-
        ctx->in.secure_channel_type = SEC_CHAN_WKSTA;
 
        *r = ctx;
@@ -1837,7 +1863,6 @@ WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
                             struct libnet_UnjoinCtx **r)
 {
        struct libnet_UnjoinCtx *ctx;
-       const char *krb5_cc_env = NULL;
 
        ctx = talloc_zero(mem_ctx, struct libnet_UnjoinCtx);
        if (!ctx) {
@@ -1849,13 +1874,6 @@ WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
        ctx->in.machine_name = talloc_strdup(mem_ctx, lp_netbios_name());
        W_ERROR_HAVE_NO_MEMORY(ctx->in.machine_name);
 
-       krb5_cc_env = getenv(KRB5_ENV_CCNAME);
-       if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
-               krb5_cc_env = talloc_strdup(mem_ctx, "MEMORY:libnetjoin");
-               W_ERROR_HAVE_NO_MEMORY(krb5_cc_env);
-               setenv(KRB5_ENV_CCNAME, krb5_cc_env, 1);
-       }
-
        *r = ctx;
 
        return WERR_OK;
@@ -1921,7 +1939,6 @@ static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx,
                if (!valid_security) {
                        const char *sec = NULL;
                        switch (lp_security()) {
-                       case SEC_SHARE: sec = "share"; break;
                        case SEC_USER:  sec = "user"; break;
                        case SEC_DOMAIN: sec = "domain"; break;
                        case SEC_ADS: sec = "ads"; break;
@@ -2007,7 +2024,8 @@ 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, &cli->dest_ss, cli->desthost);
+               NULL, smbXcli_conn_remote_sockaddr(cli->conn),
+               smbXcli_conn_remote_name(cli->conn));
 
        if (r->out.domain_is_ad && r->in.account_ou &&
            !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
@@ -2082,6 +2100,7 @@ static WERROR libnet_join_rollback(TALLOC_CTX *mem_ctx,
        u->in.admin_account     = r->in.admin_account;
        u->in.admin_password    = r->in.admin_password;
        u->in.modify_config     = r->in.modify_config;
+       u->in.use_kerberos      = r->in.use_kerberos;
        u->in.unjoin_flags      = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;