param: rename lp function and variable from "adduser_script" to "add_user_script"
[samba.git] / source3 / libnet / libnet_join.c
index 28b2f6c6540866ceab7c2806a0dd711fc2aabd82..a87eb382d6bf2ff6dea2307f091b7c84592a0e31 100644 (file)
 #include "librpc/gen_ndr/ndr_libnet_join.h"
 #include "libnet/libnet_join.h"
 #include "libcli/auth/libcli_auth.h"
-#include "../librpc/gen_ndr/cli_samr.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
 #include "rpc_client/init_samr.h"
-#include "../librpc/gen_ndr/cli_lsa.h"
+#include "../librpc/gen_ndr/ndr_lsa_c.h"
 #include "rpc_client/cli_lsarpc.h"
-#include "../librpc/gen_ndr/cli_netlogon.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
 #include "rpc_client/cli_netlogon.h"
 #include "lib/smbconf/smbconf.h"
 #include "lib/smbconf/smbconf_reg.h"
 #include "../libds/common/flags.h"
 #include "secrets.h"
 #include "rpc_client/init_lsa.h"
-#include "krb5_env.h"
-#include "../libcli/security/dom_sid.h"
+#include "rpc_client/cli_pipe.h"
+#include "../libcli/security/security.h"
+#include "passdb.h"
+#include "libsmb/libsmb.h"
+#include "../libcli/smb/smbXcli_base.h"
+#include "lib/param/loadparm.h"
+#include "libcli/auth/netlogon_creds_cli.h"
+#include "auth/credentials/credentials.h"
 
 /****************************************************************
 ****************************************************************/
@@ -102,7 +108,7 @@ static void libnet_unjoin_set_error_string(TALLOC_CTX *mem_ctx,
        va_end(args);
 }
 
-#ifdef WITH_ADS
+#ifdef HAVE_ADS
 
 /****************************************************************
 ****************************************************************/
@@ -132,7 +138,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);
+                       }
                }
        }
 
@@ -377,7 +386,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)
@@ -386,7 +397,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);
@@ -438,10 +451,25 @@ static ADS_STATUS libnet_join_set_machine_upn(TALLOC_CTX *mem_ctx,
        }
 
        if (!r->in.upn) {
+               const char *realm = r->out.dns_domain_name;
+
+               /* in case we are about to generate a keytab during the join
+                * make sure the default upn we create is usable with kinit -k.
+                * gd */
+
+               if (USE_KERBEROS_KEYTAB) {
+                       realm = talloc_strdup_upper(mem_ctx,
+                                                   r->out.dns_domain_name);
+               }
+
+               if (!realm) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+
                r->in.upn = talloc_asprintf(mem_ctx,
                                            "host/%s@%s",
                                            r->in.machine_name,
-                                           r->out.dns_domain_name);
+                                           realm);
                if (!r->in.upn) {
                        return ADS_ERROR(LDAP_NO_MEMORY);
                }
