More spelling fixes across source4/
[samba.git] / source4 / libnet / libnet_join.c
index cecf07ed4e3c1692e14a94f889d552b347d4afbc..84d3250c3168a2019fe04d57855275c7f030b781 100644 (file)
 #include "lib/ldb/include/ldb_errors.h"
 #include "param/secrets.h"
 #include "dsdb/samdb/samdb.h"
-#include "db_wrap.h"
+#include "ldb_wrap.h"
+#include "../lib/util/util_ldb.h"
 #include "libcli/security/security.h"
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_krb5.h"
 #include "librpc/gen_ndr/ndr_samr_c.h"
+#include "param/param.h"
+#include "param/provision.h"
 
 /*
  * complete a domain join, when joining to a AD domain:
@@ -110,9 +113,10 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        status = dcerpc_pipe_connect_b(tmp_ctx, 
                                       &drsuapi_pipe,
                                       drsuapi_binding,
-                                      &dcerpc_table_drsuapi,
+                                      &ndr_table_drsuapi,
                                       ctx->cred, 
-                                      ctx->event_ctx);
+                                      ctx->event_ctx,
+                                      ctx->lp_ctx);
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_asprintf(r,
                                        "Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s",
@@ -159,13 +163,19 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        ZERO_STRUCT(r_crack_names);
        r_crack_names.in.bind_handle            = &drsuapi_bind_handle;
        r_crack_names.in.level                  = 1;
-       r_crack_names.in.req.req1.codepage      = 1252; /* western european */
-       r_crack_names.in.req.req1.language      = 0x00000407; /* german */
-       r_crack_names.in.req.req1.count         = 1;
-       r_crack_names.in.req.req1.names         = names;
-       r_crack_names.in.req.req1.format_flags  = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
-       r_crack_names.in.req.req1.format_offered= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
-       r_crack_names.in.req.req1.format_desired= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+       r_crack_names.in.req                    = talloc(r, union drsuapi_DsNameRequest);
+       if (!r_crack_names.in.req) {
+               r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+       r_crack_names.in.req->req1.codepage     = 1252; /* western european */
+       r_crack_names.in.req->req1.language     = 0x00000407; /* german */
+       r_crack_names.in.req->req1.count        = 1;
+       r_crack_names.in.req->req1.names        = names;
+       r_crack_names.in.req->req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
+       r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
+       r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
        names[0].str = dom_sid_string(tmp_ctx, r->out.account_sid);
        if (!names[0].str) {
                r->out.error_string = NULL;
@@ -173,6 +183,14 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                return NT_STATUS_NO_MEMORY;
        }
 
+       r_crack_names.out.ctr                   = talloc(r, union drsuapi_DsNameCtr);
+       r_crack_names.out.level_out             = talloc(r, int32_t);
+       if (!r_crack_names.out.ctr || !r_crack_names.out.level_out) {
+               r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
@@ -198,24 +216,24 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                                                  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
-       } else if (r_crack_names.out.level != 1 
-                  || !r_crack_names.out.ctr.ctr1 
-                  || r_crack_names.out.ctr.ctr1->count != 1) {
+       } else if (*r_crack_names.out.level_out != 1
+                  || !r_crack_names.out.ctr->ctr1
+                  || r_crack_names.out.ctr->ctr1->count != 1) {
                r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
                talloc_free(tmp_ctx);
                return NT_STATUS_INVALID_PARAMETER;
-       } else if (r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr.ctr1->array[0].status);
+       } else if (r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr->ctr1->array[0].status);
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
-       } else if (r_crack_names.out.ctr.ctr1->array[0].result_name == NULL) {
+       } else if (r_crack_names.out.ctr->ctr1->array[0].result_name == NULL) {
                r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name");
                talloc_free(tmp_ctx);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Store the DN of our machine account. */
-       account_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name;
+       account_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;
 
        /* Now we know the user's DN, open with LDAP, read and modify a few things */
 
@@ -227,8 +245,9 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                return NT_STATUS_NO_MEMORY;
        }
 
-       remote_ldb = ldb_wrap_connect(tmp_ctx, remote_ldb_url, 
-                                     NULL, ctx->cred, 0, NULL);
+       remote_ldb = ldb_wrap_connect(tmp_ctx, ctx->event_ctx, ctx->lp_ctx, 
+                                     remote_ldb_url, 
+                                     NULL, ctx->cred, 0);
        if (!remote_ldb) {
                r->out.error_string = NULL;
                talloc_free(tmp_ctx);
@@ -244,8 +263,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        }
 
        /* search for the user's record */
