s4:libnet_join.c - always use LDB constants
[kai/samba.git] / source4 / libnet / libnet_join.c
index 70fcb4a894eac46bc86a1a6208f27c2fe2b0daf6..ea110392e43bf982a67ec41e29896cb3c23b52f1 100644 (file)
@@ -33,6 +33,7 @@
 #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:
@@ -132,23 +133,14 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        r_drsuapi_bind.in.bind_info = NULL;
        r_drsuapi_bind.out.bind_handle = &drsuapi_bind_handle;
 
-       status = dcerpc_drsuapi_DsBind(drsuapi_pipe, tmp_ctx, &r_drsuapi_bind);
+       status = dcerpc_drsuapi_DsBind_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_drsuapi_bind);
        if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsBind failed - %s", 
-                                                 dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
-                       talloc_free(tmp_ctx);
-                       return status;
-               } else {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsBind failed - %s", 
-                                                 nt_errstr(status));
-                       talloc_free(tmp_ctx);
-                       return status;
-               }
+               r->out.error_string
+                       = talloc_asprintf(r,
+                                         "dcerpc_drsuapi_DsBind failed - %s",
+                                         nt_errstr(status));
+               talloc_free(tmp_ctx);
+               return status;
        } else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) {
                r->out.error_string
                                = talloc_asprintf(r,
@@ -183,32 +175,22 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        }
 
        r_crack_names.out.ctr                   = talloc(r, union drsuapi_DsNameCtr);
-       r_crack_names.out.level_out             = talloc(r, int32_t);
+       r_crack_names.out.level_out             = talloc(r, uint32_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);
+       status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names);
        if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