@@ -642,7 +670,7 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx,
 
        return ADS_SUCCESS;
 }
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */
 
 /****************************************************************
  Store the machine password and domain SID
@@ -675,6 +703,7 @@ static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx,
 
 static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
                                           const char *user,
+                                          const char *domain,
                                           const char *pass,
                                           bool use_kerberos,
                                           struct cli_state **cli)
@@ -694,10 +723,10 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
                                   NULL, 0,
                                   "IPC$", "IPC",
                                   user,
-                                  NULL,
+                                  domain,
                                   pass,
                                   flags,
-                                  Undefined, NULL);
+                                  SMB_SIGNING_DEFAULT);
 }
 
 /****************************************************************
@@ -710,11 +739,13 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx,
 {
        struct rpc_pipe_client *pipe_hnd = NULL;
        struct policy_handle lsa_pol;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS status, result;
        union lsa_PolicyInformation *info = NULL;
+       struct dcerpc_binding_handle *b;
 
        status = libnet_join_connect_dc_ipc(r->in.dc_name,
                                            r->in.admin_account,
+                                           r->in.admin_domain,
                                            r->in.admin_password,
                                            r->in.use_kerberos,
                                            cli);
@@ -722,7 +753,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id,
+       status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc,
                                          &pipe_hnd);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Error connecting to LSA pipe. Error was %s\n",
@@ -730,17 +761,20 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
+       b = pipe_hnd->binding_handle;
+
        status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
                                        SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
-       status = rpccli_lsa_QueryInfoPolicy2(pipe_hnd, mem_ctx,
+       status = dcerpc_lsa_QueryInfoPolicy2(b, mem_ctx,
                                             &lsa_pol,
                                             LSA_POLICY_INFO_DNS,
-                                            &info);
-       if (NT_STATUS_IS_OK(status)) {
+                                            &info,
+                                            &result);
+       if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
                r->out.domain_is_ad = true;
                r->out.netbios_domain_name = info->dns.name.string;
                r->out.dns_domain_name = info->dns.dns_domain.string;
@@ -750,20 +784,25 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
+               status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
                                                    &lsa_pol,
                                                    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
-                                                   &info);
+                                                   &info,
+                                                   &result);
                if (!NT_STATUS_IS_OK(status)) {
                        goto done;
                }
+               if (!NT_STATUS_IS_OK(result)) {
+                       status = result;
+                       goto done;
+               }
 
                r->out.netbios_domain_name = info->account_domain.name.string;
                r->out.domain_sid = dom_sid_dup(mem_ctx, info->account_domain.sid);
                NT_STATUS_HAVE_NO_MEMORY(r->out.domain_sid);
        }
 
-       rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
+       dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
        TALLOC_FREE(pipe_hnd);
 
  done:
@@ -778,46 +817,73 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx,
                                                    struct libnet_JoinCtx *r,
                                                    struct cli_state *cli)
 {
-       struct rpc_pipe_client *pipe_hnd = NULL;
-       unsigned char orig_trust_passwd_hash[16];
-       unsigned char new_trust_passwd_hash[16];
-       fstring trust_passwd;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct rpc_pipe_client *netlogon_pipe = NULL;
+       struct netlogon_creds_cli_context *netlogon_creds = NULL;
+       struct samr_Password current_nt_hash;
+       const char *account_name = NULL;
        NTSTATUS status;
 
-       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
-                                         &pipe_hnd);
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
+                                         &netlogon_pipe);
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
                return status;
        }
 
        if (!r->in.machine_password) {
-               r->in.machine_password = generate_random_str(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
-               NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
+               r->in.machine_password = generate_random_password(mem_ctx,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
+                               DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+               if (r->in.machine_password == NULL) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
-       E_md4hash(r->in.machine_password, new_trust_passwd_hash);
-
        /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */
-       fstrcpy(trust_passwd, r->in.admin_password);
-       strlower_m(trust_passwd);
+       E_md4hash(r->in.admin_password, current_nt_hash.hash);
 
-       /*
-        * Machine names can be 15 characters, but the max length on
-        * a password is 14.  --jerry
-        */
+       account_name = talloc_asprintf(frame, "%s$",
+                                      r->in.machine_name);
+       if (account_name == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       trust_passwd[14] = '\0';
+       status = rpccli_create_netlogon_creds(netlogon_pipe->desthost,
+                                             r->in.domain_name,
+                                             account_name,
+                                             r->in.secure_channel_type,
+                                             r->in.msg_ctx,
+                                             frame,
+                                             &netlogon_creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
+       }
 
-       E_md4hash(trust_passwd, orig_trust_passwd_hash);
+       status = rpccli_setup_netlogon_creds(cli,
+                                            netlogon_creds,
+                                            true, /* force_reauth */
+                                            current_nt_hash,
+                                            NULL); /* previous_nt_hash */
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
+       }
 
-       status = rpccli_netlogon_set_trust_password(pipe_hnd, mem_ctx,
-                                                   r->in.machine_name,
-                                                   orig_trust_passwd_hash,
-                                                   r->in.machine_password,
-                                                   new_trust_passwd_hash,
-                                                   r->in.secure_channel_type);
+       status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds,
+                                                     netlogon_pipe->binding_handle,
+                                                     r->in.machine_password,
+                                                     NULL); /* new_version */
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
+       }
 
-       return status;
+       TALLOC_FREE(frame);
+       return NT_STATUS_OK;
 }
 
 /****************************************************************
@@ -830,7 +896,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 {
        struct rpc_pipe_client *pipe_hnd = NULL;
        struct policy_handle sam_pol, domain_pol, user_pol;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL, result;
        char *acct_name;
        struct lsa_String lsa_acct_name;
        uint32_t user_rid;
@@ -838,7 +904,10 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        struct samr_Ids user_rids;
        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;
 
@@ -858,13 +927,15 @@ 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);
        }
 
        /* Open the domain */
 