-       ret = ldb_search(remote_ldb, account_dn, LDB_SCOPE_BASE, 
-                        NULL, attrs, &res);
+       ret = ldb_search(remote_ldb, tmp_ctx, &res,
+                        account_dn, LDB_SCOPE_BASE, attrs, NULL);
        if (ret != LDB_SUCCESS) {
                r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s",
                                                      account_dn_str, ldb_errstring(remote_ldb));
@@ -253,8 +272,6 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       talloc_steal(tmp_ctx, res);
-
        if (res->count != 1) {
                r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries",
                                                      account_dn_str, res->count);
@@ -314,7 +331,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                        return NT_STATUS_NO_MEMORY;
                }
 
-               rtn = samdb_replace(remote_ldb, tmp_ctx, msg);
+               rtn = dsdb_replace(remote_ldb, msg, 0);
                if (rtn != 0) {
                        r->out.error_string
                                = talloc_asprintf(r, 
@@ -326,8 +343,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        }
                                
        /* DsCrackNames to find out the DN of the domain. */
-       r_crack_names.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r_crack_names.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+       r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
+       r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
        names[0].str = talloc_asprintf(tmp_ctx, "%s\\", r->out.domain_name);
        if (!names[0].str) {
                r->out.error_string = NULL;
@@ -360,11 +377,11 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                                          "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
-       } else if (r_crack_names.out.level != 1 
-                  || !r_crack_names.out.ctr.ctr1 
-                  || r_crack_names.out.ctr.ctr1->count != 1
-                  || !r_crack_names.out.ctr.ctr1->array[0].result_name           
-                  || r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+       } else if (*r_crack_names.out.level_out != 1
+                  || !r_crack_names.out.ctr->ctr1
+                  || r_crack_names.out.ctr->ctr1->count != 1
+                  || !r_crack_names.out.ctr->ctr1->array[0].result_name
+                  || r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
                r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
@@ -375,8 +392,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        talloc_steal(r, account_dn_str);
 
        /* Store the domain DN. */
-       r->out.domain_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name;
-       talloc_steal(r, r_crack_names.out.ctr.ctr1->array[0].result_name);
+       r->out.domain_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;
+       talloc_steal(r, r_crack_names.out.ctr->ctr1->array[0].result_name);
 
        /* Store the KVNO of the account, critical for some kerberos
         * operations */
@@ -386,7 +403,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        r->out.account_guid = samdb_result_guid(res->msgs[0], "objectGUID");
 
        if (r->in.acct_type == ACB_SVRTRUST) {
-               status = libnet_JoinSite(remote_ldb, r);
+               status = libnet_JoinSite(ctx, remote_ldb, r);
        }
        talloc_free(tmp_ctx);
 
@@ -428,13 +445,16 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        struct samr_OpenDomain od;
        struct policy_handle d_handle;
        struct samr_LookupNames ln;
+       struct samr_Ids rids, types;
        struct samr_OpenUser ou;
        struct samr_CreateUser2 cu;
        struct policy_handle *u_handle = NULL;
        struct samr_QueryUserInfo qui;
+       union samr_UserInfo *uinfo;
        struct samr_UserInfo21 u_info21;
        union libnet_SetPassword r2;
        struct samr_GetUserPwInfo pwp;
+       struct samr_PwInfo info;
        struct lsa_String samr_account_name;
        
        uint32_t acct_flags, old_acct_flags;
@@ -460,7 +480,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                return NT_STATUS_NO_MEMORY;
        }
        
-       connect_with_info = talloc(tmp_ctx, struct libnet_RpcConnect);
+       connect_with_info = talloc_zero(tmp_ctx, struct libnet_RpcConnect);
        if (!connect_with_info) {
                r->out.error_string = NULL;
                talloc_free(tmp_ctx);
@@ -479,7 +499,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        /* This level makes a connection to the LSA pipe on the way,
         * to get some useful bits of information about the domain */
        connect_with_info->level              = LIBNET_RPC_CONNECT_DC_INFO;
-       connect_with_info->in.dcerpc_iface    = &dcerpc_table_samr;
+       connect_with_info->in.dcerpc_iface    = &ndr_table_samr;
 
        /*
          establish the SAMR connection
@@ -503,7 +523,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
 
        status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe,
                                  connect_with_info->out.dcerpc_pipe->binding, 
-                                 &dcerpc_table_samr, ctx->cred);
+                                 &ndr_table_samr, ctx->cred, ctx->lp_ctx);
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_asprintf(mem_ctx,
                                                "SAMR bind failed: %s",
@@ -533,9 +553,9 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
                        connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name);
                } else {
-                       /* Bugger, we just lost our way to automaticly find the domain name */
-                       connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup());
-                       connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm());
+                       /* Bugger, we just lost our way to automatically find the domain name */
+                       connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup(ctx->lp_ctx));
+                       connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm(ctx->lp_ctx));
                }
        }
 