-                                                 names[0].str,
-                                                 dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
-                       talloc_free(tmp_ctx);
-                       return status;
-               } else {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
-                                                 names[0].str,
-                                                 nt_errstr(status));
-                       talloc_free(tmp_ctx);
-                       return status;
-               }
+               r->out.error_string
+                       = talloc_asprintf(r,
+                                         "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s",
+                                         names[0].str,
+                                         nt_errstr(status));
+               talloc_free(tmp_ctx);
+               return status;
        } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
                r->out.error_string
                                = talloc_asprintf(r,
@@ -246,7 +228,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
 
        remote_ldb = ldb_wrap_connect(tmp_ctx, ctx->event_ctx, ctx->lp_ctx, 
                                      remote_ldb_url, 
-                                     NULL, ctx->cred, 0, NULL);
+                                     NULL, ctx->cred, 0);
        if (!remote_ldb) {
                r->out.error_string = NULL;
                talloc_free(tmp_ctx);
@@ -288,7 +270,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        msg->dn = res->msgs[0]->dn;
 
        {
-               int i;
+               unsigned int i;
                const char *service_principal_name[6];
                const char *dns_host_name = strlower_talloc(tmp_ctx, 
                                                            talloc_asprintf(tmp_ctx, 
@@ -316,7 +298,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                                return NT_STATUS_NO_MEMORY;
                        }
                        rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "servicePrincipalName", service_principal_name[i]);
-                       if (rtn == -1) {
+                       if (rtn != LDB_SUCCESS) {
                                r->out.error_string = NULL;
                                talloc_free(tmp_ctx);
                                return NT_STATUS_NO_MEMORY;
@@ -324,14 +306,14 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                }
 
                rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "dNSHostName", dns_host_name);
-               if (rtn == -1) {
+               if (rtn != LDB_SUCCESS) {
                        r->out.error_string = NULL;
                        talloc_free(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
-               rtn = samdb_replace(remote_ldb, tmp_ctx, msg);
-               if (rtn != 0) {
+               rtn = dsdb_replace(remote_ldb, msg, 0);
+               if (rtn != LDB_SUCCESS) {
                        r->out.error_string
                                = talloc_asprintf(r, 
                                                  "Failed to replace entries on %s", 
@@ -341,6 +323,38 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                }
        }
                                
+       msg = ldb_msg_new(tmp_ctx);
+       if (!msg) {
+               r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+       msg->dn = res->msgs[0]->dn;
+
+       rtn = ldb_msg_add_fmt(msg, "msDS-SupportedEncryptionTypes",
+                             "%lu",
+                             (long unsigned int)(ENC_CRC32 | ENC_RSA_MD5 |
+                                                 ENC_RC4_HMAC_MD5 |
+                                                 ENC_HMAC_SHA1_96_AES128 |
+                                                 ENC_HMAC_SHA1_96_AES256));
+       if (rtn != LDB_SUCCESS) {
+               r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       rtn = dsdb_replace(remote_ldb, msg, 0);
+       /* The remote server may not support this attribute, if it
+        * isn't a modern schema */
+       if (rtn != LDB_SUCCESS && rtn != LDB_ERR_NO_SUCH_ATTRIBUTE) {
+               r->out.error_string
+                       = talloc_asprintf(r,
+                                         "Failed to replace msDS-SupportedEncryptionType on %s",
+                                         ldb_dn_get_linearized(msg->dn));
+               talloc_free(tmp_ctx);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
        /* 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;
@@ -351,25 +365,15 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
+       status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names);
        if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
-                                                 r->in.domain_name, 
-                                                 dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
-                       talloc_free(tmp_ctx);
-                       return status;
-               } else {
-                       r->out.error_string
-                               = talloc_asprintf(r,
-                                                 "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
-                                                 r->in.domain_name, 
-                                                 nt_errstr(status));
-                       talloc_free(tmp_ctx);
-                       return status;
-               }
+               r->out.error_string
+                       = talloc_asprintf(r,
+                                         "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s",
+                                         r->in.domain_name,
+                                         nt_errstr(status));
+               talloc_free(tmp_ctx);
+               return status;
        } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
                r->out.error_string
                        = talloc_asprintf(r,
@@ -479,7 +483,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);
@@ -538,7 +542,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        sc.out.connect_handle = &p_handle;
 
        /* 2. do a samr_Connect to get a policy handle */
-       status = dcerpc_samr_Connect(samr_pipe, tmp_ctx, &sc);
+       status = dcerpc_samr_Connect_r(samr_pipe->binding_handle, tmp_ctx, &sc);
+       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) {
+               status = sc.out.result;
+       }
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_asprintf(mem_ctx,
                                                "samr_Connect failed: %s",
@@ -552,7 +559,7 @@ 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 */
+                       /* 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));
                }
@@ -568,7 +575,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                l.in.domain_name = &name;
                l.out.sid = &sid;
                
-               status = dcerpc_samr_LookupDomain(samr_pipe, tmp_ctx, &l);
+               status = dcerpc_samr_LookupDomain_r(samr_pipe->binding_handle, tmp_ctx, &l);
+               if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(l.out.result)) {
+                       status = l.out.result;
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        r->out.error_string = talloc_asprintf(mem_ctx,
                                                              "SAMR LookupDomain failed: %s",
@@ -587,7 +597,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        od.out.domain_handle = &d_handle;
 
        /* do a samr_OpenDomain to get a domain handle */
-       status = dcerpc_samr_OpenDomain(samr_pipe, tmp_ctx, &od);                       
+       status = dcerpc_samr_OpenDomain_r(samr_pipe->binding_handle, tmp_ctx, &od);
+       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) {
+               status = od.out.result;
+       }
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_asprintf(mem_ctx,
                                                      "samr_OpenDomain for [%s] failed: %s",
@@ -609,7 +622,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        cu.out.access_granted = &access_granted;
 
        /* do a samr_CreateUser2 to get an account handle, or an error */
-       cu_status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu);                   
+       cu_status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu);
+       if (NT_STATUS_IS_OK(cu_status) && !NT_STATUS_IS_OK(cu.out.result)) {
+               cu_status = cu.out.result;
+       }
        status = cu_status;
        if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
                /* prepare samr_LookupNames */
@@ -626,7 +642,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                ln.in.names[0].string = r->in.account_name;
                
                /* 5. do a samr_LookupNames to get the users rid */
-               status = dcerpc_samr_LookupNames(samr_pipe, tmp_ctx, &ln);
+               status = dcerpc_samr_LookupNames_r(samr_pipe->binding_handle, tmp_ctx, &ln);
+               if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) {
+                       status = ln.out.result;
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        r->out.error_string = talloc_asprintf(mem_ctx,
                                                "samr_LookupNames for [%s] failed: %s",
@@ -654,7 +673,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                ou.out.user_handle = u_handle;
                
                /* 6. do a samr_OpenUser to get a user handle */
-               status = dcerpc_samr_OpenUser(samr_pipe, tmp_ctx, &ou); 
+               status = dcerpc_samr_OpenUser_r(samr_pipe->binding_handle, tmp_ctx, &ou);
+               if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) {
+                       status = ou.out.result;
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        r->out.error_string = talloc_asprintf(mem_ctx,
                                                        "samr_OpenUser for [%s] failed: %s",
@@ -668,7 +690,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                        struct samr_DeleteUser d;
                        d.in.user_handle = u_handle;
                        d.out.user_handle = u_handle;
-                       status = dcerpc_samr_DeleteUser(samr_pipe, mem_ctx, &d);
+                       status = dcerpc_samr_DeleteUser_r(samr_pipe->binding_handle, mem_ctx, &d);
+                       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(d.out.result)) {
+                               status = d.out.result;
+                       }
                        if (!NT_STATUS_IS_OK(status)) {
                                r->out.error_string = talloc_asprintf(mem_ctx,
                                                                      "samr_DeleteUser (for recreate) of [%s] failed: %s",
@@ -681,7 +706,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
                        /* We want to recreate, so delete and another samr_CreateUser2 */
                        
                        /* &cu filled in above */
-                       status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu);                      
+                       status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu);
+                       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(cu.out.result)) {
+                               status = cu.out.result;
+                       }
                        if (!NT_STATUS_IS_OK(status)) {
                                r->out.error_string = talloc_asprintf(mem_ctx,
                                                                      "samr_CreateUser2 (recreate) for [%s] failed: %s",
@@ -703,7 +731,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        qui.in.level = 16;
        qui.out.info = &uinfo;
        
-       status = dcerpc_samr_QueryUserInfo(samr_pipe, tmp_ctx, &qui);
+       status = dcerpc_samr_QueryUserInfo_r(samr_pipe->binding_handle, tmp_ctx, &qui);
+       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(qui.out.result)) {
+               status = qui.out.result;
+       }
        if (!NT_STATUS_IS_OK(status)) {
                r->out.error_string = talloc_asprintf(mem_ctx,
                                                "samr_QueryUserInfo for [%s] failed: %s",
@@ -788,14 +819,17 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        pwp.in.user_handle = u_handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(samr_pipe, tmp_ctx, &pwp);                           
+       status = dcerpc_samr_GetUserPwInfo_r(samr_pipe->binding_handle, tmp_ctx, &pwp);
+       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pwp.out.result)) {
+               status = pwp.out.result;
+       }
        if (NT_STATUS_IS_OK(status)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        
        /* Grab a password of that minimum length */
        
-       password_str = generate_random_str(tmp_ctx, MAX(8, policy_min_pw_len)); 
+       password_str = generate_random_password(tmp_ctx, MAX(8, policy_min_pw_len), 255);
 
        /* set full_name and reset flags */
        ZERO_STRUCT(u_info21);
@@ -839,7 +873,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;
@@ -860,254 +894,6 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        return status;
 }
 
-NTSTATUS libnet_set_join_secrets(struct libnet_context *ctx, 
-                                TALLOC_CTX *mem_ctx, 
-                                struct libnet_set_join_secrets *r)
-{
-       TALLOC_CTX *tmp_mem;
-       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
-       };
-
-       tmp_mem = talloc_new(mem_ctx);
-       if (!tmp_mem) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* Open the secrets database */
-       ldb = secrets_db_connect(tmp_mem, ctx->event_ctx, ctx->lp_ctx);
-       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;
-       }
-
-       /*
-        * 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", r->in.domain_name)) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "flatname", r->in.domain_name);
-       if (rtn == -1) {
-               r->out.error_string = NULL;
-               talloc_free(tmp_mem);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (r->in.realm) {
-               rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "realm", r->in.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", r->in.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", r->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 (r->in.kvno) {
-               rtn = samdb_msg_add_uint(ldb, tmp_mem, msg, "msDS-KeyVersionNumber",
-                                        r->in.kvno);
-               if (rtn == -1) {
-                       r->out.error_string = NULL;
-                       talloc_free(tmp_mem);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       if (r->in.domain_sid) {
-               rtn = samdb_msg_add_dom_sid(ldb, tmp_mem, msg, "objectSid",
-                                           r->in.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))",
-                          r->in.domain_name, r->in.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", 
-                                         r->in.domain_name, r->in.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_main_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", r->in.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", r->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_main_keytab = ldb_msg_find_ldb_val(msgs[0], "krb5Keytab");
-               if (krb5_main_keytab) {
-                       rtn = samdb_msg_set_value(ldb, tmp_mem, msg,
-                                       "krb5Keytab", krb5_main_keytab);
-                       if (rtn == -1) {
-                               r->out.error_string = NULL;
-                               talloc_free(tmp_mem);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-       }
-
-       /* create the secret */
-       ret = ldb_add(ldb, msg);
-       if (ret != 0) {
-               r->out.error_string = talloc_asprintf(mem_ctx, "Failed to create secret record %s", 
-                                                     ldb_dn_get_linearized(msg->dn));
-               talloc_free(tmp_mem);
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
-       return NT_STATUS_OK;
-}
-
 static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, 
                                           TALLOC_CTX *mem_ctx, 
                                           struct libnet_Join *r)
@@ -1115,11 +901,12 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        NTSTATUS status;
        TALLOC_CTX *tmp_mem;
        struct libnet_JoinDomain *r2;
-       struct libnet_set_join_secrets *r3;
+       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);
@@ -1147,7 +934,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(ctx->lp_ctx));
+               netbios_name = talloc_strdup(tmp_mem, lp_netbios_name(ctx->lp_ctx));
                if (!netbios_name) {
                        r->out.error_string = NULL;
                        talloc_free(tmp_mem);
@@ -1179,26 +966,25 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
                return status;
        }
 
-       r3 = talloc(tmp_mem, struct libnet_set_join_secrets);
-       if (!r3) {
+       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;
        }
        
-       ZERO_STRUCTP(r3);
-       r3->in.domain_name = r2->out.domain_name;
-       r3->in.realm = r2->out.realm;
-       r3->in.account_name = account_name;
-       r3->in.netbios_name = netbios_name;
-       r3->in.join_type = r->in.join_type;
-       r3->in.join_password = r2->out.join_password;
-       r3->in.kvno = r2->out.kvno;
-       r3->in.domain_sid = r2->out.domain_sid;
+       ZERO_STRUCTP(set_secrets);
+       set_secrets->domain_name = r2->out.domain_name;
+       set_secrets->realm = r2->out.realm;
+       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 = libnet_set_join_secrets(ctx, r3, r3);
+       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, r3->out.error_string);
+               r->out.error_string = talloc_steal(mem_ctx, error_string);
                talloc_free(tmp_mem);
                return status;
        }
@@ -1206,11 +992,11 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        /* 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;
 }
@@ -1223,6 +1009,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;
        }