-       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
                                          &pipe_hnd);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
@@ -872,30 +943,52 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       status = rpccli_samr_Connect2(pipe_hnd, 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
                                      | SAMR_ACCESS_LOOKUP_DOMAIN,
-                                     &sam_pol);
+                                     &sam_pol,
+                                     &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
-       status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_OpenDomain(b, mem_ctx,
                                        &sam_pol,
                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
                                        | SAMR_DOMAIN_ACCESS_CREATE_USER
                                        | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                        r->out.domain_sid,
-                                       &domain_pol);
+                                       &domain_pol,
+                                       &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
        /* 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);
 
@@ -911,14 +1004,20 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                DEBUG(10,("Creating account with desired access mask: %d\n",
                        access_desired));
 
-               status = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
+               status = dcerpc_samr_CreateUser2(b, mem_ctx,
                                                 &domain_pol,
                                                 &lsa_acct_name,
                                                 acct_flags,
                                                 access_desired,
                                                 &user_pol,
                                                 &access_granted,
-                                                &user_rid);
+                                                &user_rid,
+                                                &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
+               }
+
+               status = result;
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
 
@@ -948,19 +1047,32 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
                /* We *must* do this.... don't ask... */
 
                if (NT_STATUS_IS_OK(status)) {
-                       rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+                       dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
                }
        }
 