@@ -543,9 +563,11 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        if (!connect_with_info->out.domain_sid) {
                struct lsa_String name;
                struct samr_LookupDomain l;
+               struct dom_sid2 *sid = NULL;
                name.string = connect_with_info->out.domain_name;
                l.in.connect_handle = &p_handle;
                l.in.domain_name = &name;
+               l.out.sid = &sid;
                
                status = dcerpc_samr_LookupDomain(samr_pipe, tmp_ctx, &l);
                if (!NT_STATUS_IS_OK(status)) {
@@ -555,7 +577,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                        talloc_free(tmp_ctx);
                        return status;
                }
-               connect_with_info->out.domain_sid = l.out.sid;
+               connect_with_info->out.domain_sid = *l.out.sid;
        }
 
        /* prepare samr_OpenDomain */
@@ -595,6 +617,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                ln.in.domain_handle = &d_handle;
                ln.in.num_names = 1;
                ln.in.names = talloc_array(tmp_ctx, struct lsa_String, 1);
+               ln.out.rids = &rids;
+               ln.out.types = &types;
                if (!ln.in.names) {
                        r->out.error_string = NULL;
                        talloc_free(tmp_ctx);
@@ -614,10 +638,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                }
                
                /* check if we got one RID for the user */
-               if (ln.out.rids.count != 1) {
+               if (ln.out.rids->count != 1) {
                        r->out.error_string = talloc_asprintf(mem_ctx,
                                                              "samr_LookupNames for [%s] returns %d RIDs",
-                                                             r->in.account_name, ln.out.rids.count);
+                                                             r->in.account_name, ln.out.rids->count);
                        talloc_free(tmp_ctx);
                        return NT_STATUS_INVALID_PARAMETER;
                }
@@ -626,7 +650,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                ZERO_STRUCTP(u_handle);
                ou.in.domain_handle = &d_handle;
                ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-               ou.in.rid = ln.out.rids.ids[0];
+               ou.in.rid = ln.out.rids->ids[0];
                rid = ou.in.rid;
                ou.out.user_handle = u_handle;
                
@@ -678,6 +702,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        /* prepare samr_QueryUserInfo (get flags) */
        qui.in.user_handle = u_handle;
        qui.in.level = 16;
+       qui.out.info = &uinfo;
        
        status = dcerpc_samr_QueryUserInfo(samr_pipe, tmp_ctx, &qui);
        if (!NT_STATUS_IS_OK(status)) {
@@ -689,7 +714,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                return status;
        }
        
-       if (!qui.out.info) {
+       if (!uinfo) {
                status = NT_STATUS_INVALID_PARAMETER;
                r->out.error_string
                        = talloc_asprintf(mem_ctx,
@@ -699,7 +724,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                return status;
        }
 
-       old_acct_flags = (qui.out.info->info16.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST | ACB_DOMTRUST));
+       old_acct_flags = (uinfo->info16.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST | ACB_DOMTRUST));
        /* Possibly bail if the account is of the wrong type */
        if (old_acct_flags
            != r->in.acct_type) {
@@ -755,17 +780,18 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                        return NT_STATUS_USER_EXISTS;
                }
        } else {
-               acct_flags = qui.out.info->info16.acct_flags;
+               acct_flags = uinfo->info16.acct_flags;
        }
        
        acct_flags = (acct_flags & ~(ACB_DISABLED|ACB_PWNOTREQ));
 
        /* Find out what password policy this user has */
        pwp.in.user_handle = u_handle;
+       pwp.out.info = &info;
 
        status = dcerpc_samr_GetUserPwInfo(samr_pipe, tmp_ctx, &pwp);                           
        if (NT_STATUS_IS_OK(status)) {
-               policy_min_pw_len = pwp.out.info.min_password_length;
+               policy_min_pw_len = pwp.out.info->min_password_length;
        }
        
        /* Grab a password of that minimum length */