-       status = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_LookupNames(b, mem_ctx,
                                         &domain_pol,
                                         1,
                                         &lsa_acct_name,
                                         &user_rids,
-                                        &name_types);
+                                        &name_types,
+                                        &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
+       if (user_rids.count != 1) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto done;
+       }
+       if (name_types.count != 1) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto done;
+       }
 
        if (name_types.ids[0] != SID_NAME_USER) {
                DEBUG(0,("%s is not a user account (type=%d)\n",
@@ -973,14 +1085,19 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
 
        /* Open handle on user */
 
-       status = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_OpenUser(b, mem_ctx,
                                      &domain_pol,
                                      SEC_FLAG_MAXIMUM_ALLOWED,
                                      user_rid,
-                                     &user_pol);
+                                     &user_pol,
+                                     &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
        /* Fill in the additional account flags now */
 
@@ -990,15 +1107,28 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(user_info.info16);
        user_info.info16.acct_flags = acct_flags;
 
-       status = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_SetUserInfo(b, mem_ctx,
                                         &user_pol,
                                         16,
-                                        &user_info);
-
+                                        &user_info,
+                                        &result);
        if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_samr_DeleteUser(b, mem_ctx,
+                                      &user_pol,
+                                      &result);
 
-               rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
-                                      &user_pol);
+               libnet_join_set_error_string(mem_ctx, r,
+                       "Failed to set account flags for machine account (%s)\n",
+                       nt_errstr(status));
+               goto done;
+       }
+
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+
+               dcerpc_samr_DeleteUser(b, mem_ctx,
+                                      &user_pol,
+                                      &result);
 
                libnet_join_set_error_string(mem_ctx, r,
                        "Failed to set account flags for machine account (%s)\n",
@@ -1008,39 +1138,62 @@ 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;
        user_info.info26.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
 
-       status = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
                                          &user_pol,
                                          26,
-                                         &user_info);
+                                         &user_info,
+                                         &result);
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
+       if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
 
                /* 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;
                user_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
 
-               status = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
+               status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
                                                  &user_pol,
                                                  24,
-                                                 &user_info);
+                                                 &user_info,
+                                                 &result);
        }
 
+       old_timeout = rpccli_set_timeout(pipe_hnd, old_timeout);
+
        if (!NT_STATUS_IS_OK(status)) {
 
-               rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
-                                      &user_pol);
+               dcerpc_samr_DeleteUser(b, mem_ctx,
+                                      &user_pol,
+                                      &result);
+
+               libnet_join_set_error_string(mem_ctx, r,
+                       "Failed to set password for machine account (%s)\n",
+                       nt_errstr(status));
+               goto done;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+
+               dcerpc_samr_DeleteUser(b, mem_ctx,
+                                      &user_pol,
+                                      &result);
 
                libnet_join_set_error_string(mem_ctx, r,
                        "Failed to set password for machine account (%s)\n",
@@ -1055,14 +1208,16 @@ 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)) {
-               rpccli_samr_Close(pipe_hnd, mem_ctx, &sam_pol);
+               dcerpc_samr_Close(b, mem_ctx, &sam_pol, &result);
        }
        if (is_valid_policy_hnd(&domain_pol)) {
-               rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
+               dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
        }
        if (is_valid_policy_hnd(&user_pol)) {
-               rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
        }
        TALLOC_FREE(pipe_hnd);
 
@@ -1072,35 +1227,56 @@ 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)
+NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
+                       const char *netbios_domain_name,
+                       const char *dc_name,
+                       const bool use_kerberos)
 {
-       uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+       TALLOC_CTX *frame = talloc_stackframe();
        struct cli_state *cli = NULL;
-       struct rpc_pipe_client *pipe_hnd = NULL;
        struct rpc_pipe_client *netlogon_pipe = 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;
-       char *machine_account = NULL;
+       const char *machine_name = NULL;
+       const char *machine_account = 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_INVALID_PARAMETER;
        }
 
        if (!secrets_init()) {
+               TALLOC_FREE(frame);
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
-       machine_password = secrets_fetch_machine_password(netbios_domain_name,
-                                                         NULL, NULL);
-       if (!machine_password) {
-               return NT_STATUS_NO_TRUST_LSA_SECRET;
+       ok = get_trust_pw_clear(netbios_domain_name,
+                               &machine_password,
+                               &machine_name,
+                               &sec_chan_type);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
-       if (asprintf(&machine_account, "%s$", machine_name) == -1) {
+       machine_account = talloc_asprintf(frame, "%s$", machine_name);
+       if (machine_account == NULL) {
                SAFE_FREE(machine_password);
-               return NT_STATUS_NO_MEMORY;
+               SAFE_FREE(previous_nt_hash);
+               TALLOC_FREE(frame);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
+       if (use_kerberos) {
+               flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
        }
 
        status = cli_full_connection(&cli, NULL,
@@ -1108,12 +1284,13 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                                     NULL, 0,
                                     "IPC$", "IPC",
                                     machine_account,
-                                    NULL,
+                                    netbios_domain_name,
                                     machine_password,
-                                    0,
-                                    Undefined, NULL);
-       free(machine_account);
-       free(machine_password);
+                                    flags,
+                                    SMB_SIGNING_DEFAULT);
+
+       E_md4hash(machine_password, current_nt_hash.hash);
+       SAFE_FREE(machine_password);
 
        if (!NT_STATUS_IS_OK(status)) {
                status = cli_full_connection(&cli, NULL,
@@ -1124,48 +1301,83 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
                                             NULL,
                                             "",
                                             0,
-                                            Undefined, NULL);
+                                            SMB_SIGNING_DEFAULT);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
+               SAFE_FREE(previous_nt_hash);
+               TALLOC_FREE(frame);
                return status;
        }
 
-       status = get_schannel_session_key(cli, netbios_domain_name,
-                                         &neg_flags, &netlogon_pipe);
+       status = rpccli_create_netlogon_creds(dc_name,
+                                             netbios_domain_name,
+                                             machine_account,
+                                             sec_chan_type,
+                                             msg_ctx,
+                                             frame,
+                                             &netlogon_creds);
        if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_NETWORK_RESPONSE)) {
-                       cli_shutdown(cli);
-                       return NT_STATUS_OK;
-               }
+               SAFE_FREE(previous_nt_hash);
+               cli_shutdown(cli);
+               TALLOC_FREE(frame);
+               return status;
+       }
 
-               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)));
+       status = rpccli_setup_netlogon_creds(cli,
+                                            netlogon_creds,
+                                            true, /* force_reauth */
+                                            current_nt_hash,
+                                            previous_nt_hash);
+       SAFE_FREE(previous_nt_hash);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("connect_to_domain_password_server: "
+                        "unable to open the domain client session to "
+                        "machine %s. Flags[0x%08X] Error was : %s.\n",
+                        dc_name, (unsigned)netlogon_flags,
+                        nt_errstr(status)));
+               cli_shutdown(cli);
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       status = netlogon_creds_cli_get(netlogon_creds,
+                                       talloc_tos(),
+                                       &creds);
+       if (!NT_STATUS_IS_OK(status)) {
                cli_shutdown(cli);
+               TALLOC_FREE(frame);
                return status;
        }
+       netlogon_flags = creds->negotiate_flags;
+       TALLOC_FREE(creds);
 
-       if (!lp_client_schannel()) {
+       if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
                cli_shutdown(cli);
+               TALLOC_FREE(frame);
                return NT_STATUS_OK;
        }
 
        status = cli_rpc_pipe_open_schannel_with_key(
-               cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
-               DCERPC_AUTH_LEVEL_PRIVACY,
-               netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd);
+               cli, &ndr_table_netlogon, NCACN_NP,
+               netbios_domain_name,
+               netlogon_creds, &netlogon_pipe);
 
-       cli_shutdown(cli);
+       TALLOC_FREE(netlogon_pipe);
 
        if (!NT_STATUS_IS_OK(status)) {
                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)));
+               cli_shutdown(cli);
+               TALLOC_FREE(frame);
                return status;
        }
 
+       cli_shutdown(cli);
+       TALLOC_FREE(frame);
        return NT_STATUS_OK;
 }
 
@@ -1177,9 +1389,10 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
 
-       status = libnet_join_ok(r->out.netbios_domain_name,
-                               r->in.machine_name,
-                               r->in.dc_name);
+       status = libnet_join_ok(r->in.msg_ctx,
+                               r->out.netbios_domain_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",
@@ -1216,13 +1429,14 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
        struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_hnd = NULL;
        struct policy_handle sam_pol, domain_pol, user_pol;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL, result;
        char *acct_name;
        uint32_t user_rid;
        struct lsa_String lsa_acct_name;
        struct samr_Ids user_rids;
        struct samr_Ids name_types;
        union samr_UserInfo *info = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        ZERO_STRUCT(sam_pol);
        ZERO_STRUCT(domain_pol);
@@ -1230,6 +1444,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
 
        status = libnet_join_connect_dc_ipc(r->in.dc_name,
                                            r->in.admin_account,
+                                           r->in.admin_domain,
                                            r->in.admin_password,
                                            r->in.use_kerberos,
                                            &cli);
@@ -1239,7 +1454,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
 
        /* Open the domain */
 
-       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
                                          &pipe_hnd);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
@@ -1247,40 +1462,68 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
+       b = pipe_hnd->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, mem_ctx,
                                      pipe_hnd->desthost,
                                      SEC_FLAG_MAXIMUM_ALLOWED,
-                                     &sam_pol);
+                                     &sam_pol,
+                                     &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
-       status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_OpenDomain(b, mem_ctx,
                                        &sam_pol,
                                        SEC_FLAG_MAXIMUM_ALLOWED,
                                        r->in.domain_sid,
-                                       &domain_pol);
+                                       &domain_pol,
+                                       &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
        /* 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);
 
-       status = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_LookupNames(b, mem_ctx,
                                         &domain_pol,
                                         1,
                                         &lsa_acct_name,
                                         &user_rids,
-                                        &name_types);
+                                        &name_types,
+                                        &result);
 
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
+       if (user_rids.count != 1) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto done;
+       }
+       if (name_types.count != 1) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto done;
+       }
 
        if (name_types.ids[0] != SID_NAME_USER) {
                DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name,
@@ -1293,23 +1536,34 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
 
        /* Open handle on user */
 
-       status = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_OpenUser(b, mem_ctx,
                                      &domain_pol,
                                      SEC_FLAG_MAXIMUM_ALLOWED,
                                      user_rid,
-                                     &user_pol);
+                                     &user_pol,
+                                     &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
        /* Get user info */
 
-       status = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
                                           &user_pol,
                                           16,
-                                          &info);
+                                          &info,
+                                          &result);
        if (!NT_STATUS_IS_OK(status)) {
-               rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
+               goto done;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
                goto done;
        }
 
@@ -1317,20 +1571,30 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
 
        info->info16.acct_flags |= ACB_DISABLED;
 
-       status = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_SetUserInfo(b, mem_ctx,
                                         &user_pol,
                                         16,
-                                        info);
-
-       rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+                                        info,
+                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
+               goto done;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
+               goto done;
+       }
+       status = result;
+       dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
 
 done:
-       if (pipe_hnd) {
+       if (pipe_hnd && b) {
                if (is_valid_policy_hnd(&domain_pol)) {
-                       rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
+                       dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
                }
                if (is_valid_policy_hnd(&sam_pol)) {
-                       rpccli_samr_Close(pipe_hnd, mem_ctx, &sam_pol);
+                       dcerpc_samr_Close(b, mem_ctx, &sam_pol, &result);
                }
                TALLOC_FREE(pipe_hnd);
        }
@@ -1347,40 +1611,61 @@ done:
 
 static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
 {
-       WERROR werr;
+       WERROR werr = WERR_OK;
+       sbcErr err;
        struct smbconf_ctx *ctx;
 
-       werr = smbconf_init_reg(r, &ctx, NULL);
-       if (!W_ERROR_IS_OK(werr)) {
+       err = smbconf_init_reg(r, &ctx, NULL);
+       if (!SBC_ERROR_IS_OK(err)) {
+               werr = WERR_NO_SUCH_SERVICE;
                goto done;
        }
 
        if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) {
 
-               werr = smbconf_set_global_parameter(ctx, "security", "user");
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               err = smbconf_set_global_parameter(ctx, "security", "user");
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
 
-               werr = smbconf_set_global_parameter(ctx, "workgroup",
-                                                   r->in.domain_name);
+               err = smbconf_set_global_parameter(ctx, "workgroup",
+                                                  r->in.domain_name);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
 
                smbconf_delete_global_parameter(ctx, "realm");
                goto done;
        }
 
-       werr = smbconf_set_global_parameter(ctx, "security", "domain");
-       W_ERROR_NOT_OK_GOTO_DONE(werr);
+       err = smbconf_set_global_parameter(ctx, "security", "domain");
+       if (!SBC_ERROR_IS_OK(err)) {
+               werr = WERR_NO_SUCH_SERVICE;
+               goto done;
+       }
 
-       werr = smbconf_set_global_parameter(ctx, "workgroup",
-                                           r->out.netbios_domain_name);
-       W_ERROR_NOT_OK_GOTO_DONE(werr);
+       err = smbconf_set_global_parameter(ctx, "workgroup",
+                                          r->out.netbios_domain_name);
+       if (!SBC_ERROR_IS_OK(err)) {
+               werr = WERR_NO_SUCH_SERVICE;
+               goto done;
+       }
 
        if (r->out.domain_is_ad) {
-               werr = smbconf_set_global_parameter(ctx, "security", "ads");
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               err = smbconf_set_global_parameter(ctx, "security", "ads");
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
 
-               werr = smbconf_set_global_parameter(ctx, "realm",
-                                                   r->out.dns_domain_name);
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               err = smbconf_set_global_parameter(ctx, "realm",
+                                                  r->out.dns_domain_name);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
        }
 
  done:
@@ -1394,20 +1679,28 @@ static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
 static WERROR do_unjoin_modify_vals_config(struct libnet_UnjoinCtx *r)
 {
        WERROR werr = WERR_OK;
+       sbcErr err;
        struct smbconf_ctx *ctx;
 
-       werr = smbconf_init_reg(r, &ctx, NULL);
-       if (!W_ERROR_IS_OK(werr)) {
+       err = smbconf_init_reg(r, &ctx, NULL);
+       if (!SBC_ERROR_IS_OK(err)) {
+               werr = WERR_NO_SUCH_SERVICE;
                goto done;
        }
 
        if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
 
-               werr = smbconf_set_global_parameter(ctx, "security", "user");
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               err = smbconf_set_global_parameter(ctx, "security", "user");
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
 
-               werr = smbconf_delete_global_parameter(ctx, "workgroup");
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               err = smbconf_delete_global_parameter(ctx, "workgroup");
+               if (!SBC_ERROR_IS_OK(err)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+                       goto done;
+               }
 
                smbconf_delete_global_parameter(ctx, "realm");
        }
@@ -1437,7 +1730,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;
@@ -1465,7 +1758,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;
@@ -1527,6 +1820,15 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
                return WERR_INVALID_PARAM;
        }
 
+       if (strlen(r->in.machine_name) > 15) {
+               libnet_join_set_error_string(mem_ctx, r,
+                       "Our netbios name can be at most 15 chars long, "
+                         "\"%s\" is %u chars long\n",
+                         r->in.machine_name,
+                        (unsigned int)strlen(r->in.machine_name));
+               return WERR_INVALID_PARAM;
+        }
+
        if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name,
                                    &r->in.domain_name,
                                    &r->in.dc_name)) {
@@ -1539,6 +1841,17 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
                return WERR_SETUP_DOMAIN_CONTROLLER;
        }
 