@@ -814,7 +840,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        r->out.realm = connect_with_info->out.realm;
        talloc_steal(mem_ctx, r->out.realm);
        r->out.samr_pipe = samr_pipe;
-       talloc_steal(mem_ctx, samr_pipe);
+       talloc_reparent(tmp_ctx, mem_ctx, samr_pipe);
        r->out.samr_binding = samr_pipe->binding;
        talloc_steal(mem_ctx, r->out.samr_binding);
        r->out.user_handle = u_handle;
@@ -842,24 +868,12 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        NTSTATUS status;
        TALLOC_CTX *tmp_mem;
        struct libnet_JoinDomain *r2;
-       int ret, rtn;
-       struct ldb_context *ldb;
-       struct ldb_dn *base_dn;
-       struct ldb_message **msgs, *msg;
-       const char *sct;
-       const char * const attrs[] = {
-               "whenChanged",
-               "secret",
-               "priorSecret",
-               "priorChanged",
-               "krb5Keytab",
-               "privateKeytab",
-               NULL
-       };
+       struct provision_store_self_join_settings *set_secrets;
        uint32_t acct_type = 0;
        const char *account_name;
        const char *netbios_name;
-       
+       const char *error_string;
+
        r->out.error_string = NULL;
 
        tmp_mem = talloc_new(mem_ctx);