+       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;
+               r->in.admin_account = admin_account;
+       }
+
        if (!secrets_init()) {
                libnet_join_set_error_string(mem_ctx, r,
                        "Unable to open secrets database");
@@ -1560,7 +1873,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",
@@ -1571,7 +1884,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",
@@ -1605,7 +1918,7 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
                saf_join_store(r->out.dns_domain_name, r->in.dc_name);
        }
 
-#ifdef WITH_ADS
+#ifdef HAVE_ADS
        if (r->out.domain_is_ad &&
            !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
                ADS_STATUS ads_status;
@@ -1615,7 +1928,7 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
                        return WERR_GENERAL_FAILURE;
                }
        }
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */
 
        libnet_join_add_dom_rids_to_builtins(r->out.domain_sid);
 
@@ -1627,17 +1940,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(krb5_cc_env, "MEMORY:libnetjoin")) {
-               unsetenv(KRB5_ENV_CCNAME);
-       }
-
        return 0;
 }
 
@@ -1646,17 +1952,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(krb5_cc_env, "MEMORY:libnetjoin")) {
-               unsetenv(KRB5_ENV_CCNAME);
-       }
-
        return 0;
 }
 
@@ -1667,7 +1966,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) {
@@ -1676,16 +1974,9 @@ WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
 
        talloc_set_destructor(ctx, libnet_destroy_JoinCtx);
 
-       ctx->in.machine_name = talloc_strdup(mem_ctx, global_myname());
+       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;
@@ -1700,7 +1991,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) {
@@ -1709,16 +1999,9 @@ WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
 
        talloc_set_destructor(ctx, libnet_destroy_UnjoinCtx);
 
-       ctx->in.machine_name = talloc_strdup(mem_ctx, global_myname());
+       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;
@@ -1784,7 +2067,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;
@@ -1823,9 +2105,9 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        WERROR werr;
        struct cli_state *cli = NULL;
-#ifdef WITH_ADS
+#ifdef HAVE_ADS
        ADS_STATUS ads_status;
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */
 
        if (!r->in.dc_name) {
                struct netr_DsRGetDCNameInfo *info;
@@ -1866,7 +2148,13 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-#ifdef WITH_ADS
+#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),
+               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)) {
 
@@ -1886,7 +2174,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 
                r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
        }
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */
 
        if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) &&
            (r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED)) {
@@ -1940,6 +2228,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;
 
@@ -1961,6 +2250,8 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx,
                LIBNET_JOIN_IN_DUMP_CTX(mem_ctx, r);
        }
 
+       ZERO_STRUCT(r->out);
+
        werr = libnet_join_pre_processing(mem_ctx, r);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
@@ -2044,11 +2335,11 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
        }
 
-#ifdef WITH_ADS
+#ifdef HAVE_ADS
        /* for net ads leave, try to delete the account.  If it works, 
           no sense in disabling.  If it fails, we can still try to 
           disable it. jmcd */
-          
+
        if (r->in.delete_machine_account) {
                ADS_STATUS ads_status;
                ads_status = libnet_unjoin_connect_ads(mem_ctx, r);
@@ -2071,7 +2362,7 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                        return WERR_OK;
                }
        }
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */
 
        /* The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag really means 
           "disable".  */
@@ -2086,7 +2377,7 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                        }
                        return ntstatus_to_werror(status);
                }
-               
+
                r->out.disabled_machine_account = true;
        }
 
@@ -2122,6 +2413,17 @@ static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx,
                return WERR_SETUP_DOMAIN_CONTROLLER;
        }
 
+       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;
+               r->in.admin_account = admin_account;
+       }
+
        if (!secrets_init()) {
                libnet_unjoin_set_error_string(mem_ctx, r,
                        "Unable to open secrets database");