@@ -887,7 +901,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        if (r->in.netbios_name != NULL) {
                netbios_name = r->in.netbios_name;
        } else {
-               netbios_name = talloc_reference(tmp_mem, lp_netbios_name());
+               netbios_name = talloc_strdup(tmp_mem, lp_netbios_name(ctx->lp_ctx));
                if (!netbios_name) {
                        r->out.error_string = NULL;
                        talloc_free(tmp_mem);
@@ -902,19 +916,6 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
                return NT_STATUS_NO_MEMORY;
        }
        
-       /*
-        * Local secrets are stored in secrets.ldb 
-        * open it to make sure we can write the info into it after the join
-        */
-       ldb = secrets_db_connect(tmp_mem);
-       if (!ldb) {
-               r->out.error_string
-                       = talloc_asprintf(mem_ctx, 
-                                         "Could not open secrets database");
-               talloc_free(tmp_mem);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
        /*
         * join the domain
         */
@@ -924,231 +925,46 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        r2->in.netbios_name     = netbios_name;
        r2->in.level            = LIBNET_JOINDOMAIN_AUTOMATIC;
        r2->in.acct_type        = acct_type;
-       r2->in.recreate_account = False;
+       r2->in.recreate_account = false;
        status = libnet_JoinDomain(ctx, r2, r2);
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_steal(mem_ctx, r2->out.error_string);
                talloc_free(tmp_mem);
                return status;
        }
-       
-       /*
-        * now prepare the record for secrets.ldb
-        */
-       sct = talloc_asprintf(tmp_mem, "%d", r->in.join_type); 
-       if (!sct) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       msg = ldb_msg_new(tmp_mem);
-       if (!msg) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       base_dn = ldb_dn_new(tmp_mem, ldb, "cn=Primary Domains");
-       if (!base_dn) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
 
-       msg->dn = ldb_dn_copy(tmp_mem, base_dn);
-       if ( ! ldb_dn_add_child_fmt(msg->dn, "flatname=%s", r2->out.domain_name)) {
+       set_secrets = talloc(tmp_mem, struct provision_store_self_join_settings);
+       if (!set_secrets) {
                r->out.error_string = NULL;
                talloc_free(tmp_mem);
                return NT_STATUS_NO_MEMORY;
        }
        
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "flatname", r2->out.domain_name);
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (r2->out.realm) {
-               rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "realm", r2->out.realm);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secret", r2->out.join_password);
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "samAccountName", r2->in.account_name);
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secureChannelType", sct);
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (r2->out.kvno) {
-               rtn = samdb_msg_add_uint(ldb, tmp_mem, msg, "msDS-KeyVersionNumber",
-                                        r2->out.kvno);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       if (r2->out.domain_sid) {
-               rtn = samdb_msg_add_dom_sid(ldb, tmp_mem, msg, "objectSid",
-                                           r2->out.domain_sid);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       /* 
-        * search for the secret record
-        * - remove the records we find
-        * - and fetch the old secret and store it under priorSecret
-        */
-       ret = gendb_search(ldb,
-                          tmp_mem, base_dn,
-                          &msgs, attrs,
-                          "(|" SECRETS_PRIMARY_DOMAIN_FILTER "(realm=%s))",
-                          r2->out.domain_name, r2->out.realm);
-       if (ret == 0) {
-               rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secretsKeytab", "secrets.keytab");
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       } else if (ret == -1) {
-               r->out.error_string
-                       = talloc_asprintf(mem_ctx, 
-                                         "Search for domain: %s and realm: %s failed: %s", 
-                                         r2->out.domain_name, r2->out.realm, ldb_errstring(ldb));
-               talloc_free(tmp_mem);
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       } else {
-               const struct ldb_val *private_keytab;
-               const struct ldb_val *krb5_keytab;
-               const struct ldb_val *prior_secret;
-               const struct ldb_val *prior_modified_time;
-               int i;
-
-               for (i = 0; i < ret; i++) {
-                       ldb_delete(ldb, msgs[i]->dn);
-               }
-
-               prior_secret = ldb_msg_find_ldb_val(msgs[0], "secret");
-               if (prior_secret) {
-                       rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorSecret", prior_secret);
-                       if (rtn == -1) {
-                               r->out.error_string = NULL;
-                               talloc_free(tmp_mem);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-               rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secret", r2->out.join_password);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               prior_modified_time = ldb_msg_find_ldb_val(msgs[0], 
-                                                          "whenChanged");
-               if (prior_modified_time) {
-                       rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorWhenChanged", 
-                                                 prior_modified_time);
-                       if (rtn == -1) {
-                               r->out.error_string = NULL;
-                               talloc_free(tmp_mem);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-
-               rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "samAccountName", r2->in.account_name);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secureChannelType", sct);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               /* We will want to keep the keytab names */
-               private_keytab = ldb_msg_find_ldb_val(msgs[0], "privateKeytab");
-               if (private_keytab) {
-                       rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "privateKeytab", private_keytab);
-                       if (rtn == -1) {
-                               r->out.error_string = NULL;
-                               talloc_free(tmp_mem);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-               krb5_keytab = ldb_msg_find_ldb_val(msgs[0], "krb5Keytab");
-               if (krb5_keytab) {
-                       rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "krb5Keytab", krb5_keytab);
-                       if (rtn == -1) {
-                               r->out.error_string = NULL;
-                               talloc_free(tmp_mem);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-       }
-
-       /* create the secret */
-       ret = samdb_add(ldb, tmp_mem, msg);
-       if (ret != 0) {
-               r->out.error_string = talloc_asprintf(mem_ctx, "Failed to create secret record %s", 
-                                                     ldb_dn_get_linearized(msg->dn));
+       ZERO_STRUCTP(set_secrets);
+       set_secrets->domain_name = r2->out.domain_name;
+       set_secrets->realm = r2->out.realm;
+       set_secrets->account_name = account_name;
+       set_secrets->netbios_name = netbios_name;
+       set_secrets->secure_channel_type = r->in.join_type;
+       set_secrets->machine_password = r2->out.join_password;
+       set_secrets->key_version_number = r2->out.kvno;
+       set_secrets->domain_sid = r2->out.domain_sid;
+       
+       status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
+       if (!NT_STATUS_IS_OK(status)) {
+               r->out.error_string = talloc_steal(mem_ctx, error_string);
                talloc_free(tmp_mem);
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               return status;
        }
 
        /* move all out parameter to the callers TALLOC_CTX */
        r->out.error_string     = NULL;
        r->out.join_password    = r2->out.join_password;
-       talloc_steal(mem_ctx, r2->out.join_password);
+       talloc_reparent(r2, mem_ctx, r2->out.join_password);
        r->out.domain_sid       = r2->out.domain_sid;
-       talloc_steal(mem_ctx, r2->out.domain_sid);
+       talloc_reparent(r2, mem_ctx, r2->out.domain_sid);
        r->out.domain_name      = r2->out.domain_name;
-       talloc_steal(mem_ctx, r2->out.domain_name);
+       talloc_reparent(r2, mem_ctx, r2->out.domain_name);
        talloc_free(tmp_mem);
        return NT_STATUS_OK;
 }
@@ -1161,6 +977,8 @@ NTSTATUS libnet_Join(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct lib
                case SEC_CHAN_BDC:
                        return libnet_Join_primary_domain(ctx, mem_ctx, r);
                case SEC_CHAN_DOMAIN:
+               case SEC_CHAN_DNS_DOMAIN:
+               case SEC_CHAN_NULL:
                        break;
        }